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 is used for translating strings at runtime. Babel is used by the build system for extracting, compiling, and generally managing translations catalogs.

A Translator helper class is provided by plover.i18n. An instance of that class (configured according to the system locale), is available as _ from the main package.

This instance can be “called” directly:

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:

# 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:

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.

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.