Rendered Raw
1 # Core GIT Translations
2
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>,
8 coordinates our localization effort in the l10n coordinator repository:
9
10 https://github.com/git-l10n/git-po/
11
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.
20
21
22 ## Contributing to an existing translation
23
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
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
36 ## Creating a new language translation
37
38 If you are the first contributor for the language XX, please fork this
39 repository, prepare and/or update the translated message file "po/XX.po"
40 (described later), and ask the l10n coordinator to pull your work.
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
47
48 ## Translation Process Flow
49
50 The overall data-flow looks like this:
51
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 +----------------------------------+
62
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:
66
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"
70
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)
75
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"
80
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).
84
85
86 ## Dynamically generated POT files
87
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.
92
93 The two POT files "po/git.pot" and "po/git-core.pot" can be created
94 dynamically when necessary.
95
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:
99
100 ```shell
101 make po/git.pot
102 ```
103
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.
109
110 The "core" template file "po/git-core.pot" can be generated manually
111 by running:
112
113 ```shell
114 make po/git-core.pot
115 ```
116
117
118 ## Initializing a "XX.po" file
119
120 (This is done by the language teams).
121
122 If your language XX does not have translated message file "po/XX.po" yet,
123 you add a translation for the first time by running:
124
125 ```shell
126 make po-init PO_FILE=po/XX.po
127 ```
128
129 where XX is the locale, e.g. "de", "is", "pt\_BR", "zh\_CN", etc.
130
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.
134
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
139 ## Updating a "XX.po" file
140
141 (This is done by the language teams).
142
143 If you are replacing translation strings in an existing "XX.po" file to
144 improve the translation, just edit the file.
145
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:
148
149 ```shell
150 make po-update PO_FILE=po/XX.po
151 ```
152
153 It will:
154
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
163 ## Fuzzy translation
164
165 Fuzzy translation is a translation marked by comment "fuzzy" to let you
166 know that the translation is out of date because the "msgid" has been
167 changed. A fuzzy translation will be ignored when compiling using "msgfmt".
168 Fuzzy translation can be marked by hands, but for most cases they are
169 marked automatically when running "msgmerge" to update your "XX.po" file.
170
171 After fixing the corresponding translation, you must remove the "fuzzy"
172 tag in the comment.
173
174
175 ## Testing your changes
176
177 (This is done by the language teams, after creating or updating "XX.po" file).
178
179 Before you submit your changes go back to the top-level and do:
180
181 ```shell
182 make
183 ```
184
185 On systems with GNU gettext (i.e. not Solaris) this will compile your
186 changed PO file with `msgfmt --check`, the --check option flags many
187 common errors, e.g. missing printf format strings, or translated
188 messages that deviate from the originals in whether they begin/end
189 with a newline or not.
190
191 L10n coordinator will check your contributions using a helper program
192 (see "PO helper" section below):
193
194 ```shell
195 git-po-helper check-po po/XX.po
196 git-po-helper check-commits <rev-list-opts>
197 ```
198
199
200 ## Preparing a "XX.po" file for commit
201
202 Once you are done testing the translation, it's better to commit a
203 location-less "po/XX.po" file to save repository space and make a
204 user-friendly patch for review.
205
206 To save a location-less "po/XX.po" automatically in the repository,
207 follow these steps:
208
209 First, check which filter is configured for your "po/XX.po" file:
210
211 ```
212 git check-attr filter po/XX.po
213 ```
214
215 The filter configuration is defined in the "po/.gitattributes" file.
216
217 Then define the driver for the filter. Most languages use the
218 "gettext-no-location" clean filter, which strips out both filenames and line
219 numbers from location comments. To set this up, run the following command:
220
221 ```shell
222 git config --global filter.gettext-no-location.clean \
223 "msgcat --no-location -"
224 ```
225
226 Some PO files use the "gettext-no-line-number" clean filter, which keeps
227 filenames but strips line numbers. This filter requires gettext 0.20 or
228 later. The only benefit is being able to locate source files from location
229 comments when the .po file is not updated from the POT via `make po-update`.
230
231 ```shell
232 git config --global filter.gettext-no-line-number.clean \
233 "msgcat --add-location=file -"
234 ```
235
236 You're now ready to ask the l10n coordinator to pull from you.
237
238
239 ## Marking strings for translation
240
241 (This is done by the core developers).
242
243 Before strings can be translated they first have to be marked for
244 translation.
245
246 Git uses an internationalization interface that wraps the system's
247 gettext library, so most of the advice in your gettext documentation
248 (on GNU systems `info gettext` in a terminal) applies.
249
250 General advice:
251
252 - Don't mark everything for translation, only strings which will be
253 read by humans (the porcelain interface) should be translated.
254
255 The output from Git's plumbing utilities will primarily be read by
256 programs and would break scripts under non-C locales if it was
257 translated. Plumbing strings should not be translated, since
258 they're part of Git's API.
259
260 - Adjust the strings so that they're easy to translate. Most of the
261 advice in `info '(gettext)Preparing Strings'` applies here.
262
263 - Strings referencing numbers of items may need to be split into singular and
264 plural forms; see the Q\_() wrapper in the C sub-section below for an
265 example.
266
267 - If something is unclear or ambiguous you can use a "TRANSLATORS"
268 comment to tell the translators what to make of it. These will be
269 extracted by xgettext(1) and put in the "po/\*.po" files, e.g. from
270 git-am.sh:
271
272 ```shell
273 # TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
274 # in your translation. The program will only accept English
275 # input at this point.
276 gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
277 ```
278
279 Or in C, from builtin/revert.c:
280
281 ```c
282 /* TRANSLATORS: %s will be "revert" or "cherry-pick" */
283 die(_("%s: Unable to write new index file"), action_name(opts));
284 ```
285
286 We provide wrappers for C, Shell and Perl programs. Here's how they're
287 used:
288
289
290 ### C
291
292 Include builtin.h at the top, it'll pull in gettext.h, which
293 defines the gettext interface. Consult with the list if you need to
294 use gettext.h directly.
295
296 The C interface is a subset of the normal GNU gettext
297 interface. We currently export these functions:
298
299 - \_()
300
301 Mark and translate a string. E.g.:
302
303 ```c
304 printf(_("HEAD is now at %s"), hex);
305 ```
306
307 - Q\_()
308
309 Mark and translate a plural string. E.g.:
310
311 ```c
312 printf(Q_("%d commit", "%d commits", number_of_commits));
313 ```
314
315 This is just a wrapper for the ngettext() function.
316
317 - N\_()
318
319 A no-op pass-through macro for marking strings inside static
320 initializations, e.g.:
321
322 ```c
323 static const char *reset_type_names[] = {
324 N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
325 };
326 ```
327
328 And then, later:
329
330 ```c
331 die(_("%s reset is not allowed in a bare repository"),
332 _(reset_type_names[reset_type]));
333 ```
334
335 Here `_()` couldn't have statically determined what the translation
336 string will be, but since it was already marked for translation
337 with `N_()` the look-up in the message catalog will succeed.
338
339
340 ### Shell
341
342 The Git gettext shell interface is just a wrapper for
343 gettext.sh. Import it right after git-sh-setup like this:
344
345 ```shell
346 . git-sh-setup
347 . git-sh-i18n
348 ```
349
350 And then use the `gettext` or `eval_gettext` functions:
351
352 ```shell
353 # For constant interface messages:
354 gettext "A message for the user"; echo
355
356 # To interpolate variables:
357 details="oh noes"
358 eval_gettext "An error occurred: \$details"; echo
359 ```
360
361 In addition we have wrappers for messages that end with a trailing
362 newline. I.e. you could write the above as:
363
364 ```shell
365 # For constant interface messages:
366 gettextln "A message for the user"
367
368 # To interpolate variables:
369 details="oh noes"
370 eval_gettextln "An error occurred: \$details"
371 ```
372
373 More documentation about the interface is available in the GNU info
374 page: `info '(gettext)sh'`. Looking at git-am.sh (the first shell
375 command to be translated) for examples is also useful:
376
377 ```shell
378 git log --reverse -p --grep=i18n git-am.sh
379 ```
380
381
382 ### Perl
383
384 The Git::I18N module provides a limited subset of the
385 Locale::Messages functionality, e.g.:
386
387 ```perl
388 use Git::I18N;
389 print __("Welcome to Git!\n");
390 printf __("The following error occurred: %s\n"), $error;
391 ```
392
393 Run `perldoc perl/Git/I18N.pm` for more info.
394
395
396 ## Testing marked strings
397
398 Git's tests are run under `LANG=C LC_ALL=C`. So the tests do not need be
399 changed to account for translations as they're added.
400
401
402 ## AI-assisted translation and review
403
404 [po/AGENTS.md](AGENTS.md) describes optional workflows for AI coding assistants
405 that help with Git localization: updating templates and PO files, translating
406 `po/XX.po`, and reviewing translations. Those workflows often use git-po-helper
407 together with the gettext tools; see the PO helper section below for what the
408 program does and how to build or install it. AI assistants are optional; treat
409 their output as a draft and have it reviewed by contributors who know Git and
410 the target language well.
411
412 When you prompt a coding assistant, mention that file explicitly, for example:
413 "Translate po/XX.po with reference to po/AGENTS.md" (replace XX with your
414 language code).
415
416
417 ## PO helper
418
419 `git-po-helper` is a helper for Git l10n coordinators and contributors. It
420 automates checks that contributions follow project conventions (PO syntax,
421 commit messages, which paths may change, and related rules) and can work with
422 AI coding agents for tasks such as translating new entries, and reviewing
423 translations.
424
425 Build and install instructions are in [git-po-helper/README][].
426
427
428 ## Conventions
429
430 There are some conventions that l10n contributors must follow:
431
432 - The subject of each l10n commit should be prefixed with "l10n: ".
433
434 - Do not use non-ASCII characters in the subject of a commit.
435
436 - The length of commit subject (first line of the commit log) should
437 be no more than 50 characters, and the length of other lines of the
438 commit log should be no more than 72 characters.
439
440 - Add "Signed-off-by" trailer to your commit log, like other commits
441 in Git. You can automatically add the trailer by committing with
442 the following command:
443
444 ```shell
445 git commit -s
446 ```
447
448 - Check syntax with "msgfmt" or the following command before creating
449 your commit:
450
451 ```shell
452 git-po-helper check-po <XX.po>
453 ```
454
455 - Squash trivial commits to make history clear.
456
457 - DO NOT edit files outside "po/" directory.
458
459 - Other subsystems ("git-gui", "gitk", and Git itself) have their
460 own workflow. See [Documentation/SubmittingPatches][] for
461 instructions on how to contribute patches to these subsystems.
462
463
464 To contribute for a new l10n language, contributor should follow
465 additional conventions:
466
467 - Initialize proper filename of the "XX.po" file conforming to
468 iso-639 and iso-3166.
469
470 - Must complete a minimal translation based on the "Core
471 translation". See that section above.
472
473 - Add a new entry in the "po/TEAMS" file with proper format, and check
474 the syntax of "po/TEAMS" by running the following command:
475
476 ```shell
477 git-po-helper team --check
478 ```
479
480
481 [git-po-helper/README]: https://github.com/git-l10n/git-po-helper#readme
482 [Documentation/SubmittingPatches]: Documentation/SubmittingPatches