Локализация JavaScript/TypeScript
Введение
Подключение функции rk в компоненте
В первую очередь нужно подключить функцию для перевода с помощью RequireJS плагин i18n!. Зависимость должна содержать имя интерфейсного модуля, чей словарь вы хотите использовать.
- JavaScript
define('SBIS3/Demo/NewButton', [ ..., 'i18n!SBIS3'], function(..., rk) {...});
- TypeScript
import rk = require('i18n!SBIS3');
...
Локализация на сервере
При построении компонентов на сервере следует иметь в виду, что прототип компонента будет общим для всех языков, на которые будет осуществляться перевод. Поэтому существует ограничение на объявление локализуемых свойств класса: нельзя использовать конструкции, выполняющие приведение типов, например конкатенацию строк:
caption: rk('Скачать') + '...'
Нужно, чтобы переводимая фраза целиком передавалась аргументом в функцию rk()
:
caption: rk('Скачать...')
Связано это с тем, что на сервере функция rk()
возвращает не обычную строку, а объект, строковое значение которого вычисляется "лениво" при приведении к типу "Строка". Поэтому прототип класса должен хранить переводимые свойства в экземплярах подобных объектов, а не строк.
Локализация опций и переменных шаблона компонента
Значение опции компонента может быть локализовано в следующих случаях:
- В JS-модуле компонента для опции создан доклет с тегом
@translatable
и начальное значение обёрнуто в функциуюrk()
. Доклет должен начинаться с тега @cfg, чтобы описание было корректно интерпретировано (см. Документирование опции).
/**
* @cfg {String} Устанавливает надпись на кнопке.
* @translatable
*/
caption: rk('Скачать')
* Когда для локализации определён контекст перевода:
<pre class="brush: js">
/**
* @cfg {String} Устанавливает надпись на кнопке.
* @translatable
*/
caption: rk('Скачать', 'Кнопка на главной странице')
</pre>
- В разметке компонента значение опции обёрнуто в конструкции вида {[ ... ]} (см. Локализация WML).
<SBIS3.Demo.NewButton caption="{[Загрузить]}" />
* Когда выполнено условие из пункта 1, оборачивать значение опции компонента необязательно (за исключением случая с [опциями типа Content](/doc/platform/developmentapl/interface-development/internalization/javascript-localization/#localization-of-component-options-content)).
<pre class="brush: html">
<SBIS3.Demo.NewButton caption="Загрузить" />
</pre>
Локализация @typedef
Чтобы локализовать опции собственных типов данных, которые определены в @typedef, их перечисляют через одинарный пробел в теге @translatable.
/**
* @typedef {Object} Columns
* @property {String} title
* @property {String} field
* @property {String|Boolean} extendedTooltip
* @translatable title extendedTooltip
*/
Локализация строковых констант
Для локализации строковых констант используйте функцию rk()
.
console.log(rk('Аналитик', 'ИмяРоли'));
где "Аналитик" — локализуемая строка, а "ИмяРоли" — контекст перевода.
Конкатенация строк
В исходном JavaScript коде можно встретить склеенные строки следующим образом:
throw Error(rk('Ошибка: "') + message + rk('" с кодом ') + code);
Из-за того, что строки формируются динамически, и в rk нельзя передавать переменные, для их локализации рекомендуется использовать функцию template:
import {template} from 'Types/formatter';
const errorString = rk('Задача №${id} уже находится в статусе "${status}".');
throw new Error(template(errorString, {
id: 42,
status: rk('Выполнение')
}));
При локализации, например, на английский язык, в словаре переводов en-US.json ключи локализации и его перевод будут такими:
{
"Задача №${id} уже находится в статусе \"${status}\"." : "The task with id ${id} has \"${status}\" state already",
"Выполнение": "In progress"
}
Локализация дат
Используйте Types/formatter:date.
// My/SampleControl.ts
import {Control, TemplateFunction} from 'UI/Base';
import {date as format} from 'Types/formatter';
import template = require('wml!My/SampleTemplate');
export default class SampleControl extends Control {
protected _template: TemplateFunction = template;
protected _format: Function = format;
protected _article: object = {};
protected _beforeMount(): void {
this._article.created= new Date();
}
}
<!-- WML -->
This article was created at {{ _format(_article.created, _format.FULL_DATETIME) }}.
Склонение слова в зависимости от числа
Ранее задачу изменения формы слова Вы могли решать с использованием функции wordCaseByNumber. Однако использование этой функции признано устаревшим способом, в скором времени она будет удалена из веб-фреймворка WS.
require(['Core/helpers/i18n/wordCaseByNumber'], function(wordCaseByNumber) {
console.log(wordCaseByNumber(10, 'рублей', 'рубль', 'рубля')); // 'рублей'
});
В функции rk()
доступен необязательный числовой параметр, от значения которого можно установить соответствующую форму слова для текущей локализации.
// новый формат вызова функции
rk(stringToLocalization, contextString, number)
// второй вариант вызова функции, где второй аргумент number — число
rk(stringToLocalization, number)
При склонении слова в зависимости от числа предполагается, что исходная строка stringToLocalization
будет следующего вида: запись(-и, -ей)
. К исходной строке добавляются скобки с вариантами окончания слова. Такой вид строки нужен только для того, чтобы выделить её среди остальных в словаре переводов. Добавленные в скобках окончания никак не повлияют на перевод или форму слова при локализации. Если на сервисе отключена локализация, то строка будет выводиться в исходном виде.
Чтобы через функцию rk()
добавить склонение слова в зависимости от числа, Вам нужно:
- В исходном коде обернуть строку функцией
rk()
.
// число, которое соответствует форме склоняемого слова
var numberOfRecords;
...
tooltip: format(rk('В таблице БД хранится $n$s$ $row$s$'),
object = {
n: numberOfRecords ,
row: rk("запись(-и,-ей)", numberOfRecords)
});
- В словарях перевода компонента: ru-RU.json (для локализации на русском языке), en-US.json (для локализации на английском языке) и других — добавить "ключ:значение" (см. Правила):
/* ru-RU.json */
{
"plural#запись(-и,-ей)": "запись|записи|записей|записи"
}
/* en-US.json */
{
"plural#запись(-и,-ей)": "record|records"
}
В этом случае вызов функции rk('запись(-и,-ей)', 21) вернет для локализации:
- на русском языке — "запись";
- на английском языке — "records";
- на стенде без локализации — "запись(-и,-ей)".
Правила добавления строки в словарь переводов для назначения разных форм слова и их локализации
В словарь переводов локализуемую строку добавляют с префиксом plural, которые разделяются символом # (решётка). В качестве перевода устанавливают строку, которая содержит слова в нужных склонениях, разделенные через | (pipe, вертикальная линия).
/* ru-RU.json */
"plural#запись(-и,-ей)": "запись|записи|записей|записи"
/* en-US.json */
"plural#запись(-и,-ей)": "record|records"
Для локализации на русском языке используются 4 слова, располагающиеся в следующем порядке:
- для единицы. Например одна "запись" или один "день".
- для диапазона от 2 до 4. Например две "записи" или два "дня".
- для диапазона от 5 до 9. Например пять "записей" или пять "дней".
- для дроби. Например полторы "записи" или полтора "дня".
Для локализации на английском языке используется 2 слова, располагающиеся в следующем порядке:
- Первое слово — для единицы. Например one "record".
- Второе слово — для нескольких. Например two "records".
Правила для остальных языков Вы можете найти здесь. Сейчас для локализации поддерживаются только русский и английский языки.
Если в функции rk мы указываем контекст и количество для склонения, то в словаре должно быть записано:
"Контекст@@plural#запись(-и,-ей)": "record|records"
Пробелы и управляющие символы в начале и в конце локализуемых строк
Для строковых констант, которые планируется локализовать, устанавливается особое требование в использовании пробелов и управляющих символов ("\t" — горизонтальная табуляция; "\n" — перевод строки; "\r" — возврат каретки.) в начале и в конце таких строк:
- Локализуемая строка не должна содержать символы пробелов в начале или в конце:
// Неправильно
rk(' Текст ')
// Правильно
rk('Текст')
- Локализуемая строка не должна содержать символы перевода строки.
// Неправильно
rk('\nТекст')
// Правильно
'\n' + rk('Текст')
Ключи с невидимыми символами на концах строки сильно затруднят перевод. Например, строки "Сохранить", "\nСохранить" и " Сохранить" придётся переводить отдельно.