File: i18n.md

package info (click to toggle)
plover 5.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,356 kB
  • sloc: python: 21,589; sh: 682; ansic: 25; makefile: 11
file content (157 lines) | stat: -rw-r--r-- 5,811 bytes parent folder | download | duplicates (2)
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.