mirror of
https://github.com/git/git
synced 2024-08-28 12:09:19 +00:00
![Arthur Milchior](/assets/img/avatar_default.png)
This 10-year old typo was introduced at 75b182ae
(Update l10n guide:
change the repository URL, etc, 2012-03-02). The word "l10" should be
"l10n".
Signed-off-by: Arthur Milchior <arthur@milchior.fr>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
461 lines
14 KiB
Markdown
461 lines
14 KiB
Markdown
# Core GIT Translations
|
|
|
|
This directory holds the translations for the core of Git. This document
|
|
describes how you can contribute to the effort of enhancing the language
|
|
coverage and maintaining the translation.
|
|
|
|
The localization (l10n) coordinator, Jiang Xin <worldhello.net@gmail.com>,
|
|
coordinates our localization effort in the l10n coordinator repository:
|
|
|
|
https://github.com/git-l10n/git-po/
|
|
|
|
We will use XX as an alias to refer to the language translation code in
|
|
the following paragraphs, for example we use "po/XX.po" to refer to the
|
|
translation file for a specific language. But this doesn't mean that
|
|
the language code has only two letters. The language code can be in one
|
|
of two forms: "ll" or "ll\_CC". Here "ll" is the ISO 639 two-letter
|
|
language code and "CC" is the ISO 3166 two-letter code for country names
|
|
and subdivisions. For example: "de" for German language code, "zh\_CN"
|
|
for Simplified Chinese language code.
|
|
|
|
|
|
## Contributing to an existing translation
|
|
|
|
As a contributor for a language XX, you should first check TEAMS file in
|
|
this directory to see whether a dedicated repository for your language XX
|
|
exists. Fork the dedicated repository and start to work if it exists.
|
|
|
|
Sometime, contributors may find that the translations of their Git
|
|
distributions are quite different with the translations of the
|
|
corresponding version from Git official. This is because some Git
|
|
distributions (such as from Ubuntu, etc.) have their own l10n workflow.
|
|
For this case, wrong translations should be reported and fixed through
|
|
their workflows.
|
|
|
|
|
|
## Creating a new language translation
|
|
|
|
If you are the first contributor for the language XX, please fork this
|
|
repository, prepare and/or update the translated message file "po/XX.po"
|
|
(described later), and ask the l10n coordinator to pull your work.
|
|
|
|
If there are multiple contributors for the same language, please first
|
|
coordinate among yourselves and nominate the team leader for your
|
|
language, so that the l10n coordinator only needs to interact with one
|
|
person per language.
|
|
|
|
|
|
## Translation Process Flow
|
|
|
|
The overall data-flow looks like this:
|
|
|
|
+-------------------+ +------------------+
|
|
| Git source code | ----(2)---> | L10n coordinator |
|
|
| repository | <---(5)---- | repository |
|
|
+-------------------+ +------------------+
|
|
| | ^
|
|
(1) (3) (4)
|
|
V v |
|
|
+----------------------------------+
|
|
| Language Team XX |
|
|
+----------------------------------+
|
|
|
|
- Translatable strings are marked in the source file.
|
|
- Language teams can start translation iterations at any time, even
|
|
before the l10n window opens:
|
|
|
|
+ Pull from the master branch of the source (1)
|
|
+ Update the message file by running "make po-update PO\_FILE=po/XX.po"
|
|
+ Translate the message file "po/XX.po"
|
|
|
|
- The L10n coordinator pulls from source and announces the l10n window
|
|
open (2)
|
|
- Language team pulls from the l10n coordinator, starts another
|
|
translation iteration against the l10n coordinator's tree (3)
|
|
|
|
+ Run "git pull --rebase" from the l10n coordinator
|
|
+ Update the message file by running "make po-update PO\_FILE=po/XX.po"
|
|
+ Translate the message file "po/XX.po"
|
|
+ Squash trivial l10n git commits using "git rebase -i"
|
|
|
|
- Language team sends pull request to the l10n coordinator (4)
|
|
- L10n coordinator checks and merges
|
|
- L10n coordinator asks the result to be pulled (5).
|
|
|
|
|
|
## Dynamically generated POT files
|
|
|
|
POT files are templates for l10n contributors to create or update their
|
|
translation files. We used to have the "po/git.pot" file which was
|
|
generated by the l10n coordinator, but this file had been removed from
|
|
the tree.
|
|
|
|
The two POT files "po/git.pot" and "po/git-core.pot" can be created
|
|
dynamically when necessary.
|
|
|
|
L10n contributors use "po/git.pot" to prepare translations for their
|
|
languages, but they are not expected to modify it. The "po/git.pot" file
|
|
can be generated manually with the following command:
|
|
|
|
```shell
|
|
make po/git.pot
|
|
```
|
|
|
|
The "po/git-core.pot" file is the template for core translations. A core
|
|
translation is the minimum set of work necessary to complete a
|
|
translation of a new language. Since there are more than 5000 messages
|
|
in the full set of template message file "po/git.pot" that need to be
|
|
translated, this is not a piece of cake for new language contributors.
|
|
|
|
The "core" template file "po/git-core.pot" can be generated manually
|
|
by running:
|
|
|
|
```shell
|
|
make po/git-core.pot
|
|
```
|
|
|
|
|
|
## Initializing a "XX.po" file
|
|
|
|
(This is done by the language teams).
|
|
|
|
If your language XX does not have translated message file "po/XX.po" yet,
|
|
you add a translation for the first time by running:
|
|
|
|
```shell
|
|
make po-init PO_FILE=po/XX.po
|
|
```
|
|
|
|
where XX is the locale, e.g. "de", "is", "pt\_BR", "zh\_CN", etc.
|
|
|
|
The newly generated message file "po/XX.po" is based on the core pot
|
|
file "po/git-core.pot", so it contains only a minimal set of messages
|
|
and it's a good start for a new language contribution.
|
|
|
|
Once you are done testing the translation (see below), commit the result
|
|
and ask the l10n coordinator to pull from you.
|
|
|
|
|
|
## Updating a "XX.po" file
|
|
|
|
(This is done by the language teams).
|
|
|
|
If you are replacing translation strings in an existing "XX.po" file to
|
|
improve the translation, just edit the file.
|
|
|
|
If you want to find new translatable strings in source files of upstream
|
|
repository and propagate them to your "po/XX.po", run command:
|
|
|
|
```shell
|
|
make po-update PO_FILE=po/XX.po
|
|
```
|
|
|
|
It will:
|
|
|
|
- Call "make po/git.pot" to generate new "po/git.pot" file
|
|
- Call "msgmerge --add-location --backup=off -U po/XX.po po/git.pot"
|
|
to update your "po/XX.po"
|
|
- The "--add-location" option for msgmerge will add location lines,
|
|
and these location lines will help translation tools to locate
|
|
translation context easily.
|
|
|
|
Once you are done testing the translation (see below), it's better
|
|
to commit a location-less "po/XX.po" file to save repository space
|
|
and make a user-friendly patch for review.
|
|
|
|
To save a location-less "po/XX.po" automatically in repository, you
|
|
can:
|
|
|
|
First define a new attribute for "po/XX.po" by appending the following
|
|
line in ".git/info/attributes":
|
|
|
|
```
|
|
/po/XX.po filter=gettext-no-location
|
|
```
|
|
|
|
Then define the driver for the "gettext-no-location" clean filter to
|
|
strip out both filenames and locations from the contents as follows:
|
|
|
|
```shell
|
|
git config --global filter.gettext-no-location.clean \
|
|
"msgcat --no-location -"
|
|
```
|
|
|
|
For users who have gettext version 0.20 or higher, it is also possible
|
|
to define a clean filter to preserve filenames but not locations:
|
|
|
|
```shell
|
|
git config --global filter.gettext-no-location.clean \
|
|
"msgcat --add-location=file -"
|
|
```
|
|
|
|
You're now ready to ask the l10n coordinator to pull from you.
|
|
|
|
|
|
## Fuzzy translation
|
|
|
|
Fuzzy translation is a translation marked by comment "fuzzy" to let you
|
|
know that the translation is out of date because the "msgid" has been
|
|
changed. A fuzzy translation will be ignored when compiling using "msgfmt".
|
|
Fuzzy translation can be marked by hands, but for most cases they are
|
|
marked automatically when running "msgmerge" to update your "XX.po" file.
|
|
|
|
After fixing the corresponding translation, you must remove the "fuzzy"
|
|
tag in the comment.
|
|
|
|
|
|
## Testing your changes
|
|
|
|
(This is done by the language teams, after creating or updating "XX.po" file).
|
|
|
|
Before you submit your changes go back to the top-level and do:
|
|
|
|
```shell
|
|
make
|
|
```
|
|
|
|
On systems with GNU gettext (i.e. not Solaris) this will compile your
|
|
changed PO file with `msgfmt --check`, the --check option flags many
|
|
common errors, e.g. missing printf format strings, or translated
|
|
messages that deviate from the originals in whether they begin/end
|
|
with a newline or not.
|
|
|
|
L10n coordinator will check your contributions using a helper program
|
|
(see "PO helper" section below):
|
|
|
|
```shell
|
|
git-po-helper check-po po/XX.po
|
|
git-po-helper check-commits <rev-list-opts>
|
|
```
|
|
|
|
|
|
## Marking strings for translation
|
|
|
|
(This is done by the core developers).
|
|
|
|
Before strings can be translated they first have to be marked for
|
|
translation.
|
|
|
|
Git uses an internationalization interface that wraps the system's
|
|
gettext library, so most of the advice in your gettext documentation
|
|
(on GNU systems `info gettext` in a terminal) applies.
|
|
|
|
General advice:
|
|
|
|
- Don't mark everything for translation, only strings which will be
|
|
read by humans (the porcelain interface) should be translated.
|
|
|
|
The output from Git's plumbing utilities will primarily be read by
|
|
programs and would break scripts under non-C locales if it was
|
|
translated. Plumbing strings should not be translated, since
|
|
they're part of Git's API.
|
|
|
|
- Adjust the strings so that they're easy to translate. Most of the
|
|
advice in `info '(gettext)Preparing Strings'` applies here.
|
|
|
|
- Strings referencing numbers of items may need to be split into singular and
|
|
plural forms; see the Q\_() wrapper in the C sub-section below for an
|
|
example.
|
|
|
|
- If something is unclear or ambiguous you can use a "TRANSLATORS"
|
|
comment to tell the translators what to make of it. These will be
|
|
extracted by xgettext(1) and put in the "po/\*.po" files, e.g. from
|
|
git-am.sh:
|
|
|
|
```shell
|
|
# TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
|
|
# in your translation. The program will only accept English
|
|
# input at this point.
|
|
gettext "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
|
|
```
|
|
|
|
Or in C, from builtin/revert.c:
|
|
|
|
```c
|
|
/* TRANSLATORS: %s will be "revert" or "cherry-pick" */
|
|
die(_("%s: Unable to write new index file"), action_name(opts));
|
|
```
|
|
|
|
We provide wrappers for C, Shell and Perl programs. Here's how they're
|
|
used:
|
|
|
|
|
|
### C
|
|
|
|
Include builtin.h at the top, it'll pull in gettext.h, which
|
|
defines the gettext interface. Consult with the list if you need to
|
|
use gettext.h directly.
|
|
|
|
The C interface is a subset of the normal GNU gettext
|
|
interface. We currently export these functions:
|
|
|
|
- \_()
|
|
|
|
Mark and translate a string. E.g.:
|
|
|
|
```c
|
|
printf(_("HEAD is now at %s"), hex);
|
|
```
|
|
|
|
- Q\_()
|
|
|
|
Mark and translate a plural string. E.g.:
|
|
|
|
```c
|
|
printf(Q_("%d commit", "%d commits", number_of_commits));
|
|
```
|
|
|
|
This is just a wrapper for the ngettext() function.
|
|
|
|
- N\_()
|
|
|
|
A no-op pass-through macro for marking strings inside static
|
|
initializations, e.g.:
|
|
|
|
```c
|
|
static const char *reset_type_names[] = {
|
|
N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
|
|
};
|
|
```
|
|
|
|
And then, later:
|
|
|
|
```c
|
|
die(_("%s reset is not allowed in a bare repository"),
|
|
_(reset_type_names[reset_type]));
|
|
```
|
|
|
|
Here `_()` couldn't have statically determined what the translation
|
|
string will be, but since it was already marked for translation
|
|
with `N_()` the look-up in the message catalog will succeed.
|
|
|
|
|
|
### Shell
|
|
|
|
The Git gettext shell interface is just a wrapper for
|
|
gettext.sh. Import it right after git-sh-setup like this:
|
|
|
|
```shell
|
|
. git-sh-setup
|
|
. git-sh-i18n
|
|
```
|
|
|
|
And then use the `gettext` or `eval_gettext` functions:
|
|
|
|
```shell
|
|
# For constant interface messages:
|
|
gettext "A message for the user"; echo
|
|
|
|
# To interpolate variables:
|
|
details="oh noes"
|
|
eval_gettext "An error occurred: \$details"; echo
|
|
```
|
|
|
|
In addition we have wrappers for messages that end with a trailing
|
|
newline. I.e. you could write the above as:
|
|
|
|
```shell
|
|
# For constant interface messages:
|
|
gettextln "A message for the user"
|
|
|
|
# To interpolate variables:
|
|
details="oh noes"
|
|
eval_gettextln "An error occurred: \$details"
|
|
```
|
|
|
|
More documentation about the interface is available in the GNU info
|
|
page: `info '(gettext)sh'`. Looking at git-am.sh (the first shell
|
|
command to be translated) for examples is also useful:
|
|
|
|
```shell
|
|
git log --reverse -p --grep=i18n git-am.sh
|
|
```
|
|
|
|
|
|
### Perl
|
|
|
|
The Git::I18N module provides a limited subset of the
|
|
Locale::Messages functionality, e.g.:
|
|
|
|
```perl
|
|
use Git::I18N;
|
|
print __("Welcome to Git!\n");
|
|
printf __("The following error occurred: %s\n"), $error;
|
|
```
|
|
|
|
Run `perldoc perl/Git/I18N.pm` for more info.
|
|
|
|
|
|
## Testing marked strings
|
|
|
|
Git's tests are run under `LANG=C LC_ALL=C`. So the tests do not need be
|
|
changed to account for translations as they're added.
|
|
|
|
|
|
## PO helper
|
|
|
|
To make the maintenance of "XX.po" easier, the l10n coordinator and l10n
|
|
team leaders can use a helper program named "git-po-helper". It is a
|
|
wrapper to gettext suite, specifically written for the purpose of Git
|
|
l10n workflow.
|
|
|
|
To build and install the helper program from source, see
|
|
[git-po-helper/README][].
|
|
|
|
|
|
## Conventions
|
|
|
|
There are some conventions that l10n contributors must follow:
|
|
|
|
- The subject of each l10n commit should be prefixed with "l10n: ".
|
|
|
|
- Do not use non-ASCII characters in the subject of a commit.
|
|
|
|
- The length of commit subject (first line of the commit log) should
|
|
be less than 50 characters, and the length of other lines of the
|
|
commit log should be no more than 72 characters.
|
|
|
|
- Add "Signed-off-by" trailer to your commit log, like other commits
|
|
in Git. You can automatically add the trailer by committing with
|
|
the following command:
|
|
|
|
```shell
|
|
git commit -s
|
|
```
|
|
|
|
- Check syntax with "msgfmt" or the following command before creating
|
|
your commit:
|
|
|
|
```shell
|
|
git-po-helper check-po <XX.po>
|
|
```
|
|
|
|
- Squash trivial commits to make history clear.
|
|
|
|
- DO NOT edit files outside "po/" directory.
|
|
|
|
- Other subsystems ("git-gui", "gitk", and Git itself) have their
|
|
own workflow. See [Documentation/SubmittingPatches][] for
|
|
instructions on how to contribute patches to these subsystems.
|
|
|
|
|
|
To contribute for a new l10n language, contributor should follow
|
|
additional conventions:
|
|
|
|
- Initialize proper filename of the "XX.po" file conforming to
|
|
iso-639 and iso-3166.
|
|
|
|
- Must complete a minimal translation based on the "Core
|
|
translation". See that section above.
|
|
|
|
- Add a new entry in the "po/TEAMS" file with proper format, and check
|
|
the syntax of "po/TEAMS" by running the following command:
|
|
|
|
```shell
|
|
git-po-helper team --check
|
|
```
|
|
|
|
|
|
[git-po-helper/README]: https://github.com/git-l10n/git-po-helper#readme
|
|
[Documentation/SubmittingPatches]: Documentation/SubmittingPatches
|