1# Translating Cataclysm: DDA
2
3* [Translators](#translators)
4  * [Getting Started](#getting-Started)
5  * [Glossary](#glossary)
6  * [Grammatical gender](#grammatical-gender)
7  * [Tips](#tips)
8* [Developers](#developers)
9  * [Translation Functions](#translation-functions)
10  * [`translation`](#translation)
11  * [Recommendations](#recommendations)
12* [Maintainers](#maintainers)
13
14## Translators
15
16The official location for translating Cataclysm: DDA is the
17[Transifex translations project][1].
18
19Some of the currently supported languages are:
20
21* Arabic
22* Bulgarian
23* Chinese (Simplified)
24* Chinese (Traditional)
25* Dutch
26* French
27* German
28* Italian (Italy)
29* Japanese
30* Korean
31* Polish
32* Portuguese (Brazil)
33* Russian
34* Serbian
35* Spanish (Argentina)
36* Spanish (Spain)
37* Turkish
38
39Don't see your language in the list above? You can add it into the project at
40Transifex!
41
42If you have any questions or comments about translation, feel free to post in
43the [Translations Team Discussion][2] subforum.
44
45### Getting Started
46
47To begin translating, head over the [translation project][1] and click on the
48"Help Translate Cataclysm: DDA" button.
49This should take you to a page where you can either create a free account on
50Transifex, or login using GitHub, Google+ or LinkedIn.
51
52![Start translating](img/translating-start.png)
53
54After you've created your account, return to the [translation project][1] and
55click on the "Join team" button.
56This will open a window where you can choose the language you are interested on
57translating, so pick one and click the "Join" button.
58
59![Join project](img/translating-join.png)
60
61After this, the most straightforward thing to do is to reload the page,
62which should redirect you to the translation project's dashboard.
63Here, you can click the "Languages" link on the sidebar to see the list of
64supported languages and the current progress of the translation effort.
65
66Note that you can request for the inclusion of additional languages,
67if the one you are interested in is not available on the list.
68
69![Language list](img/translating-list.png)
70
71From this list, you can click on the language of your choice, and then click on
72the "Translate" to get started right away. Otherwise, you can click on any
73other language and click on the "Join team" button, if you are interested in
74translating for that language as well.
75
76After clicking on the "Translate" button, you will be taken to the web editor.
77To begin, you need to choose a resource to translate. Most of the in-game text
78is contained in the `master-cataclysm-dda` resource, so click on it to start.
79
80![Choose a resource](img/translating-resource.png)
81
82At this point, the editor should show you the list of text available for
83translation, now you only need to click on the string you want to translate and
84type your translation on the translation area on the right side of the screen.
85Click on the "Save" button when you are satisfied with your translation.
86
87![Web editor](img/translating-editor.png)
88
89See [Transifex's documentation][3] for more information.
90
91### Glossary
92
93This glossary is intended to help explain some CDDA-specific terms and their
94etymology in order to help translations.
95
96* **Exodii**: The Exodii are a bunch of humans from another dimension.  When
97  the Blob invaded their world, they managed to acquire enough technology to
98  open portals of their own, and now they portal to worlds that have been
99  attacked by the Blob and try to rescue survivors.  Exodii is a horrible
100  mangling of "Exodus" - the word literally means leaving or going out and has
101  connotations of forced emigration and refugees.  The Exodii are the people of
102  an Exodus.  While Exodus is a Latin word and "ii" to indicate a plural is a
103  Latin thing, but this isn't actually the [correct Latin
104  plural](https://www.latin-is-simple.com/en/vocabulary/noun/9294/) for this
105  word.
106
107### Grammatical gender
108
109For NPC dialogue (and potentially other strings) some languages may wish to
110have alternate translations depending on the gender of the conversation
111participants.  This two pieces of initial configuration.
112
1131. The dialogue must have the relevant genders listed in the json file defining
114   it.  See [the NPC docs](NPCs.md).
1152. Each language must specify the genders it wishes to use via the translation
116   of `grammatical gender list`.  This should be a space-separated list of
117   genders used in this language for such translations.  Don't add genders here
118   until you're sure you will need them, because it will make more work for
119   you.  If you need different genders than are currently supported you must
120   add them to the `all_genders` lists in `lang/extract_json_strings.py` and
121   `src/translations.cpp`.
122
123Having done this, the relevant dialogue lines will appear multiple times for
124translation, with different genders specified in the message context.  For
125example, a context of `npc:m` would indicate that the NPC participant in the
126conversation is male.
127
128Because of technical limitations, all supported genders will appear as
129contexts, but you only need to provide translations for the genders listed in
130`grammatical gender list` for your language.
131
132Other parts of the game have various ad hoc solutions to grammatical gender, so
133don't be surprised to see other contexts appearing for other strings.
134
135### Tips
136
137There are issues specific to Cataclysm: DDA which translators should be aware of.
138These include the use of terms like `%s` and `%3$d` (leave them as they are),
139and the use of tags like `<name>`, which shouldn't be translated.
140
141Information about these and any other issues specific to individual languages,
142can be found in Cataclysm: DDA's [language notes folder][4].
143
144General notes for all translators are in `README_all_translators.txt`,
145and notes specific to a language may be stored as `<lang_id>.txt`,
146for example `de.txt` for German.
147
148Cataclysm: DDA has more than 14000 translatable strings, but don't be discouraged.
149The more translators there are, the easier it becomes ��.
150
151## Developers
152
153Cataclysm: DDA uses [GNU gettext][5] to display translated texts.
154
155Using `gettext` requires two actions:
156
157* Marking strings that should be translated in the source code.
158* Calling translation functions at run time.
159
160Marking translatable string allows for their automatic extraction.
161This process generates a file that maps the original string (usually in English)
162as it appears in the source code to the translated string.
163These mappings are used at run time by the translation functions.
164
165Note that only extracted strings can get translated, since the original string
166is acting as the identifier used to request the translation.
167If a translation function can't find the translation, it returns the original
168string.
169
170### Translation Functions
171
172In order to mark a string for translation and to obtain its translation at
173runtime, you should use one of the following functions and classes.
174
175String *literals* that are used in any of these functions are automatically
176extracted. Non-literal strings are still translated at run time, but they won't
177get extracted.
178
179#### `_()`
180
181This function is appropriate for use on simple strings, for example:
182
183```c++
184const char *translated = _( "text marked for translation" )
185```
186
187It also works directly:
188
189```c++
190add_msg( _( "You drop the %s." ), the_item_name );
191```
192
193Strings from the JSON files are extracted by the `lang/extract_json_strings.py`
194script, and can be translated at run time using `_()`. If translation context
195is desired for a JSON string, `class translation` can be used instead, which is
196documented below.
197
198#### `pgettext()`
199
200This function is useful when the original string's meaning is ambiguous in
201isolation. For example, the word "blue", which can mean either a color or an
202emotion.
203
204In addition to the translatable string, `pgettext` receives a context which is
205provided to the translators, but is not part of the translated string itself.
206This function's first parameter is the context, the second is the string to be
207translated:
208
209```c++
210const char *translated = pgettext("The color", "blue")
211```
212
213#### `ngettext()`
214
215Some languages have complex rules for plural forms. `ngettext` can be used to
216translate these plurals correctly. Its first parameter is the untranslated
217string in singular form, the second parameter is the untranslated string in
218plural form and the third one is used to determine which one of the first two
219should be used at run time:
220
221```c++
222const char *translated = ngettext("one zombie", "many zombies", num_of_zombies)
223```
224
225### `translation`
226
227There are times when you want to store a string for translation, maybe with
228translation context; Sometimes you may also want to store a string that needs no
229translation or has plural forms. `class translation` in `translations.h|cpp`
230offers these functionalities in a single wrapper:
231
232```c++
233const translation text = to_translation( "Context", "Text" );
234```
235
236```c++
237const translation text = to_translation( "Text without context" );
238```
239
240```c++
241const translation text = pl_translation( "Singular", "Plural" );
242```
243
244```c++
245const translation text = pl_translation( "Context", "Singular", "Plural" );
246```
247
248```c++
249const translation text = no_translation( "This string will not be translated" );
250```
251
252The string can then be translated/retrieved with the following code
253
254```c++
255const std::string translated = text.translated();
256```
257
258```c++
259// this translates the plural form of the text corresponding to the number 2
260const std::string translated = text.translated( 2 );
261```
262
263`class translation` can also be read from JSON. The method `translation::deserialize()`
264handles deserialization from a `JsonIn` object, so translations can be read from
265JSON using the appropriate JSON functions. The JSON syntax is as follows:
266
267```JSON
268"name": "bar"
269```
270
271```JSON
272"name": { "ctxt": "foo", "str": "bar", "str_pl": "baz" }
273```
274
275or
276
277```JSON
278"name": { "ctxt": "foo", "str_sp": "foo" }
279```
280
281In the above code, `"ctxt"` and `"str_pl"` are both optional, whereas `"str_sp"`
282is equivalent to specifying `"str"` and `"str_pl"` with the same string. Additionally,
283`"str_pl"` and `"str_sp"` will only be read if the translation object is constructed using
284`plural_tag` or `pl_translation()`, or converted using `make_plural()`. Here's
285an example:
286
287```c++
288translation name{ translation::plural_tag() };
289jsobj.read( "name", name );
290```
291
292If neither "str_pl" nor "str_sp" is specified, the plural form defaults to the
293singular form + "s".
294
295You can also add comments for translators by writing it like below (the order
296of the entries does not matter):
297
298```JSON
299"name": {
300    "//~": "as in 'foobar'",
301    "str": "bar"
302}
303```
304
305Do note that the JSON syntax is only supported if a JSON value is read using
306`translation`. If you want new json values to use this format, refer to
307`translations.h|cpp` and read the strings with `translation`. Afterwards
308you also need to update `extract_json_strings.py` and run `lang/update_pot.sh`
309to ensure that the strings are correctly extracted for translation, and run the
310unit test to fix text styling issues reported by the `translation` class.
311
312### Recommendations
313
314In Cataclysm: DDA, some classes, like `itype` and `mtype`, provide a wrapper
315for the translation functions, called `nname`.
316
317When an empty string is marked for translation, it is always translated into
318debug information, rather than an empty string.
319On most cases, strings can be considered to be never empty, and thus always
320safe to mark for translation, however, when handling a string that can be empty
321and *needs* to remain empty after translation, the string should be checked for
322emptiness and only passed to a translation function when is non-empty.
323
324Error and debug messages must not be marked for translation.
325When they appear, the player is expected to report them *exactly* as they are
326printed by the game.
327
328See the [gettext manual][6] for more information.
329
330## Maintainers
331
332Several steps need to be done in the correct order to correctly merge and maintain the translation files.
333
334There are scripts available for these, so usually the process will be as follows:
335
3361. Download the translations in `.po` format.
3372. Put them in `lang/incoming/`, ensuring they are named consistently with the files in `lang/po/`.
3383. Run `lang/update_pot.sh` to update `lang/po/cataclysm-dda.pot`.
3394. Run `lang/merge_po.sh` to update `lang/po/*.po`. (This is only used to test translations locally as the project now uses Transifex for translation)
340
341    This will also merge the translations from `lang/incoming/`.
342
343These steps should be enough to keep the translation files up-to-date.
344
345To compile the .po files into `.mo` files for use, run `lang/compile_mo.sh`. It will create a directory in `lang/mo/` for each language found.
346
347Also note that both `lang/merge_po.sh` and `lang/compile_mo.sh` accept arguments specifying which languages to merge or compile. So to compile only the translation for, say, Traditional Chinese (zh_TW), one would run `lang/compile_mo.sh zh_TW`.
348
349After compiling the appropriate .mo file, if your system is using that language, the translations will be automatically used when you run cataclysm.
350
351If your system locale is different from the one you want to test, the easiest way to do so is to find out your locale identifier, compile the translation you want to test, then rename the directory in `lang/mo/` to your locale identifier.
352
353So for example if your local language is New Zealand English (en_NZ), and you want to test the Russian (ru) translation, the steps would be `lang/compile_mo.sh ru`, `mv lang/mo/ru lang/mo/en_NZ`, `./cataclysm`.
354
355
356[1]: https://www.transifex.com/cataclysm-dda-translators/cataclysm-dda/
357[2]: https://discourse.cataclysmdda.org/c/game-talk/translations-team-discussion
358[3]: https://docs.transifex.com/
359[4]: ../lang/notes
360[5]: https://www.gnu.org/software/gettext/
361[6]: https://www.gnu.org/software/gettext/manual/index.html
362