From 9ad6bb952a93152cf381028beea990630d1c0858 Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Thu, 3 Feb 2022 12:10:48 +0200 Subject: [PATCH] docs(i18n): make translation guide more explicit (#18254) --- docs/docs/Contributing/translations.mdx | 89 +++++++++++++++++++------ 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/docs/docs/Contributing/translations.mdx b/docs/docs/Contributing/translations.mdx index bb57cdf745261..52200aedff04a 100644 --- a/docs/docs/Contributing/translations.mdx +++ b/docs/docs/Contributing/translations.mdx @@ -7,14 +7,19 @@ version: 1 ## Translating -We use [Babel](http://babel.pocoo.org/en/latest/) to translate Superset. -In Python files, we import the magic `_` function using: +We use [Flask-Babel](https://flask-babel.tkte.ch/) to translate Superset. +In Python files, we use the following +[translation functions](https://flask-babel.tkte.ch/#using-translations) from +`Flask-Babel`: +- `gettext` and `lazy_gettext` (usually aliased to `_`): for translating singular + strings. +- `ngettext`: for translating strings that might become plural. ```python from flask_babel import lazy_gettext as _ ``` -then wrap our translatable strings with it, e.g. `_('Translate me')`. +then wrap the translatable strings with it, e.g. `_('Translate me')`. During extraction, string literals passed to `_` will be added to the generated `.po` file for each language for later translation. @@ -43,29 +48,80 @@ LANGUAGES = { } ``` +### Creating a new language dictionary + +First check if the language code for your target language already exists. Check if the +[two letter ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) +for your target language already exists in the `superset/translations` directory: + +```bash +ls superset/translations | grep -E "^[a-z]{2}\/" +``` + +If your language already has a pre-existing translation, skip to the next section + +The following languages are already supported by Flask AppBuilder, and will make it +easier to translate the application to your target language: +[Flask AppBuilder i18n documentation](https://flask-appbuilder.readthedocs.io/en/latest/i18n.html) + +To create a dictionary for a new language, first make sure the necessary dependencies are installed: +```bash +pip install -r superset/translations/requirements.txt +``` + +Then run the following, where `LANGUAGE_CODE` is replaced with the language code for your target +language: + +```bash +pybabel init -i superset/translations/messages.pot -d superset/translations -l LANGUAGE_CODE +``` + +For instance, to add a translation for Finnish (language code `fi`), run the following: + +```bash +pybabel init -i superset/translations/messages.pot -d superset/translations -l fi +``` + ### Extracting new strings for translation +This step needs to be done every time application strings change. This happens fairly +frequently, so if you want to ensure that your translation has good coverage, this +step needs to be run fairly frequently and the updated strings merged to the upstream +codebase via PRs. To update the template file `superset/translations/messages.pot` +with current application strings, run the following command: + ```bash pybabel extract -F superset/translations/babel.cfg -o superset/translations/messages.pot -k _ -k __ -k t -k tn -k tct . ``` -This will update the template file `superset/translations/messages.pot` with current application strings. Do not forget to update -this file with the appropriate license information. +Do not forget to update this file with the appropriate license information. ### Updating language files +Run the following command to update the language files with the new extracted strings. + ```bash pybabel update -i superset/translations/messages.pot -d superset/translations --ignore-obsolete ``` -This will update language files with the new extracted strings. - You can then translate the strings gathered in files located under -`superset/translation`, where there's one per language. You can use [Poedit](https://poedit.net/features) +`superset/translation`, where there's one folder per language. You can use [Poedit](https://poedit.net/features) to translate the `po` file more conveniently. There are some [tutorials in the wiki](https://wiki.lxde.org/en/Translate_*.po_files_with_Poedit). -In the case of JS translation, we need to convert the PO file into a JSON file, and we need the global download of the npm package po2json. +To perform the translation on MacOS, you can install `poedit` via Homebrew: + +```bash +brew install poedit +``` + +After this, just start the `poedit` application and open the `messages.po` file. In the +case of the Finnish translation, this would be `superset/translations/fi/LC_MESSAGES/messages.po`. + +### Applying translations + +To make the translations available on the frontend, we need to convert the PO file into +a JSON file. To do this, we need to globally install the npm package `po2json`. ```bash npm install -g po2json @@ -84,20 +140,9 @@ the executable path (e.g. `/usr/local/bin/po2json` instead of `po2json`). If you get a lot of `[null,***]` in `messages.json`, just delete all the `null,`. For example, `"year":["年"]` is correct while `"year":[null,"年"]`is incorrect. -For the translations to take effect we need to compile translation catalogs into binary MO files. +Finally, for the translations to take effect we need to compile translation catalogs into +binary MO files. ```bash pybabel compile -d superset/translations ``` - -### Creating a new language dictionary - -To create a dictionary for a new language, run the following, where `LANGUAGE_CODE` is replaced with -the language code for your target language, e.g. `es` (see [Flask AppBuilder i18n documentation](https://flask-appbuilder.readthedocs.io/en/latest/i18n.html) for more details): - -```bash -pip install -r superset/translations/requirements.txt -pybabel init -i superset/translations/messages.pot -d superset/translations -l LANGUAGE_CODE -``` - -Then, [extract strings for the new language](#extracting-new-strings-for-translation).