пятница, 18 октября 2013 г.

[Перевод] Локализация приложений Node.js. Часть 2: инструментарий и процесс

От переводчика: Это деcятая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.
Предыдущие статьи:








В прошлой статье о локализации приложений Node.js мы узнали, как использовать модуль i18n-abide в нашем коде. Наша работа, как программистов, фактически закончилась на том, что мы обернули строки в шаблонах и коде приложения в вызовы gettext(). Но работа по локализации и переводу приложения только начинается.

Инструментарий




Инструментарий локализации команды Mozilla Persona совместим с теми инструментами, которые используются в остальном сообществе Mozilla, и при этом сохраняет преимущества в дружественности и гибкости, присущие Node.

Проекту Mozilla уже почти 15 лет, и наша команда локализаторов и переводчиков одна из самых больших (и клёвых) в мире Open Source. Поэтому у нас широко используются давно привычные, можно даже сказать старинные и причудливые инструменты.



Gettext




GNU Gettext — это набор инструментов, предназначенный для локализации настольных и веб-приложений. Когда вы пишете код и шаблоны для Node, вы используете везде английские фразы, но оборачиваете каждую из них в вызов gettext().

gettext делает две вещи:



  • во время сборки составляет каталог всех строк, встреченных в приложении;

  • во время выполнения заменяет их на локализованные варианты.




Все извлечённые строки хранятся в текстовых файлах с расширением .po В дальнейшем мы будем называть их po-файлы.

Po-файлы




Po-файлы — это текстовые файлы определённого формата, которые gettext может читать, писать и объединять.

Вот пример содержимого po-файла zhTW/LCMESSAGES/messages.po:



#: resources/views/about.ejs:46
msgid "Persona preserves your privacy"
msgstr "Persona 保護您的隱私"




Подробнее мы его рассмотрим позже, а сейчас нам важно понимать, что msgid — это английская строка, а msgstr — её перевод на китайский. Всё, что начинается с # — комментарий. Комментарий в этом примере указывает на расположение этой строки в коде.

Gettext предоставляет множество других инструментов для работы со строками и po-файлами. Мы коснёмся и их.


Почему именно этот инструментарий?




Прежде чем мы погрузимся в более подробное изучение модулей Node.js для работы с gettext, мы должны спросить себя, почему мы выбрали именно этот набор инструментов?

Год назад я подробно исследовал существующие модули Node.js для интернационализации и локализации. Большинство из них изобретали собственные велосипеды и основанные на JSON форматы для хранения строк.


С другой стороны, в Mozilla давно и успешно используются такие инструменты, как POEdit, Verbatim, Translate Toolkit и Pootle. Вместо того, чтобы заставлять людей переучиваться, мы решили разработать для них инструменты, совместимые с привычными стандартами и процессами.


Po-файлы — общепринятый формат обмена и сотрудничества наших переводчиков. Именно в этом формате они должны получать от нас строки для перевода, и отдавать нам готовый текст.


Имея большой опыт разработки в Mozilla ещё на PHP и Python, я нахожу Gettext очень удобным. По мере того, как веб-приложение растёт и содержит всё больше текста, проявляется всё больше нюансов, которые требуют применения хорошо проверенных инструментов и API Gettext.


Создаём po-файлы для переводчиков




Итак, мы разметили наш код вызовами gettext. Что дальше? В дело вступает тот, кого мы называем «строководом». Это можете быть вы сами, переводчик или администратор. Что делает строковод?

  • Извлекает строки, впервые появившиеся в приложении.

  • Находит новые, изменившиеся строки или помечает удалённые в последующих релизах.

  • Готовит po-файлы для каждой команды переводчиков.

  • Разрешает конфликты и помечает изменённые или удалённые строки переводов.




Это может звучать несколько запутанно, но, к счастью, большинство этих задач хорошо автоматизируется. Строководу приходится вмешиваться только, когда возникают проблемы.

msginit, xgettext, msgfmt и другие инструменты GNU Gettext — это мощный набор для работы с каталогами строк. С этими инструментами работает только строковод. Большинство разработчиков могут оставаться в блаженном неведении относительно них.


Создание дерева файлов для локали:



$ mkdir -p locale/templates/LC_MESSAGES




В этой директории хранятся шаблоны po-файлов — файлы .pot. Они будут использованы gettext в дальнейшем.

Извлечение строк




В прошлой статье мы установили i18n-abide:

$ npm install i18n-abide




Среди других инструментов командной строки, abide предоставляет extract-pot. Эта команда используется для извлечения строк в директорию локали:

mkdir -p locale/templates/LC_MESSAGES
$ ./node_modules/.bin/extract-pot --locale locale




Скрипт пройдёт по всему исходному коду приложения, находит строки и записывает их в файл шаблона po.

Для создания pot-файлов можно было бы воспользоваться и традиционными утилитами gettext, но мы написали специальный модуль jsxgettext, удобный и кроссплатформенный. Под капотом extract-pot использует именно его.


Jsxgettext ищет в коде вызовы gettext() и извлекает из них строковый аргумент, затем он форматирует строки в формат, совместимый с инструментарием gettext. Вот отрывок такого pot-файла:



#: resources/views/about.ejs:46
msgid "Persona preserves your privacy"
msgstr ""

#: resources/views/about.ejs:47
msgid ""
"Persona does not track your activity around the Web. It creates a wall "
"between signing you in and what you do once you're there. The history of "
"what sites you visit is stored only on your own computer."
msgstr ""
""

#: resources/views/about.ejs:51
msgid "Persona for developers"
msgstr ""




Позже на основе этого шаблона будут созданы po-файлы с переводом. Они будут выглядеть так:

#: resources/views/about.ejs:46
msgid "Persona preserves your privacy"
msgstr "Persona 保護您的隱私"

#: resources/views/about.ejs:47
msgid ""
"Persona does not track your activity around the Web. It creates a wall "
"between signing you in and what you do once you're there. The history of "
"what sites you visit is stored only on your own computer."
msgstr ""
"Persona 只是連結您登入過程的一座橋樑,不會追蹤您在網路上的行為。您的網頁瀏覽"
"紀錄只會留在您自己的電腦當中。"

#: resources/views/about.ejs:51
msgid "Persona for developers"
msgstr "Persona 的開發人員資訊"




Чтобы лучше почувствовать тему, вы можете взглянуть на полный вариант po-файла для китайского языка.

Создание локали




Команда msginit из набора Gettext используется для создания po-файла для конкретной локали, основанного на файле шаблона:

$ for l in en_US de es; do
mkdir -p locale/${l}/LC_MESSAGES/
msginit --input=./locale/templates/LC_MESSAGES/messages.pot \
--output-file=./locale/${l}/LC_MESSAGES/messages.po \
-l ${l}
done




Мы только что создали po-файлы для американского английского, немецкого и испанского языков.

Po-файлы




Итак, мы извлекли строки и создали папки локалей. Вот так выглядит наше дерево файлов:

locale/
el/
LC_MESSAGES/
messages.po
en_US
LC_MESSAGES/
messages.po
es
LC_MESSAGES/
messages.po
templates
LC_MESSAGES/
messages.pot




К этим частям вашего приложения можно дать доступ переводчикам. К примеру, испанская команда будет иметь доступ к locale/es/LC_MESSAGES/messages.po. Если у вас очень большой проект, могут быть даже две отдельные локали для испанского и аргентинского вариантов испанского языка: es-ES и es-AR.

Со временем могут добавляться новые локали.


Слияние изменений строк




Релиз за релизом вы будете добавлять новые, менять и удалять старые строки. Вам будет необходимо обновлять все po-файлы в соответствии с этими изменениями. В gettext есть мощные инструменты для этого. Для себя мы сделали скрипт-обертку merge-po.sh, который использует команду msgmerge из пакета GNU Gettext.

Добавим инструменты i18n-abide в системные пути:



$ export PATH=$PATH:node_modules/i18n-abide/bin




и запустим процесс слияния строк:

$ ./node_modules/.bin/extract-pot --locale locale .
$ merge_po.sh ./locale




Как и в первый раз, extract-pot собирает все строки и создаёт шаблон. Затем merge-po.sh обновляет все po-файлы, приводя их в соответствие с текущей версией приложения. После этого команды переводчиков могут снова браться за работу.

Gettext против синдрома «изобретено не здесь»




Нет ничего сложного в том, чтобы изобрести свой велосипед на основе JSON вместо gettext. Большинство авторов модулей Node пошли именно этим путём. Но по мере роста приложения и добавления новых и новых языков мелкие неприятности будут нарастать как снежный ком. Например, без merge-po.sh вам рано или поздно придётся писать и отлаживать собственные инструменты для слияния. Вручную обновить 30 файлов для 30 локалей, ничего при этом не потеряв и не перепутав — та ещё морока.

А в gettext всё необходимое уже есть и это экономит нам кучу времени и нервов.


Заключение




Теперь, когда мы окончательно разобрались, как создавать и обновлять po-файлы, можно перепоручить их заботам переводчиков. Вообще, всегда лучше заранее пообщаться с ними и обсудить, когда можно будет начать перевод, какой предполагается объём и когда желательно закончить. Также будет нелишним изучить документацию gettext.

Итак, строки переведены, и в следующей статье мы узнаем, как работает локализация во время выполнения приложения.






Продолжение следует...

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



2 комментария:

  1. Этот комментарий был удален автором.

    ОтветитьУдалить
  2. Добрый день! Если Вы заинтересованы в локализации web-ПО, ПО для персональных компьютеров, ПО для мобильных устройств либо иного вида программного обеспечения, я рекомендую Вам использовать этот инструмент на базе web: https://poeditor.com/
    POEditor является интуитивным, хорошо проработанным инструментом, обладающим рядом полезных свойств, которые помогают организовать процесс управления переводом. Он поддерживает множество популярных форматов файлов и обладает собственным API, что обеспечивает лучшую автоматизацию. Желаю Вам больших успехов в Ваших проектах!

    ОтветитьУдалить