Improve the Translation/Externalization documentation

Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
Rémy Coutable 2018-02-15 18:17:13 +01:00
parent ccbce7af7e
commit df029d4f73
2 changed files with 169 additions and 121 deletions

View File

@ -107,10 +107,139 @@ You can mark that content for translation with:
### JavaScript files
In JavaScript we added the `__()` (double underscore parenthesis) function
for translations.
In JavaScript we added the `__()` (double underscore parenthesis) function that
you can import from the `~/locale` file. For instance:
In order to test JavaScript translations you have to change the GitLab localization to other language than English and you have to generate JSON files using `bundle exec rake gettext:po_to_json` or `bundle exec rake gettext:compile`.
```js
import { __ } from '~/locale';
const label = __('Subscribe');
```
In order to test JavaScript translations you have to change the GitLab
localization to other language than English and you have to generate JSON files
using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
### Dynamic translations
Sometimes there are some dynamic translations that can't be found by the
parser when running `bin/rake gettext:find`. For these scenarios you can
use the [`N_` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind).
There is also and alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a).
## Working with special content
### Interpolation
- In Ruby/HAML:
```ruby
_("Hello %{name}") % { name: 'Joe' } => 'Hello Joe'
```
- In JavaScript:
```js
import { __, sprintf } from '~/locale';
sprintf(__('Hello %{username}'), { username: 'Joe' }) => 'Hello Joe'
```
The placeholders should match the code style of the respective source file.
For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript.
### Plurals
- In Ruby/HAML:
```ruby
n_('Apple', 'Apples', 3)
# => 'Apples'
```
Using interpolation:
```ruby
n_("There is a mouse.", "There are %d mice.", size) % size
# => When size == 1: 'There is a mouse.'
# => When size == 2: 'There are 2 mice.'
```
- In JavaScript:
```js
n__('Apple', 'Apples', 3)
// => 'Apples'
```
Using interpolation:
```js
n__('Last day', 'Last %d days', x)
// => When x == 1: 'Last day'
// => When x == 2: 'Last 2 days'
```
### Namespaces
Sometimes you need to add some context to the text that you want to translate
(if the word occurs in a sentence and/or the word is ambiguous).
- In Ruby/HAML:
```ruby
s_('OpenedNDaysAgo|Opened')
```
In case the translation is not found it will return `Opened`.
- In JavaScript:
```js
s__('OpenedNDaysAgo|Opened')
```
Note: The namespace should be removed from the translation. See the [translation
guidelines for more details](./translation.md#namespaced-strings).
### Dates / times
- In JavaScript:
```js
import { createDateTimeFormat } from '~/locale';
const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' });
console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063
```
This makes use of [`Intl.DateTimeFormat`].
[`Intl.DateTimeFormat`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
## Best practices
### Splitting sentences
Please never split a sentence as that would assume the sentence grammar and
structure is the same in all languages.
For instance, the following
```js
{{ s__("mrWidget|Set by") }}
<mr-widget-author :author="mr.setToMWPSBy" />
{{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }}
```
should be externalized as follows:
```js
{{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: '<mr-widget-author :author="mr.setToMWPSBy" />' }) }}
```
When in doubt, try to follow the best practices described in this [Mozilla
Developer documentation][mdn].
[mdn]: https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices#Splitting
## Updating the PO files with the new content
@ -118,7 +247,7 @@ Now that the new content is marked for translation, we need to update the PO
files with the following command:
```sh
bundle exec rake gettext:find
bin/rake gettext:find
```
This command will update the `locale/gitlab.pot` file with the newly externalized
@ -180,108 +309,6 @@ In this output the `locale/zh_HK/gitlab.po` has syntax errors.
The `locale/zh_TW/gitlab.po` has variables that are used in the translation that
aren't in the message with id `1 pipeline`.
## Working with special content
### Just marking content for parsing
- In Ruby/HAML:
```ruby
_('Subscribe')
```
- In JavaScript:
```js
import { __ } from '../../../locale';
const label = __('Subscribe');
```
Sometimes there are some dynamic translations that can't be found by the
parser when running `bundle exec rake gettext:find`. For these scenarios you can
use the [`_N` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind).
There is also and alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a).
### Interpolation
- In Ruby/HAML:
```ruby
_("Hello %{name}") % { name: 'Joe' } => 'Hello Joe'
```
- In JavaScript:
```js
import { __, sprintf } from '../../../locale';
sprintf(__('Hello %{username}'), { username: 'Joe' }) => 'Hello Joe'
```
The placeholders should match the code style of the respective source file.
For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript.
### Plurals
- In Ruby/HAML:
```ruby
n_('Apple', 'Apples', 3) => 'Apples'
```
Using interpolation:
```ruby
n_("There is a mouse.", "There are %d mice.", size) % size
```
- In JavaScript:
```js
n__('Apple', 'Apples', 3) => 'Apples'
```
Using interpolation:
```js
n__('Last day', 'Last %d days', 30) => 'Last 30 days'
```
### Namespaces
Sometimes you need to add some context to the text that you want to translate
(if the word occurs in a sentence and/or the word is ambiguous).
- In Ruby/HAML:
```ruby
s_('OpenedNDaysAgo|Opened')
```
In case the translation is not found it will return `Opened`.
- In JavaScript:
```js
s__('OpenedNDaysAgo|Opened')
```
### Dates / times
- In JavaScript:
```js
import { createDateTimeFormat } from '.../locale';
const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' });
console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063
```
This makes use of [`Intl.DateTimeFormat`].
[`Intl.DateTimeFormat`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
## Adding a new language
Let's suppose you want to add translations for a new language, let's say French.
@ -300,14 +327,14 @@ Let's suppose you want to add translations for a new language, let's say French.
1. Next, you need to add the language:
```sh
bundle exec rake gettext:add_language[fr]
bin/rake gettext:add_language[fr]
```
If you want to add a new language for a specific region, the command is similar,
you just need to separate the region with an underscore (`_`). For example:
```sh
bundle exec rake gettext:add_language[en_GB]
bin/rake gettext:add_language[en_GB]
```
Please note that you need to specify the region part in capitals.
@ -321,7 +348,7 @@ Let's suppose you want to add translations for a new language, let's say French.
containing the translations:
```sh
bundle exec rake gettext:compile
bin/rake gettext:compile
```
1. In order to see the translated content we need to change our preferred language

View File

@ -37,33 +37,43 @@ Comments can be added to discuss a translation with the community.
Remember to **Save** each translation.
## Translation Guidelines
## General Translation Guidelines
Be sure to check the following guidelines before you translate any strings.
### Namespaced strings
When an externalized string is prepended with a namespace, e.g.
`s_('OpenedNDaysAgo|Opened')`, the namespace should be removed from the final
translation.
For example in French `OpenedNDaysAgo|Opened` would be translated to
`Ouvert•e`, not `OpenedNDaysAgo|Ouvert•e`.
### Technical terms
Technical terms should be treated like proper nouns and not be translated.
This helps maintain a logical connection and consistency between tools (e.g. `git` client) and
GitLab.
Some technical terms should be treated like proper nouns and not be translated.
Technical terms that should always be in English are noted in the glossary when using
[translate.gitlab.com](https://translate.gitlab.com).
Technical terms that should always be in English are noted in the glossary when
using [translate.gitlab.com](https://translate.gitlab.com).
This helps maintain a logical connection and consistency between tools (e.g.
`git` client) and GitLab.
### Formality
The level of formality used in software varies by language.
For example, in French we translate `you` as the informal `tu`.
For example, in French we translate `you` as the formal `vous`.
You can refer to other translated strings and notes in the glossary to assist determining a
suitable level of formality.
You can refer to other translated strings and notes in the glossary to assist
determining a suitable level of formality.
### Inclusive language
[Diversity] is one of GitLab's values.
We ask you to avoid translations which exclude people based on their gender or ethnicity.
In languages which distinguish between a male and female form,
use both or choose a neutral formulation.
We ask you to avoid translations which exclude people based on their gender or
ethnicity.
In languages which distinguish between a male and female form, use both or
choose a neutral formulation.
For example in German, the word "user" can be translated into "Benutzer" (male) or "Benutzerin" (female).
Therefore "create a new user" would translate into "Benutzer(in) anlegen".
@ -74,3 +84,14 @@ Therefore "create a new user" would translate into "Benutzer(in) anlegen".
To propose additions to the glossary please
[open an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues).
## French Translation Guidelines
### Inclusive language in French
In French, we should follow the guidelines from [ecriture-inclusive.fr]. For
instance:
- Utilisateur•rice•s
[ecriture-inclusive.fr]: http://www.ecriture-inclusive.fr/