# Internationalization Translated strings fall into 4 categories: - System strings: depending on the platform, Qt (the widget library) may use system dialogs, like the file picker. - Qt internal strings: the translation for some standard dialogs (like the OK/Cancel buttons on a message box) is provided by Qt itself. - Plover's UI. - The UI of the various installed Plover plugins. The first 2 cases are mostly out of our control, and consequently this guide only covers the last 2. ## Language selection The correct language is automatically selected at startup according to the system preferences. For testing, it's possible to force Plover to select another language by setting the `LANGUAGE` environment variable to the desired language code (e.g. `fr` for French). ## For developers The standard Python package [`gettext`](https://docs.python.org/3/library/gettext.html) is used for translating strings at runtime. [`Babel`](https://pypi.org/project/Babel/) is used by the build system for extracting, compiling, and generally managing translations catalogs. A {class}`Translator` helper class is provided by {mod}`plover.i18n`. An instance of that class (configured according to the system locale), is available as {data}`_` from the main package. This instance can be "called" directly: ```python from plover import _ print(_("message to be translated")) ``` `_(...)` is a shortcut for `_.gettext(...)`. The plural variant is also available with `_.ngettext(...)`. Finally, a string can be marked for translation without translating it using `_._(...)`. All the user-faced strings of the Qt GUI should be marked for translation. When formatting a string, `str.format(...)` should be used (avoid `%` interpolation), and only keyword placeholders should be used. Rational: this make translating easier (more context), and allow for re-arranging the arguments (which might be needed depending on the language being targeted). It's also possible to add a note for the translators with a preceding comment. The format is as follows: ```python # i18n: A very important note to translators. print(_("message to be translated")) ``` All the translations catalogs live under `plover/messages`: * `plover.pot` is the main catalog, and can be updated using: `python setup.py extract_messages` (please make sure UI generated files are up-to-date first by running `python ./setup.py build_ui -f`). * The text-based translations catalog for each supported language lives in `{language_code}/LC_MESSAGES/plover.po` * The corresponding binary catalogs ultimately used at runtime (`{language_code}/LC_MESSAGES/plover.mo`) are automatically compiled during the `build` phase, and must not be committed. * Strings in the UI generated files are automatically marked. * You can mark strings that are not translatable in `designer-qt5`: for example, the window title of a custom widget will never be seen. ### Setting up Setuptools See the "i18n" section in `setup.py` for how to use the helpers provided by `plover_build_utils` to configure Babel and automatically mark strings in generated UI files. Note: the helpers expect your main package to make a `Translator` instance available for sub-modules: ```python from plover.i18n import Translator _ = Translator(__package__, resource_dir='messages') ``` Note: don't forget to add `Babel` to your build dependencies (in `pyproject.toml`). ## For translators ### Initial steps 1. Each release provides a *Translations Catalogs* archive, download the one corresponding to your version of Plover. 2. Extract the contents of the archive right under Plover's configuration folder. The tree should look like this: ``` ${plover_config_folder}/messages ├── es │   └── LC_MESSAGES │   └── plover.po ├── fr │   └── LC_MESSAGES │   └── plover.po ├── it │   └── LC_MESSAGES │   └── plover.po └── plover.pot ``` 3. Download and install [Poedit](https://poedit.net/). ### Creating a new translation 1. Launch Poedit 2. Click on "Create New Translation", navigate to Plover's configuration folder and open: `messages/plover.pot`. 3. Select the language you're going to translate to. 4. Click on the save icon: Poedit will propose to name the file according to the language code, instead, save the file in `messages/${language_code}/LC_MESSAGES/plover.po`. E.g if you're translating to Italian, the file must be saved as `messages/it/LC_MESSAGES/plover.po`. 5. Translate, translate, translate! ### Updating an existing translation 1. Launch Poedit 2. Click on "Edit a Translation", navigate to Plover's configuration folder and open the `.po` file corresponding to your language. E.g for Italian, the file will be named `messages/it/LC_MESSAGES/plover.po`. 3. In the top menu, click on "Catalog", and then "Update from POT file...": navigate to Plover's configuration folder and select `messages/plover.pot`. 4. Translate, translate, translate! ### Testing Save your translation, and start / restart Plover. ### Tips & Tricks - You can use "File -> Open config folder" in Plover's menu to easily locate its configuration folder. - Some translations contain special keyword placeholders that will be replaced at runtime: those should be left as is. For example in this translation: `{machine} is {state}`, the `{machine}` and `{state}` parts must not be translated or removed. However, the order can be changed if necessary. - Some translations have notes: comments (some of them automatically generated), that can help provide more context about the translation. Those notes appear in the bottom right of Poedit's interface.