]>
Commit | Line | Data |
---|---|---|
cb92e283 | 1 | # Core GIT Translations |
5e9637c6 | 2 | |
271ce198 JH |
3 | This directory holds the translations for the core of Git. This document |
4 | describes how you can contribute to the effort of enhancing the language | |
5 | coverage and maintaining the translation. | |
6 | ||
7 | The localization (l10n) coordinator, Jiang Xin <worldhello.net@gmail.com>, | |
1b51ae59 | 8 | coordinates our localization effort in the l10n coordinator repository: |
271ce198 | 9 | |
cb92e283 | 10 | https://github.com/git-l10n/git-po/ |
271ce198 | 11 | |
e2f4045f ÆAB |
12 | We will use XX as an alias to refer to the language translation code in |
13 | the following paragraphs, for example we use "po/XX.po" to refer to the | |
14 | translation file for a specific language. But this doesn't mean that | |
15 | the language code has only two letters. The language code can be in one | |
16 | of two forms: "ll" or "ll\_CC". Here "ll" is the ISO 639 two-letter | |
17 | language code and "CC" is the ISO 3166 two-letter code for country names | |
18 | and subdivisions. For example: "de" for German language code, "zh\_CN" | |
19 | for Simplified Chinese language code. | |
a6926b83 PO |
20 | |
21 | ||
cb92e283 JX |
22 | ## Contributing to an existing translation |
23 | ||
75b182ae JX |
24 | As a contributor for a language XX, you should first check TEAMS file in |
25 | this directory to see whether a dedicated repository for your language XX | |
26 | exists. Fork the dedicated repository and start to work if it exists. | |
27 | ||
a6926b83 PO |
28 | Sometime, contributors may find that the translations of their Git |
29 | distributions are quite different with the translations of the | |
30 | corresponding version from Git official. This is because some Git | |
31 | distributions (such as from Ubuntu, etc.) have their own l10n workflow. | |
32 | For this case, wrong translations should be reported and fixed through | |
33 | their workflows. | |
34 | ||
35 | ||
cb92e283 JX |
36 | ## Creating a new language translation |
37 | ||
75b182ae | 38 | If you are the first contributor for the language XX, please fork this |
cb92e283 | 39 | repository, prepare and/or update the translated message file "po/XX.po" |
75b182ae | 40 | (described later), and ask the l10n coordinator to pull your work. |
271ce198 JH |
41 | |
42 | If there are multiple contributors for the same language, please first | |
43 | coordinate among yourselves and nominate the team leader for your | |
44 | language, so that the l10n coordinator only needs to interact with one | |
45 | person per language. | |
46 | ||
a6926b83 | 47 | |
e2f4045f | 48 | ## Translation Process Flow |
cb92e283 | 49 | |
e2f4045f | 50 | The overall data-flow looks like this: |
2fb9d259 | 51 | |
e2f4045f ÆAB |
52 | +-------------------+ +------------------+ |
53 | | Git source code | ----(2)---> | L10n coordinator | | |
54 | | repository | <---(5)---- | repository | | |
55 | +-------------------+ +------------------+ | |
56 | | | ^ | |
57 | (1) (3) (4) | |
58 | V v | | |
59 | +----------------------------------+ | |
60 | | Language Team XX | | |
61 | +----------------------------------+ | |
2fb9d259 | 62 | |
e2f4045f ÆAB |
63 | - Translatable strings are marked in the source file. |
64 | - Language teams can start translation iterations at any time, even | |
65 | before the l10n window opens: | |
2fb9d259 | 66 | |
e2f4045f ÆAB |
67 | + Pull from the master branch of the source (1) |
68 | + Update the message file by running "make po-update PO\_FILE=po/XX.po" | |
69 | + Translate the message file "po/XX.po" | |
2fb9d259 | 70 | |
e2f4045f ÆAB |
71 | - The L10n coordinator pulls from source and announces the l10n window |
72 | open (2) | |
73 | - Language team pulls from the l10n coordinator, starts another | |
74 | translation iteration against the l10n coordinator's tree (3) | |
2fb9d259 | 75 | |
e2f4045f ÆAB |
76 | + Run "git pull --rebase" from the l10n coordinator |
77 | + Update the message file by running "make po-update PO\_FILE=po/XX.po" | |
78 | + Translate the message file "po/XX.po" | |
79 | + Squash trivial l10n git commits using "git rebase -i" | |
2fb9d259 | 80 | |
e2f4045f ÆAB |
81 | - Language team sends pull request to the l10n coordinator (4) |
82 | - L10n coordinator checks and merges | |
83 | - L10n coordinator asks the result to be pulled (5). | |
2fb9d259 | 84 | |
cb92e283 | 85 | |
e2f4045f | 86 | ## Dynamically generated POT files |
271ce198 | 87 | |
e2f4045f ÆAB |
88 | POT files are templates for l10n contributors to create or update their |
89 | translation files. We used to have the "po/git.pot" file which was | |
90 | generated by the l10n coordinator, but this file had been removed from | |
91 | the tree. | |
271ce198 | 92 | |
e2f4045f ÆAB |
93 | The two POT files "po/git.pot" and "po/git-core.pot" can be created |
94 | dynamically when necessary. | |
271ce198 | 95 | |
e2f4045f ÆAB |
96 | L10n contributors use "po/git.pot" to prepare translations for their |
97 | languages, but they are not expected to modify it. The "po/git.pot" file | |
98 | can be generated manually with the following command: | |
271ce198 | 99 | |
e2f4045f ÆAB |
100 | ```shell |
101 | make po/git.pot | |
102 | ``` | |
5e9637c6 | 103 | |
e2f4045f ÆAB |
104 | The "po/git-core.pot" file is the template for core translations. A core |
105 | translation is the minimum set of work necessary to complete a | |
106 | translation of a new language. Since there are more than 5000 messages | |
107 | in the full set of template message file "po/git.pot" that need to be | |
108 | translated, this is not a piece of cake for new language contributors. | |
5e9637c6 | 109 | |
e2f4045f ÆAB |
110 | The "core" template file "po/git-core.pot" can be generated manually |
111 | by running: | |
5e9637c6 | 112 | |
e2f4045f ÆAB |
113 | ```shell |
114 | make po/git-core.pot | |
115 | ``` | |
5e9637c6 | 116 | |
5e9637c6 | 117 | |
cb92e283 | 118 | ## Initializing a "XX.po" file |
5e9637c6 | 119 | |
271ce198 | 120 | (This is done by the language teams). |
5e9637c6 | 121 | |
cb92e283 | 122 | If your language XX does not have translated message file "po/XX.po" yet, |
271ce198 | 123 | you add a translation for the first time by running: |
5e9637c6 | 124 | |
cb92e283 | 125 | ```shell |
e2f4045f | 126 | make po-init PO_FILE=po/XX.po |
cb92e283 | 127 | ``` |
5e9637c6 | 128 | |
e2f4045f | 129 | where XX is the locale, e.g. "de", "is", "pt\_BR", "zh\_CN", etc. |
5e9637c6 | 130 | |
e2f4045f ÆAB |
131 | The newly generated message file "po/XX.po" is based on the core pot |
132 | file "po/git-core.pot", so it contains only a minimal set of messages | |
133 | and it's a good start for a new language contribution. | |
5e9637c6 | 134 | |
271ce198 JH |
135 | Once you are done testing the translation (see below), commit the result |
136 | and ask the l10n coordinator to pull from you. | |
137 | ||
138 | ||
cb92e283 | 139 | ## Updating a "XX.po" file |
271ce198 JH |
140 | |
141 | (This is done by the language teams). | |
5e9637c6 | 142 | |
cb92e283 | 143 | If you are replacing translation strings in an existing "XX.po" file to |
271ce198 | 144 | improve the translation, just edit the file. |
5e9637c6 | 145 | |
e2f4045f ÆAB |
146 | If you want to find new translatable strings in source files of upstream |
147 | repository and propagate them to your "po/XX.po", run command: | |
5e9637c6 | 148 | |
cb92e283 | 149 | ```shell |
e2f4045f | 150 | make po-update PO_FILE=po/XX.po |
cb92e283 | 151 | ``` |
5e9637c6 | 152 | |
e2f4045f | 153 | It will: |
271ce198 | 154 | |
e2f4045f ÆAB |
155 | - Call "make po/git.pot" to generate new "po/git.pot" file |
156 | - Call "msgmerge --add-location --backup=off -U po/XX.po po/git.pot" | |
157 | to update your "po/XX.po" | |
158 | - The "--add-location" option for msgmerge will add location lines, | |
159 | and these location lines will help translation tools to locate | |
160 | translation context easily. | |
161 | ||
162 | Once you are done testing the translation (see below), it's better | |
163 | to commit a location-less "po/XX.po" file to save repository space | |
164 | and make a user-friendly patch for review. | |
165 | ||
166 | To save a location-less "po/XX.po" automatically in repository, you | |
167 | can: | |
168 | ||
169 | First define a new attribute for "po/XX.po" by appending the following | |
170 | line in ".git/info/attributes": | |
171 | ||
172 | ``` | |
173 | /po/XX.po filter=gettext-no-location | |
174 | ``` | |
175 | ||
176 | Then define the driver for the "gettext-no-location" clean filter to | |
177 | strip out both filenames and locations from the contents as follows: | |
178 | ||
179 | ```shell | |
180 | git config --global filter.gettext-no-location.clean \ | |
181 | "msgcat --no-location -" | |
182 | ``` | |
183 | ||
184 | For users who have gettext version 0.20 or higher, it is also possible | |
185 | to define a clean filter to preserve filenames but not locations: | |
186 | ||
187 | ```shell | |
188 | git config --global filter.gettext-no-location.clean \ | |
189 | "msgcat --add-location=file -" | |
190 | ``` | |
191 | ||
192 | You're now ready to ask the l10n coordinator to pull from you. | |
271ce198 | 193 | |
cb92e283 JX |
194 | |
195 | ## Fuzzy translation | |
3714fbcb BS |
196 | |
197 | Fuzzy translation is a translation marked by comment "fuzzy" to let you | |
198 | know that the translation is out of date because the "msgid" has been | |
199 | changed. A fuzzy translation will be ignored when compiling using "msgfmt". | |
200 | Fuzzy translation can be marked by hands, but for most cases they are | |
201 | marked automatically when running "msgmerge" to update your "XX.po" file. | |
202 | ||
203 | After fixing the corresponding translation, you must remove the "fuzzy" | |
204 | tag in the comment. | |
205 | ||
5e9637c6 | 206 | |
cb92e283 | 207 | ## Testing your changes |
5e9637c6 | 208 | |
cb92e283 | 209 | (This is done by the language teams, after creating or updating "XX.po" file). |
271ce198 | 210 | |
5e9637c6 ÆAB |
211 | Before you submit your changes go back to the top-level and do: |
212 | ||
cb92e283 JX |
213 | ```shell |
214 | make | |
215 | ``` | |
5e9637c6 ÆAB |
216 | |
217 | On systems with GNU gettext (i.e. not Solaris) this will compile your | |
218 | changed PO file with `msgfmt --check`, the --check option flags many | |
219 | common errors, e.g. missing printf format strings, or translated | |
220 | messages that deviate from the originals in whether they begin/end | |
221 | with a newline or not. | |
222 | ||
e2f4045f ÆAB |
223 | L10n coordinator will check your contributions using a helper program |
224 | (see "PO helper" section below): | |
225 | ||
226 | ```shell | |
227 | git-po-helper check-po po/XX.po | |
228 | git-po-helper check-commits <rev-list-opts> | |
229 | ``` | |
230 | ||
5e9637c6 | 231 | |
cb92e283 | 232 | ## Marking strings for translation |
5e9637c6 | 233 | |
271ce198 JH |
234 | (This is done by the core developers). |
235 | ||
5e9637c6 ÆAB |
236 | Before strings can be translated they first have to be marked for |
237 | translation. | |
238 | ||
239 | Git uses an internationalization interface that wraps the system's | |
240 | gettext library, so most of the advice in your gettext documentation | |
241 | (on GNU systems `info gettext` in a terminal) applies. | |
242 | ||
243 | General advice: | |
244 | ||
cb92e283 JX |
245 | - Don't mark everything for translation, only strings which will be |
246 | read by humans (the porcelain interface) should be translated. | |
5e9637c6 | 247 | |
cb92e283 JX |
248 | The output from Git's plumbing utilities will primarily be read by |
249 | programs and would break scripts under non-C locales if it was | |
250 | translated. Plumbing strings should not be translated, since | |
251 | they're part of Git's API. | |
5e9637c6 | 252 | |
cb92e283 JX |
253 | - Adjust the strings so that they're easy to translate. Most of the |
254 | advice in `info '(gettext)Preparing Strings'` applies here. | |
5e9637c6 | 255 | |
786eb1ba JS |
256 | - Strings referencing numbers of items may need to be split into singular and |
257 | plural forms; see the Q\_() wrapper in the C sub-section below for an | |
258 | example. | |
259 | ||
cb92e283 JX |
260 | - If something is unclear or ambiguous you can use a "TRANSLATORS" |
261 | comment to tell the translators what to make of it. These will be | |
262 | extracted by xgettext(1) and put in the "po/\*.po" files, e.g. from | |
263 | git-am.sh: | |
5e9637c6 | 264 | |
cb92e283 JX |
265 | ```shell |
266 | # TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a] | |
267 | # in your translation. The program will only accept English | |
268 | # input at this point. | |
269 | gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " | |
270 | ``` | |
5e9637c6 | 271 | |
cb92e283 | 272 | Or in C, from builtin/revert.c: |
5e9637c6 | 273 | |
cb92e283 JX |
274 | ```c |
275 | /* TRANSLATORS: %s will be "revert" or "cherry-pick" */ | |
276 | die(_("%s: Unable to write new index file"), action_name(opts)); | |
277 | ``` | |
5e9637c6 ÆAB |
278 | |
279 | We provide wrappers for C, Shell and Perl programs. Here's how they're | |
280 | used: | |
281 | ||
5e9637c6 | 282 | |
cb92e283 JX |
283 | ### C |
284 | ||
285 | Include builtin.h at the top, it'll pull in gettext.h, which | |
286 | defines the gettext interface. Consult with the list if you need to | |
287 | use gettext.h directly. | |
288 | ||
289 | The C interface is a subset of the normal GNU gettext | |
290 | interface. We currently export these functions: | |
291 | ||
292 | - \_() | |
5e9637c6 | 293 | |
cb92e283 | 294 | Mark and translate a string. E.g.: |
5e9637c6 | 295 | |
cb92e283 JX |
296 | ```c |
297 | printf(_("HEAD is now at %s"), hex); | |
298 | ``` | |
5e9637c6 | 299 | |
cb92e283 | 300 | - Q\_() |
5e9637c6 | 301 | |
cb92e283 | 302 | Mark and translate a plural string. E.g.: |
5e9637c6 | 303 | |
cb92e283 JX |
304 | ```c |
305 | printf(Q_("%d commit", "%d commits", number_of_commits)); | |
306 | ``` | |
5e9637c6 | 307 | |
cb92e283 | 308 | This is just a wrapper for the ngettext() function. |
5e9637c6 | 309 | |
cb92e283 | 310 | - N\_() |
5e9637c6 | 311 | |
cb92e283 JX |
312 | A no-op pass-through macro for marking strings inside static |
313 | initializations, e.g.: | |
5e9637c6 | 314 | |
cb92e283 JX |
315 | ```c |
316 | static const char *reset_type_names[] = { | |
317 | N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL | |
318 | }; | |
319 | ``` | |
5e9637c6 | 320 | |
cb92e283 | 321 | And then, later: |
5e9637c6 | 322 | |
cb92e283 JX |
323 | ```c |
324 | die(_("%s reset is not allowed in a bare repository"), | |
325 | _(reset_type_names[reset_type])); | |
326 | ``` | |
5e9637c6 | 327 | |
cb92e283 JX |
328 | Here `_()` couldn't have statically determined what the translation |
329 | string will be, but since it was already marked for translation | |
330 | with `N_()` the look-up in the message catalog will succeed. | |
5e9637c6 | 331 | |
5e9637c6 | 332 | |
cb92e283 | 333 | ### Shell |
5e9637c6 | 334 | |
cb92e283 JX |
335 | The Git gettext shell interface is just a wrapper for |
336 | gettext.sh. Import it right after git-sh-setup like this: | |
5e9637c6 | 337 | |
cb92e283 JX |
338 | ```shell |
339 | . git-sh-setup | |
340 | . git-sh-i18n | |
341 | ``` | |
5e9637c6 | 342 | |
cb92e283 | 343 | And then use the `gettext` or `eval_gettext` functions: |
5e9637c6 | 344 | |
cb92e283 JX |
345 | ```shell |
346 | # For constant interface messages: | |
347 | gettext "A message for the user"; echo | |
5e9637c6 | 348 | |
cb92e283 JX |
349 | # To interpolate variables: |
350 | details="oh noes" | |
351 | eval_gettext "An error occurred: \$details"; echo | |
352 | ``` | |
5e9637c6 | 353 | |
cb92e283 JX |
354 | In addition we have wrappers for messages that end with a trailing |
355 | newline. I.e. you could write the above as: | |
5e9637c6 | 356 | |
cb92e283 JX |
357 | ```shell |
358 | # For constant interface messages: | |
359 | gettextln "A message for the user" | |
5e9637c6 | 360 | |
cb92e283 JX |
361 | # To interpolate variables: |
362 | details="oh noes" | |
363 | eval_gettextln "An error occurred: \$details" | |
364 | ``` | |
5e9637c6 | 365 | |
cb92e283 JX |
366 | More documentation about the interface is available in the GNU info |
367 | page: `info '(gettext)sh'`. Looking at git-am.sh (the first shell | |
368 | command to be translated) for examples is also useful: | |
5e9637c6 | 369 | |
cb92e283 JX |
370 | ```shell |
371 | git log --reverse -p --grep=i18n git-am.sh | |
372 | ``` | |
5e9637c6 | 373 | |
5e9637c6 | 374 | |
cb92e283 | 375 | ### Perl |
5e9637c6 | 376 | |
cb92e283 JX |
377 | The Git::I18N module provides a limited subset of the |
378 | Locale::Messages functionality, e.g.: | |
5e9637c6 | 379 | |
cb92e283 JX |
380 | ```perl |
381 | use Git::I18N; | |
382 | print __("Welcome to Git!\n"); | |
383 | printf __("The following error occurred: %s\n"), $error; | |
384 | ``` | |
5e9637c6 | 385 | |
cb92e283 | 386 | Run `perldoc perl/Git/I18N.pm` for more info. |
5e9637c6 ÆAB |
387 | |
388 | ||
cb92e283 | 389 | ## Testing marked strings |
5e9637c6 | 390 | |
cb92e283 | 391 | Git's tests are run under `LANG=C LC_ALL=C`. So the tests do not need be |
d162b25f | 392 | changed to account for translations as they're added. |
6d09c530 BS |
393 | |
394 | ||
cb92e283 | 395 | ## PO helper |
6d09c530 | 396 | |
cb92e283 | 397 | To make the maintenance of "XX.po" easier, the l10n coordinator and l10n |
6d09c530 BS |
398 | team leaders can use a helper program named "git-po-helper". It is a |
399 | wrapper to gettext suite, specifically written for the purpose of Git | |
400 | l10n workflow. | |
401 | ||
402 | To build and install the helper program from source, see | |
403 | [git-po-helper/README][]. | |
404 | ||
69c13a78 | 405 | |
cb92e283 | 406 | ## Conventions |
69c13a78 BS |
407 | |
408 | There are some conventions that l10n contributors must follow: | |
409 | ||
cb92e283 | 410 | - The subject of each l10n commit should be prefixed with "l10n: ". |
69c13a78 | 411 | |
cb92e283 | 412 | - Do not use non-ASCII characters in the subject of a commit. |
69c13a78 | 413 | |
cb92e283 | 414 | - The length of commit subject (first line of the commit log) should |
1627e6b4 | 415 | be no more than 50 characters, and the length of other lines of the |
cb92e283 | 416 | commit log should be no more than 72 characters. |
69c13a78 | 417 | |
cb92e283 JX |
418 | - Add "Signed-off-by" trailer to your commit log, like other commits |
419 | in Git. You can automatically add the trailer by committing with | |
420 | the following command: | |
421 | ||
422 | ```shell | |
423 | git commit -s | |
424 | ``` | |
425 | ||
426 | - Check syntax with "msgfmt" or the following command before creating | |
427 | your commit: | |
428 | ||
429 | ```shell | |
430 | git-po-helper check-po <XX.po> | |
431 | ``` | |
432 | ||
433 | - Squash trivial commits to make history clear. | |
434 | ||
435 | - DO NOT edit files outside "po/" directory. | |
436 | ||
437 | - Other subsystems ("git-gui", "gitk", and Git itself) have their | |
438 | own workflow. See [Documentation/SubmittingPatches][] for | |
439 | instructions on how to contribute patches to these subsystems. | |
69c13a78 | 440 | |
69c13a78 BS |
441 | |
442 | To contribute for a new l10n language, contributor should follow | |
443 | additional conventions: | |
444 | ||
cb92e283 JX |
445 | - Initialize proper filename of the "XX.po" file conforming to |
446 | iso-639 and iso-3166. | |
447 | ||
e2f4045f ÆAB |
448 | - Must complete a minimal translation based on the "Core |
449 | translation". See that section above. | |
69c13a78 | 450 | |
cb92e283 JX |
451 | - Add a new entry in the "po/TEAMS" file with proper format, and check |
452 | the syntax of "po/TEAMS" by running the following command: | |
69c13a78 | 453 | |
cb92e283 JX |
454 | ```shell |
455 | git-po-helper team --check | |
456 | ``` | |
69c13a78 BS |
457 | |
458 | ||
6d09c530 | 459 | [git-po-helper/README]: https://github.com/git-l10n/git-po-helper#readme |
69c13a78 | 460 | [Documentation/SubmittingPatches]: Documentation/SubmittingPatches |