Skip to content

Commit

Permalink
Add support for SwiftUI localization using BartyCrouch
Browse files Browse the repository at this point in the history
  • Loading branch information
tmolitor-stud-tu committed Nov 8, 2022
1 parent e0c882d commit 6fcdcb6
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 19 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/beta.build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ jobs:
run: git fetch --tags
- name: Checkout submodules
run: git submodule update -f --init --remote
- name: Update translations
run: |
chmod +x ./scripts/updateLocalization.sh
./scripts/updateLocalization.sh BUILDSERVER
- name: Get last build tag and increment it
run: |
oldBuildNumber=$(git tag --sort="v:refname" |grep "Build_iOS" | tail -n1 | sed 's/Build_iOS_//g')
Expand All @@ -50,6 +46,11 @@ jobs:
run: ./scripts/build.sh
- name: validate ios app
run: xcrun altool --validate-app --file ./Monal/build/ipa/Monal.ipa --type ios --asc-provider S8D843U34Y -u "$(cat /Users/ci/apple_connect_upload_mail.txt)" -p "$(cat /Users/ci/apple_connect_upload_secret.txt)"
- name: Update translations
run: |
chmod +x ./scripts/updateLocalization.sh
chmod +x ./scripts/xliff_extractor.py
./scripts/updateLocalization.sh BUILDSERVER
- name: push tag to beta repo
run: |
buildNumber=$(git tag --sort="v:refname" |grep "Build_iOS" | tail -n1 | sed 's/Build_iOS_//g')
Expand Down
2 changes: 1 addition & 1 deletion Monal/.bartycrouch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ plistArguments = true

[update.normalize]
paths = ["."]
sourceLocale = "en"
sourceLocale = "base"
harmonizeWithSource = true
sortByKeys = true

Expand Down
2 changes: 2 additions & 0 deletions Monal/Classes/SwiftuiHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ typealias monal_id_block_t = @convention(block) (AnyObject?) -> Void;
let monalGreen = Color(UIColor(red:128.0/255, green:203.0/255, blue:182.0/255, alpha:1.0));
let monalDarkGreen = Color(UIColor(red:20.0/255, green:138.0/255, blue:103.0/255, alpha:1.0));

let swiftuiTranslationDummyString = Text("Dummy string to test SwiftUI translation support.")

class SheetDismisserProtocol: ObservableObject {
weak var host: UIHostingController<AnyView>? = nil
func dismiss() {
Expand Down
59 changes: 45 additions & 14 deletions scripts/updateLocalization.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,68 @@ git submodule update --init --recursive --remote
git reset --hard origin/main
)

# extract xliff file (has to be run multiple times, even if no error occured, don't ask me why)
# we use grep here to test for a dummy string to detect if our run succeeded
if [ -e localization.tmp ]; then
rm -rf localization.tmp
fi
x=$((1))
while [[ $x < 8 ]]; do
echo "RUN $x..."
while ! xcrun xcodebuild -exportLocalizations -localizationPath localization.tmp -exportLanguage base SWIFT_EMIT_LOC_STRINGS=NO; do
echo "ERROR, TRYING AGAIN..."
done
if grep -q 'Dummy string to test SwiftUI translation support.' "localization.tmp/base.xcloc/Localized Contents/base.xliff"; then
echo "SUCCESS!"
break
fi
x=$((x+1))
done
rm -rf *A\ Document\ Being\ Saved\ By\ xcodebuild*
if [[ $x == 8 ]]; then
echo "Could not extract dummy string!"
exit 1
fi

# Run bartycrouch
# https://github.com/Flinesoft/BartyCrouch#exclude-specific-views--nslocalizedstrings-from-localization
if which bartycrouch > /dev/null; then
# extract additional strings from xliff file and add them to our strings file (bartycrouch will remove duplicates later on)
../scripts/xliff_extractor.py -x "localization.tmp/base.xcloc/Localized Contents/base.xliff"
# update normally using bartycrouch and use it to sync our SwiftUI translations from base language to all other languages
bartycrouch update -x
bartycrouch lint -x
# clean up all files
for folder in "localization/external" "shareSheet-iOS/localization/external"; do
for file in $folder/*.lproj/*.strings; do
# Remove empty lines
sed -i '' '/^$/d' $file
# Remove default comments that are not supported by weblate
sed -i '' '/^\/\* No comment provided by engineer\. \*\/$/d' $file
# Fix empty RHS
sed -E -i '' 's|^(.*) = "";$|\1 = \1;|' $file
done
done
# lint everything now
bartycrouch lint -x -w
else
echo "warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch"
exit 1
fi

if [ -e localization.tmp ]; then
rm -rf localization.tmp
fi

for folder in "localization/external" "shareSheet-iOS/localization/external"; do
for file in $folder/*.lproj/*.strings; do
# Remove empty lines
sed -i '' '/^$/d' $file
# Remove default comments that are not supported by weblate
sed -i '' '/^\/\* No comment provided by engineer\. \*\/$/d' $file
# Fix empty RHS
sed -E -i '' 's|^(.*) = "";$|\1 = \1;|' $file
done

#subshell to not leak from "cd $folder"
(
cd $folder
echo "Diff of $folder:"
git diff
git diff || true
if [[ $1 != "NOCOMMIT" ]]; then
git add -u
# empty commits should not abort this script
set +e
git commit -m "Updated translations via BartyCrouch"
set -e
git commit -m "Updated translations via BartyCrouch xliff extractor" || true
git log -n 2
git remote --verbose
git push
Expand Down
53 changes: 53 additions & 0 deletions scripts/xliff_extractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import os
import sys
import argparse
import re
import logging
import xml.etree.ElementTree as ElementTree

ns = {"def": "urn:oasis:names:tc:xliff:document:1.2"}
regex = re.compile('^"(.*)" = "(.*)";$')

logging.basicConfig(level=logging.DEBUG, stream=sys.stderr, format="%(asctime)s [%(levelname)-7s] %(module)s: %(message)s")
logger = logging.getLogger("__main__")

parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description="XLIFF to Strings file converter.")
parser.add_argument("-x", "--xliff", type=str, required=True, metavar='FILE', help="XLIFF file to read")
args = parser.parse_args()

preexisting = 0
duplicates = 0
added = 0
logger.info("Loading XLIFF file at '%s'...", args.xliff)
xliff = ElementTree.parse(args.xliff)
for file in xliff.findall("./def:file", ns):
path = file.attrib["original"]
if os.path.exists(path) and path[-8:] == ".strings":
logger.info("Reading strings data for '%s'...", path)
with open(path) as stringsFile:
strings = {}
for line in stringsFile:
parts = regex.search(line.strip())
if not parts and len(line.strip()) > 0:
logger.debug("Not parsable, must be comment: %s", line.strip())
elif parts:
strings[parts.group(1)] = True
if parts.group(1) != parts.group(2):
logger.warning("Strings LHS and RHS don't match: '%s' != '%s'!", parts.group(1), parts.group(2))
preexisting = len(strings)
logger.info("Adding missing strings data to '%s'...", path)
with open(path, mode="a+", encoding="utf-8") as output:
for unit in file.findall("./def:body/def:trans-unit", ns):
string = unit.attrib["id"].replace("\n", "\\n")
if string not in strings:
comment = "No comment provided by engineer."
if len(unit.find("./def:note", ns).text):
comment = unit.find("./def:note", ns).text.replace("\n", "\\n")
logger.debug("Adding new string (%s): %s", comment, string)
output.write("/* %s */\n" % comment)
output.write("\"%s\" = \"%s\";\n\n" % (string, string))
added += 1
else:
duplicates += 1
logger.info("Done, preexisting: %d, duplicates: %d, added: %d", preexisting, duplicates, added)

0 comments on commit 6fcdcb6

Please sign in to comment.