1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
# 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<plover.i18n.Translator>` helper class is provided by {mod}`plover.i18n`. An instance of that
class (configured according to the system locale), is available as {data}`_<plover._>` 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.
|