--- 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")}}