Международная локализация
API WebExtensions имеет довольно удобный модуль для международной локализации расширений — i18n. В этой статье мы рассмотрим его возможности и предоставим практический пример того, как он работает. Система i18n для расширений, построенных с использованием API WebExtension, похожа на распространенные JavaScript-библиотеки для i18n, такие как i18n.js.
Примечание: Пример расширения, представленный в этой статье — notify-link-clicks-i18n — доступен на GitHub. Следите за исходным кодом, проходя по разделам ниже.
Архитектура интернационализированного расширения
Международное расширение может содержать те же функции, что и любое другое расширение — скрипты фонового процесса, скрипты содержимого и т. д. — но оно также имеет дополнительные части, позволяющие переключаться между различными языковыми локалями. Они суммированы в следующей структуре каталогов:
- корневой каталог расширения/
- _locales
- en
- messages.json
- Сообщения на английском языке (строки)
- messages.json
- de
- messages.json
- Сообщения на немецком языке (строки)
- messages.json
- и т.д.
- en
- manifest.json
- языково-зависимые метаданные
- myJavascript.js
- JavaScript для получения языка браузера, языково-специфических сообщений и т. д.
- myStyles.css
- языково-зависимые CSS-стили
- _locales
Давайте рассмотрим каждую из новых функций по очереди — каждый из следующих разделов представляет собой шаг, который необходимо выполнить при интернационализации вашего расширения.
Предоставление локализованных строк в _locales
Примечание: Вы можете найти теги языка, используя инструмент Найти на странице поиска тегов языка. Обратите внимание, что вам нужно искать английское название языка.
Любая система i18n требует предоставления строк, переведенных на все поддерживаемые вами языковые локали. В расширениях они хранятся в каталоге с именем _locales, расположенном в корневом каталоге расширения. Каждая отдельная локали имеет свои строки (называемые сообщениями), хранящиеся в файле с именем messages.json, расположенном в подкаталоге _locales, имя которого соответствует коду языка этой локали.
Обратите внимание, что если тег включает основной язык и региональный вариант, то язык и вариант обычно разделяются дефисом: например, "en-US". Однако в каталогах под _locales, разделителем должен быть знак подчеркивания: "en_US".
Так, например, в нашем примере приложения есть каталоги для "en" (английский), "de" (немецкий), "nl" (нидерландский) и "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 расширением. Вы узнаете, как это сделать, в разделе Получение строк сообщений из JavaScript.
Примечание: Более подробную информацию о содержимом файлов messages.json можно найти в нашей справке Локализованная справка по сообщениям.
Интернационализация manifest.json
Для интернационализации manifest.json необходимо выполнить несколько задач.
Получение локализованных строк в манифестах
Ваш manifest.json содержит строки, отображаемые пользователю, такие как имя и описание расширения. Если вы интернационализируете эти строки и поместите соответствующие переводы в messages.json, то браузер отобразит правильный перевод строки в зависимости от текущей локали, как показано ниже.
Для интернационализации строк используйте следующий синтаксис:
"name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__",
Здесь мы получаем строки сообщений, основанные на локали браузера, а не просто включаем статические строки.
Для вызова строки сообщения используйте следующий формат:
- Два символа подчеркивания, за которыми следует
- Строка "MSG", за которой следует
- Один символ подчеркивания, за которым следует
- Имя сообщения, определенного в
messages.json, за которым следует - Два символа подчеркивания
__MSG_ + messageName + __
Указание языка по умолчанию
Еще одно поле, которое необходимо указать в вашем manifest.json, — это default_locale:
"default_locale": "en"
Это указывает язык по умолчанию, который используется, если расширение не содержит локализованной строки для текущей локали браузера. Любые строки сообщений, отсутствующие в текущей локали браузера, берутся из языка по умолчанию. Более подробную информацию о том, как браузер выбирает строки, см. в разделе Выбор локализованной строки.
Языково-зависимые CSS-стили
Обратите внимание, что вы также можете получать локализованные строки из CSS-файлов расширения. Например, вы можете создать правило CSS, зависящее от локали, так:
header { background-image: url(../images/__MSG_extensionName__/header.png); }
Это полезно, хотя лучше использовать для таких ситуаций предопределенные сообщения.
Получение строк сообщений из JavaScript
Итак, вы настроили свои строки сообщений и ваш манифест. Теперь вам нужно начать вызывать ваши строки сообщений из JavaScript, чтобы ваше расширение могло общаться на правильном языке в максимально возможной степени. API i18n довольно простой и содержит всего четыре основных метода:
- Скорее всего, вы будете чаще использовать
i18n.getMessage()— этот метод используется для получения конкретной строки на языке, как упоминалось выше. Мы увидим конкретные примеры использования ниже. - Методы
i18n.getAcceptLanguages()иi18n.getUILanguage()могут использоваться, если вам нужно настроить интерфейс пользователя в зависимости от локали — возможно, вы захотите показать настройки, специфичные для предпочитаемых языков пользователей, в верхней части списка настроек, или отобразить культурную информацию, относящуюся только к определенным языкам, или отформатировать отображаемые даты в соответствии с локалью браузера. - Метод
i18n.detectLanguage()можно использовать для определения языка введённого пользователем контента и его соответствующего форматирования.
В нашем примере notify-link-clicks-i18n скрипт фонового процесса содержит следующие строки:
let title = browser.i18n.getMessage("notificationTitle"); let 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$ для его вызова внутри строки сообщения. Если у вас несколько плейсхолдеров, вы можете передать их в виде массива в i18n.getMessage() в качестве второго параметра. [a, b, c] будут доступны как $1, $2, и $3, и так далее, внутри messages.json.
Давайте пройдёмся по примеру. Исходная строка сообщения notificationContent в файле en/messages.json выглядит следующим образом:
You clicked $URL$.
Допустим, нажатая ссылка указывает на https://developer.mozilla.org. После вызова 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, и этот файл содержит строку, верните её. - В противном случае верните пустую строку.
Рассмотрим следующий пример:
- директория-корень-расширения/
- _locales
- en_GB
- messages.json
{ "colorLocalized": { "message": "colour", "description": "Color." }, /* … */ }
- messages.json
- en
- messages.json
{ "colorLocalized": { "message": "color", "description": "Color." }, /* … */ }
- messages.json
- fr
- messages.json
{ "colorLocalized": { "message": "couleur", "description": "Color." }, /* … */}
- messages.json
- en_GB
- _locales
Предположим, что default_locale установлено в fr, а текущая локали браузера — en_GB:
- Если расширение вызывает
getMessage("colorLocalized"), оно вернёт "цвет". - Если "colorLocalized" отсутствует в
en_GB, тоgetMessage("colorLocalized"), вернёт "цвет", а не "couleur".
Предопределённые сообщения
Модуль i18n предоставляет нам некоторые предопределённые сообщения, которые мы можем вызвать так же, как мы видели ранее в Получение локализованных строк в манифестах и Локализованные CSS. Например:
__MSG_extensionName__
Предопределённые сообщения используют точно такой же синтаксис, за исключением префикса @@ перед именем сообщения, например
__MSG_@@ui_locale__
В следующей таблице показаны различные доступные предопределённые сообщения:
| Название сообщения | Описание |
|---|---|
@@extension_id | Внутренне сгенерированный 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 или Firefox Beta, версии Firefox, в которых можно установить языковые пакеты.
Затем для каждой поддерживаемой локали расширения, которое вы хотите проверить, следуйте инструкциям по использованию Firefox на другом языке для переключения языка интерфейса Firefox. (Если вы знаете, как работать с настройками, в разделе «Язык» используйте «Установить альтернативы».)
После того, как Firefox будет запущен на вашем тестовом языке, временно установите расширение. После установки расширения в about:debugging, если вы правильно настроите расширение, вы увидите расширение в списке с его значком, названием и описанием на выбранном языке. Вы также можете увидеть локализованные сведения об расширении в about:addons. Теперь используйте функции расширения, чтобы убедиться, что необходимые переводы на месте.
Если вы хотите попробовать этот процесс, вы можете использовать расширение notify-link-clicks-i18n. Настройте Firefox для отображения одного из языков, поддерживаемых в этом примере (немецкий, голландский или японский). Загрузите расширение и перейдите на веб-сайт. Нажмите на ссылку, чтобы увидеть переведённую версию уведомления, сообщающего URL ссылки.
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization