От переводчика: Это девятая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.
- "Охотимся за утечками памяти в Node.js"
- "Нагружаем Node под завязку"
- "Храним сессии на клиенте, чтобы упростить масштабирование приложения"
- "Производительность фронтэнда. Часть 1 — конкатенация, компрессия, кэширование"
- "Пишем сервер, который не падает под нагрузкой"
- "Производительность фронтэнда. Часть 2 — кешируем динамический контент с помощью etagify"
- "Приручаем конфигурации веб-приложений с помощью node-convict"
- "Производительность фронтенда. Часть 3 — оптимизация шрифтов"
Знаете ли вы, что продукты и сервисы Mozilla локализованы для 90 языков? Локализация включает в себя:
- текст, переведённый на региональные вариации и диалекты языков;
- рендеринг страниц с учётом написания справа налево;
- пуленепробиваемый дизайн, способный вместить тексты любой длины;
- заголовки, метки и текст на кнопках, подобранные для локальных аудиторий.
В этой серии из трёх статей, посвящённых локализации, я расскажу о технических аспектах создания многоязычного приложения Node.js.
Мы будем использовать общепринятые термины «интернационализация» (i18n) и «локализация» (l10n). Интернационализация — это набор технических приёмов, делающих возможной последующую локализацию, то есть собственно перевод и адаптацию для конкретного языка.
Mozilla Persona — веб-сервис на Node.js, локализованный для множества локалей. У нашей команды были весьма специфические запросы, и поэтому мы не стали использовать существующие библиотеки для локализации.
Наши цели
Мы создали несколько модулей чтобы добиться следующих целей:
- хорошей интеграции в существующее сообщество локализаторов и переводчиков Mozilla;
- работы всех инструментов на чистом JavaScript.
Вот модули, которые мы написали:
- i18n-abide
- jsxgettext
- po2json.js
- gobbledygook
i18n-abide — главный модуль, который используется для включения переводов в приложение. Давайте сначала разберёмся с ним. В примерах мы предполагаем, что выше приложение использует Express и шаблоны EJS.
Установка и подготовка
i18n-abide устанавливается через npm:
npm install i18n-abide
В код приложения надо включить следующие строки:
var i18n = require('i18n-abide');
app.use(i18n.abide({
supported_languages: ['en-US', 'de', 'es', 'zh-TW'],
default_lang: 'en-US',
translation_directory: 'static/i18n'
}));
Мы рассмотрим параметры конфигурации модуля в третьей статье серии о локализации. i18n-abide предоставляет несколько функций, которые нужны для перевода. Они доступны в объекте req
при обработке запроса и в шаблонах.
Следующий шаг — пройтись по коду приложения и найти все места, где пользователю показывается какой-либо текст. Вот как может выглядеть шаблон после этого:
<title></title>
Главная функция, которую добавляет abide — это gettext()
. Кроме того, добавляются переменные lang
и lang_dir
.
lang
— это код языка, основанный на настройках браузера и предпочтениях пользователя;lang_dir
— направление текста, слева направо (ltr
) или справа налево (rtl
);gettext
— функция, которая принимает английскую строку и возвращает перевод.
Стоит обратить внимание, что говоря о строках, мы имеем в виду строки gettext
, а не строки JavaScript. Это любые фрагменты текста — надписи, абзацы, элементы интерфейса, которые будут видны пользователю. Если какая-то строка в коде не предназначена для глаз пользователя, то с точки зрения gettext
она не существует. Другими словами, строки gettext
— это любые строки, которые нуждаются в переводе.
Вот пример использования gettext
в файле JavaScript:
app.get('/', function(req, res) {
res.render('homepage.ejs', {
title: req.gettext('Hello, World!')
});
});
Для того чтобы подготовить приложение к локализации, надо обернуть все строки в вызовы gettext
.
Определение языка
Откуда мы знаем, какой язык предпочитает пользователь? Его определением занимается middleware во время выполнения.
Модуль i18n-abide смотрит на поле Accept-language
HTTP-запроса. В нем перечислены языки, которые понятны пользователю, в порядке предпочтения.
abide сравнивает это значение со списком поддерживаемых языков, выбирает наилучшее соответствие и отдаёт клиенту локализованную версию страницы. Если подходящего перевода не найдено, подставляются фразы непосредственно из вызовов gettext
в коде и шаблонах.
Заключение
Во второй статье мы рассмотрим, как именно извлекаются, обрабатываются и переводятся строки.
В третьей — более подробно разберёмся с техническими деталями и параметрами конфигурации и протестируем результат локализации.
Продолжение следует...
Автор: ilya42