DD 56: Weblate integration ########################## Summary ======= We are using `Weblate `__ to translate string in all software components. Weblate should be able to read which strings needs to be translated and return a translated version of the string for all the languages supported. Motivation ========== Every development ecosystem has it's own i18n framework. * Android has strings.xml * Apple has Localizable.strings but it's deprecated * We are using gettext PO as default There is no standard file format in iOS, the current suggested format is not supported by Weblate and looks like it's never going to be a open documentation about it: from `Apple developer forum `__ String Catalogs store an entire string table in a single JSON file, even if there are a large number of keys and languages. If this ends up presenting a problem (with Xcode's performance, for example), please send some feedback our way. As for the specifics of the JSON format itself, we have not published documentation because it is primarily intended to be read/written by Xcode. If you do end up writing your own parser for this format, please be aware that Xcode reserves the right to change it. What we are doing right now --------------------------- How strings are generated: *Android*: Defines a key (like "send_deposit_amount_effective" or "amount_effective"), this key has a default English translation in **strings.xml** and some other langs in **strings-{lang}.xml**. *iOS*: Uses the English text in the source code, or can also use a key. It has just one file with translations, **Localizable.xcstrings**. *SPA*: It has the English string enclosed with i18n reference and all those strings ends up in a file **src/i18n/strings.ts** which maps the English sentence with a translated phrase. (the english sentence is used as a key) For the integration in to weblate: *Android*: Weblate just takes **strings.xml** and **strings-{lang}.xml**, creates a list of all strings to be translated and once you add new value for untranslated string or change an existing one it modifies the correct file and commit with the new XML. The project will automatically take this values. *iOS*: No integration has been found. *SPA*: The **strings.ts** file is not recognized by Weblate, so we generate **.po** files which are supported by weblate. We have a script (pogen) that parses all the source code and generate **.po** files, PO files are understood by Weblate and it will appear in the webapp to be translated. Once the translator change some strings the PO files are updated with the translations. When the changes are push into the repo, the developer can run a second script (pogen) to sync the **.po** files with the **strings.ts**. Once in the **strings.ts** file the app can show it in the UI. Requirements ============ 1. We should integrate weblate and iOS development 2. Translator should not translate 2 strings twice: if we can, we should reuse strings between apps 3. It should be clear wether we need to define a new string or add more context to the current strings 4. Stick to the `supported formats `__ Proposed Solution ================= What we need to do to support iOS --------------------------------- We should move into something more like what we are doing with the SPA since we don't have full support for **Localizable.xcstrings** and this file is kind of the same as **strings.ts** (one big json with the mappings). That will mean: 1. dev code, code, code (adding new strings to be translated, removing some other strings) 2. dev run script to sync **Localizable.xcstrings** with **file-that-weblate-understands.po** 3. translators translate and push changes 4. dev run script to sync **file-that-weblate-understands.po** with **Localizable.xcstrings** We only need to use our existing software **pogen** to create **po** files from the **Localizable.xcstrings** which seems really easy. And then also update the **Localizable.xcstrings** from the updated **po** files. This will not stop us from using XLIFF exporting/importing. What we need to do to reduce the work load in the translators side ------------------------------------------------------------------ We can split the problem in topics Using the same i18n key between apps: we should stick to DD53 Wallet Design and use this to define which strings developers should use. If the string is defined there then it should be used in the code. That will create a spec for the 3 platforms and it should use the same key. Using translation memory in weblate config: from weblate documenantion, this can be used to automatically share translations. Using context keys for short keys: Sometimes the words like "close" or "transfer" could have separated meaning depending on the context. For that cases we have the **msgctxt** (that is additional key in addition to the short sentence). Only same sentence with same context are equivalent. We can also add some more context, like a link to the screenshot in the design document so we can trigger an alarm if an image in the weblate translation is out of sync with an image in DD 53. Using images in weblate: We should keep DD 53 updated (with the screens and text) and add information in the string sentence (like context) to point into the right location. What we need to do to reduce the work load in the translators side ------------------------------------------------------------------ 1. devs and Weblate maintainers look into DD53 + Weblate maintainers take care of checks and keep the repos consistent and up-to-date 2. translators know the apps and strings very well and manage ambiguities 3. translators and reviewers take a look at: * the context message ID / key * string location in the source code * "nearby strings" * comments * the history of string changes 4. devs and Weblate maintainers add screenshots to ambiguous strings 5. devs add context via msgctxt through the pogen script Definition of Done ================== * When iOS app has a complete semi-automated integration with weblate * Adding msgctxt works for every platforms Alternatives ============ Drawbacks ========= Discussion / Q&A ================