--- title: Интернационализация slug: Mozilla/Add-ons/WebExtensions/Internationalization translation_of: Mozilla/Add-ons/WebExtensions/Internationalization original_slug: Mozilla/Add-ons/WebExtensions/Интернационализация ---
API WebExtensions предоставляет полезный модуль для интернационализации расширений — i18n. В этой статье мы рассмотрим его особенности и пример его работы. Система для расширений, построенных с помощью API WebExtension, i18n похожа на библиотеки JavaScript для i18n, такие как i18n.js.
Расширение, используемое в этой статье в качестве примера, — notify-link-clicks-i18n — доступно на GitHub. Читая последующие секции этой статьи, Вы можете исследовать его исходный код.
Интернационализированное расширение может содержать такие же элементы, как и любое другое расширение — фоновые скрипты, встраиваемые скрипты, и т. д. — а также дополнительные инструменты, позволяющие переключаться между разными локализациями. Их можно представить следующим деревом директорий:
Давайте отдельно рассмотрим каждый элемент — последующие секции представляют собой шаги, которым стоит следовать во время интернационализации вашего расширения.
Каждая система i18n требует предоставить строки во всех локализациях, которые Вы хотите поддерживать. В расширениях они хранятся в директории _locales, размещённой внутри корневой директории. Строки каждой локализации (также называемые сообщениями) хранятся в файле messages.json, находящемся в поддиректории _locales, название которой - тег языка локализации.
Стоит заметить, что если тег включает в себя и базовый язык, и его региональный вариант, то по конвенции эти язык и вариант разделяются дефисом: например, "en-US". Однако в поддиректориях _locales, вместо дефиса используется нижнее подчёркивание: "en_US".
Таким образом, в нашем примере существую директории "en" (английский), "de" (немецкий), "nl" (голландский), and "ja" (японский). Внутри каждой из них находится файл messages.json .
Давайте рассмотрим структуру одного из этих файлов (_locales/en/messages.json):
{
"extensionName": {
"message": "Notify link clicks i18n",
"description": "Name of the extension."
},
"extensionDescription": {
"message": "Shows a notification when the user clicks on links.",
"description": "Description of the extension."
},
"notificationTitle": {
"message": "Click notification",
"description": "Title of the click notification."
},
"notificationContent": {
"message": "You clicked $URL$.",
"description": "Tells the user which link they clicked.",
"placeholders": {
"url" : {
"content" : "$1",
"example" : "https://developer.mozilla.org"
}
}
}
}
Это стандартный файл JSON — каждый из его элементов является объектом с именем, содержащим сообщение (message) и описание (description). Оба предмета - строки; $URL$ — это заполнитель, который заменяется подстрокой, когда элемент notificationContent вызывается расширением. Вы научитесь это делать в секции {{anch("Получение сообщений из JavaScript")}}.
Примечание: Вы можете найти больше информации о структуре messages.json здесь.
Для интернационализации файла manifest.json нужно предпринять несколько шагов.
Ваш файл manifest.json содержит строки, отображаемые пользователю, такие как имя и описание расширения. Если Вы интернационализируете эти строки и поместите их переводы в messages.json, то эти переводы будут отображаться пользователю в зависимости от локализации его браузера.
Чтобы интернационализировать строки, их нужно указывать следующим образом:
"name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__",
Здесь мы получаем сообщения, зависящие от локализации браузера, а не просто статические строки.
Чтобы получить строку сообщения, её нужно указать следующим образом:
messages.json__MSG_ + messageName + __
Ещё одно поле. которое нужно указать в manifest.json — это default_locale:
"default_locale": "en"
Этот параметр устанавливает локализацию по умолчанию, используемую, если расширение не поддерживает локализацию браузера пользователя. Любые сообщения, недоступные в текущей локализации, будут браться из той локализации, которая установлена по умолчанию. There are some more details to be aware of in terms of how the browser selects strings — see {{anch("Выбор локализованной строки")}}.
Локализованные строки также можно получить из CSS-файлов расширения. Например, Вы можете создать поля CSS, зависящие от локализации, так:
header {
background-image: url(../images/__MSG_extensionName__/header.png);
}
Этот функционал может быть полезен, однако, возможно, для этих целей стоит использовать {{anch("Заранее определённые сообщения")}}.
Допустим, Вы добавили сообщения в Ваш manifest.json. Чтобы Ваше расширение начало использовать правильные языки, соответствующие сообщения следует вызывать при помощи JavaScript. API i18n достаточно прост и содержит всего 4 основных метода:
В нашем примере notify-link-clicks-i18n , фоновый скрипт содержит следующие строки:
var title = browser.i18n.getMessage("notificationTitle");
var content = browser.i18n.getMessage("notificationContent", message.url);
Первая из них получает поле notificationTitle message из доступного файла messages.json, соответствующее наиболее подходящей локализации . Вторая строка похожа на первую, но в ней метод принимает URL в качестве второго параметра. Зачем? С помощью этого параметра мы указываем, на что нужно заменить заполнитель $URL$ в поле notificationContent message:
"notificationContent": {
"message": "You clicked $URL$.",
"description": "Tells the user which link they clicked.",
"placeholders": {
"url" : {
"content" : "$1",
"example" : "https://developer.mozilla.org"
}
}
}
Объект "placeholders" определяет все заполнители и то, откуда их нужно получать. Заполнитель "url" указывает, что информация о нем должна содержаться в $1 — первое значение, заданное внутри второго параметра getMessage(). Поскольку заполнитель называется "url", $URL$ используется для его вызова внутри сообщения (то есть для заполнителя "name" нужно использовать $NAME$, и т. д.). Если Вы хотите задать значения нескольких заполнителей, их можно передавать во второй аргумент {{WebExtAPIRef("i18n.getMessage()")}} в виде массива — массив [a, b, c] передаёт значения $1, $2 и $3, и т. д. внутрь messages.json.
Давайте посмотрим на пример: изначально сообщение notificationContent в файле en/messages.json такое:
You clicked $URL$.
Пусть эта ссылка указывает на https://developer.mozilla.org. После вызова {{WebExtAPIRef("i18n.getMessage()")}}, содержание второго параметра становится доступно в messages.json в качестве значения $1, замещающего $URL$, так как это указано в заполнителе "url". Таким образом, итоговое значение строки:
You clicked https://developer.mozilla.org.
Переменные ($1, $2, $3, и т. д.) можно вставлять напрямую в сообщения. Например, можно переписать объект "notificationContent" следующим образом:
"notificationContent": {
"message": "You clicked $1.",
"description": "Tells the user which link they clicked."
}
Этот метод может показаться более быстрым и простым, но другой способ (использование "placeholders") считается лучшей практикой. Это вызвано тем, что имена заполнителей (например "url") и примеры помогают понять, что означают заполнители — через неделю после написания кода Вы, наверное, забудете, что обозначают заполнители $1–$8, что менее вероятно, если заполнители именованы.
Значения заполнителей можно задавать вручную, если Вы хотите, чтобы каждый раз это значение было одним и тем же, а не определялось переменной в коде. Например:
"mdn_banner": {
"message": "For more information on web technologies, go to $MDN$.",
"description": "Tell the user about MDN",
"placeholders": {
"mdn": {
"content": "https://developer.mozilla.org/"
}
}
}
В этом примере мы сами задаём значение заполнителя, а не получаем его из переменной, такой как $1. Это может быть полезно, если сообщение очень сложное, и Вы хотите разделить значения, чтобы сделать строки более читаемыми. К тому же, доступ к этим значениям можно получить внутри программы.
Вы также можете использовать такие замены для указания частей строки, не нуждающихся в переводе, таких как имена или названия.
Локализации могут быть указаны с помощью кода языка, например fr или en. Они также могут содержать региональный код, например en_US или en_GB, описывающий региональный вариант языка. Когда вы запрашиваете строку у системы i18n, системы возвращает её используя следующий алгоритм:
messages.json, содержащий требуемую строку, возвращается она.en_US) и существует файл messages.json для этого языка, но без указания региона (например en), содержащий строку, возвращается она.messages.json для default_locale, указанной в manifest.json, и этот файл содержит нужную строку, возвращается она.Рассмотрим следующий пример:
{ "colorLocalised": { "message": "colour", "description": "Color." }, ... }{ "colorLocalised": { "message": "color", "description": "Color." }, ... }{ "colorLocalised": { "message": "couleur", "description": "Color." }, ...}Пусть default_locale установлен как fr, а текущая локализация браузера — en_GB:
getMessage("colorLocalised") вернёт "colour".en_GB не было "colorLocalized", то вызов getMessage("colorLocalised"), вернул бы "color", а не "couleur".Модуль i18n module предоставляет заранее определённые сообщения, которые можно вызвать таким же образом, как мы это делали в разделе {{anch("Интернационализация manifest.json")}}. Например:
__MSG_extensionName__
Заранее определённые сообщения используют такой же синтаксис, за исключением @@ перед именем сообщения, например:
__MSG_@@ui_locale__
Следующая таблица содержит различные заранее определённые сообщения:
| Message name | Description |
|---|---|
@@extension_id |
Внутренний UUID расширения. Эту строку можно использовать для создания URL ресурсов внутри расширения.Даже нелокализованные расширения могут использовать это сообщения. Это сообщения нельзя использовать в manifest.json. Также стоит заметить, что этот ID — не ID аддона, которое возвращает {{WebExtAPIRef("runtime.id")}}, и которое может быть установлено с помощью ключа applications в manifest.json. Это сгенерированный UUID, содержащийся в URL аддона. Это означает, что данную величину нельзя использовать в качестве параметра |
@@ui_locale |
Текущая локализация; эту строку можно использовать для создания URL, зависящих от локализации. |
@@bidi_dir |
Направления чтения, либо "ltr" для языков, таких как английский, где текст читается слева направо, либо "rtl" для языков, считающихся справа налево, таких как арабский. |
@@bidi_reversed_dir |
Если @@bidi_dir имеет значение "ltr", то возвращает "rtl"; иначе "ltr". |
@@bidi_start_edge |
Если @@bidi_dir имеет значение "ltr", то возвращает "left"; иначе "right". |
@@bidi_end_edge |
Если @@bidi_dir имеет значение "ltr", то возвращает "right"; иначе "left". |
Возвращаясь к нашему примеру, лучше было бы написать:
header {
background-image: url(../images/__MSG_@@ui_locale__/header.png);
}
Теперь мы можем хранить изображения в директориях поддерживаемых локализаций — en, de, и т. д. — что выглядит логичней.
Давайте рассмотрим пример использования сообщений @@bidi_* в файле CSS:
body {
direction: __MSG_@@bidi_dir__;
}
div#header {
margin-bottom: 1.05em;
overflow: hidden;
padding-bottom: 1.5em;
padding-__MSG_@@bidi_start_edge__: 0;
padding-__MSG_@@bidi_end_edge__: 1.5em;
position: relative;
}
Для языков, в которых текст читается слева направо, таких как английский, правила CSS, использующие заранее определённые сообщения, сверху задают такие значения:
direction: ltr; padding-left: 0; padding-right: 1.5em;
Для языков, читающихся справа налево, значения будут следующими:
direction: rtl; padding-right: 0; padding-left: 1.5em;
Начиная с Firefox 45, расширения могут быть временно установлены с диска — подробнее об этом написано в статье Loading from disk. Сделайте это и попробуйте протестировать наше расширение notify-link-clicks-i18n. Перейдите на одну из Ваших любимых страниц и нажмите на ссылку, чтобы проверить, появляется ли сообщения, содержащее URL нажатой ссылки.
Затем измените локализацию Firefox на какую-либо поддерживающуюся расширением, которое Вы хотите протестировать.
intl.locale.requested (обратите внимание на версию Firefox: в версиях до Firefox 59 этот параметр называется general.useragent.locale)."") в качестве значения. В этом случае браузер выберет язык Вашей ОС по умолчанию.intl.locale.requested не существует, нажмите правой кнопкой мыши на список параметров (или откройте контекстное меню при помощи клавиатуры), и выберите "New", а затем "String". Введите intl.locale.requested как имя настройки и, "de", "nl", и т. д. как значение, как это описано в шаге 2.intl.locale.matchOS и, если параметр существует и равен true, дважды нажмите на него и установите на false.Примечание: Этот метод работает, даже если у Вас не установлен языковой пакет для выбранного языка. В этом случае UI браузера просто будет использовать Ваш язык по умолчанию.
Примечание: Чтобы изменить результат getUILanguage требуется языковой пакет, поскольку он отражает язык UI браузера, а не язык сообщений расширения.
Ещё раз загрузите расширение с диска и протестируйте локализацию:
{{EmbedYouTube("R7--fp5pPGg")}}