mirror of https://github.com/zulip/zulip.git
docs: Update documentation for FormatJS migration.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
d8a36d0702
commit
9cae3450ff
|
@ -277,8 +277,6 @@ function in those scenarios, add it to `zulip_test`. This is also
|
|||
[Jinja2]: http://jinja.pocoo.org/
|
||||
[Handlebars]: https://handlebarsjs.com/
|
||||
[trans]: http://jinja.pocoo.org/docs/dev/templates/#i18n
|
||||
[i18next]: https://www.i18next.com
|
||||
[official]: https://www.i18next.com/plurals.html
|
||||
[jconditionals]: http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures
|
||||
[hconditionals]: https://handlebarsjs.com/guide/#block_helpers.html
|
||||
[translation]: ../translating/translating.md
|
||||
|
|
|
@ -77,7 +77,7 @@ The end-to-end tooling process for translations in Zulip is as follows.
|
|||
[frontend](#frontend-translations) translations for details on
|
||||
this).
|
||||
|
||||
2. Translation [resource][] files are created using the `./manage.py
|
||||
2. Translation resource files are created using the `./manage.py
|
||||
makemessages` command. This command will create, for each language,
|
||||
a resource file called `translations.json` for the frontend strings
|
||||
and `django.po` for the backend strings.
|
||||
|
@ -208,73 +208,46 @@ Zulip linter (`tools/lint`) attempts to verify correct usage.
|
|||
|
||||
## Frontend translations
|
||||
|
||||
We use the [i18next][] library for frontend translations when dealing
|
||||
We use the [FormatJS][] library for frontend translations when dealing
|
||||
with [Handlebars][] templates or JavaScript.
|
||||
|
||||
To mark a string translatable in JavaScript files, pass it to the
|
||||
`i18n.t` function.
|
||||
`intl.formatMessage` function, which we alias to `$t` in `intl.js`:
|
||||
|
||||
```
|
||||
i18n.t('English Text', context);
|
||||
```js
|
||||
$t({defaultMessage: "English Text"})
|
||||
```
|
||||
|
||||
Variables in a translated frontend string are enclosed in
|
||||
double-underscores, like `__variable__`:
|
||||
The string to be translated must be a constant literal string, but
|
||||
variables can be interpolated by enclosing them in braces (like
|
||||
`{variable}`) and passing a context object:
|
||||
|
||||
```
|
||||
i18n.t('English text with a __variable__', {'variable': 'Variable value'});
|
||||
```js
|
||||
$t({defaultMessage: "English text with a {variable}"}, {variable: "Variable value"})
|
||||
```
|
||||
|
||||
`i18next` also supports plural translations. To support plurals make
|
||||
sure your resource file contains the related keys:
|
||||
FormatJS uses the standard [ICU MessageFormat][], which includes
|
||||
useful features such as plural translations.
|
||||
|
||||
`$t` does not escape any variables, so if your translated string is
|
||||
eventually going to be used as HTML, use `$t_html` instead.
|
||||
|
||||
```js
|
||||
$("#foo").html(
|
||||
$t_html({defaultMessage: "HTML with a {variable}"}, {variable: "Variable value"})
|
||||
);
|
||||
```
|
||||
{
|
||||
"en": {
|
||||
"translation": {
|
||||
"key": "item",
|
||||
"key_plural": "items",
|
||||
"keyWithCount": "__count__ item",
|
||||
"keyWithCount_plural": "__count__ items"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With this resource you can show plurals like this:
|
||||
|
||||
```
|
||||
i18n.t('key', {count: 0}); // output: 'items'
|
||||
i18n.t('key', {count: 1}); // output: 'item'
|
||||
i18n.t('key', {count: 5}); // output: 'items'
|
||||
i18n.t('key', {count: 100}); // output: 'items'
|
||||
i18n.t('keyWithCount', {count: 0}); // output: '0 items'
|
||||
i18n.t('keyWithCount', {count: 1}); // output: '1 item'
|
||||
i18n.t('keyWithCount', {count: 5}); // output: '5 items'
|
||||
i18n.t('keyWithCount', {count: 100}); // output: '100 items'
|
||||
```
|
||||
|
||||
For further reading on plurals, read the [official] documentation.
|
||||
|
||||
By default, all text is escaped by i18next. To unescape a text you can use
|
||||
double-underscores followed by a dash and space `__- ` like this:
|
||||
|
||||
```
|
||||
i18n.t('English text with a __- variable__', {'variable': 'Variable value'});
|
||||
```
|
||||
|
||||
For more information, you can read the official [unescape] documentation.
|
||||
|
||||
### Handlebars templates
|
||||
|
||||
For translations in Handlebars templates we also use `i18n.t`, through two
|
||||
For translations in Handlebars templates we also use FormatJS, through two
|
||||
Handlebars [helpers][] that Zulip registers. The syntax for simple strings is:
|
||||
|
||||
```
|
||||
{{t 'English Text' }}
|
||||
```
|
||||
|
||||
If you are passing a translated string to a Handlebars Partial, you can use:
|
||||
If you are passing a translated string to a Handlebars partial, you can use:
|
||||
|
||||
```
|
||||
{{> template_name
|
||||
|
@ -291,25 +264,23 @@ The syntax for block strings or strings containing variables is:
|
|||
|
||||
var context = {'variable': 'variable value'};
|
||||
{{#tr context}}
|
||||
Block of English text with a __variable__.
|
||||
Block of English text with a {variable}.
|
||||
{{/tr}}
|
||||
```
|
||||
|
||||
Just like in JavaScript code, variables are enclosed in double
|
||||
underscores `__`.
|
||||
Just like in JavaScript code, variables are enclosed in *single*
|
||||
braces (rather than the usual Handlebars double braces). Unlike in
|
||||
JavaScript code, variables are automatically escaped by our Handlebars
|
||||
helper.
|
||||
|
||||
Handlebars expressions like `{{variable}}` or blocks like
|
||||
`{{#if}}...{{/if}}` aren't permitted inside a `{{#tr}}...{{/tr}}`
|
||||
translated block, because they don't work properly with translation.
|
||||
The Handlebars expression would be evaluated before the string is
|
||||
processed by `i18n.t`, so that the string to be translated wouldn't be
|
||||
processed by FormatJS, so that the string to be translated wouldn't be
|
||||
constant. We have a linter to enforce that translated blocks don't
|
||||
contain handlebars.
|
||||
|
||||
The rules for plurals are same as for JavaScript files. You just have
|
||||
to declare the appropriate keys in the resource file and then include
|
||||
the `count` in the context.
|
||||
|
||||
## Transifex config
|
||||
|
||||
The config file that maps the resources from Zulip to Transifex is
|
||||
|
@ -339,11 +310,9 @@ organizations from the command line.
|
|||
[Jinja2]: http://jinja.pocoo.org/
|
||||
[Handlebars]: https://handlebarsjs.com/
|
||||
[trans]: http://jinja.pocoo.org/docs/dev/templates/#i18n
|
||||
[i18next]: https://www.i18next.com
|
||||
[official]: https://www.i18next.com/plurals.html
|
||||
[unescape]: https://www.i18next.com/interpolation.html#unescape
|
||||
[FormatJS]: https://formatjs.io/
|
||||
[ICU MessageFormat]: https://formatjs.io/docs/intl-messageformat
|
||||
[helpers]: https://handlebarsjs.com/guide/block-helpers.html
|
||||
[resource]: https://www.i18next.com/add-or-load-translations.html
|
||||
[Transifex]: https://transifex.com
|
||||
[transifexrc]: https://docs.transifex.com/client/client-configuration#transifexrc
|
||||
[html-templates]: ../subsystems/html-css.html#html-templates
|
||||
|
|
|
@ -291,7 +291,7 @@ channel.patch({
|
|||
data: data,
|
||||
success: function (response_data) {
|
||||
if (response_data.name !== undefined) {
|
||||
ui_report.success(i18n.t("Name changed!"), name_status);
|
||||
ui_report.success($t({defaultMessage: "Name changed!"}), name_status);
|
||||
}
|
||||
...
|
||||
```
|
||||
|
|
|
@ -20,9 +20,8 @@ page_params.translation_data = {
|
|||
|
||||
// All of our other tests stub out i18n activity;
|
||||
// here we do a quick sanity check on the engine itself.
|
||||
// We use `i18n.js` to initialize `i18next` and
|
||||
// to set `i18n` to `i18next` on the global namespace
|
||||
// for `templates.js`.
|
||||
// `i18n.js` initializes FormatJS and is imported by
|
||||
// `templates.js`.
|
||||
unmock_module("../../static/js/i18n");
|
||||
const {$t, $t_html} = zrequire("i18n");
|
||||
zrequire("templates");
|
||||
|
|
Loading…
Reference in New Issue