Интернационализация приложения на Elixir
Одна из основных возможностей приложения Forza Football — отправка подписчикам push-уведомлений о ключевых событиях футбольных матчей (подробнее об этих уведомлениях
Gettext для Elixir
Основной инструмент, который мы используем в Elixir для переводов, — Gettext. Он представляет собой реализацию
Данные уведомлений для отправки пользователям формируются следующим кодом:
Приложение, посылающее push-уведомления, мы назвали Pushboy. gettext/2
— макрос, автоматически определяемый в модуле Pushboy.Gettext
с помощью Gettext:
Переводы будут идентифицироваться по строке ("%{minute}′ Red Card ..."
); она же поможет Gettext во время выполнения приложения отыскать перевод для указанного языка.
Извлечение переводов
Разобравшись в тонкостях процесса интернационализации, можно приступить к извлечению из исходного кода строк, перевод которых необходимо выполнить. Для этого в Gettext имеется специальная mix-задача:
Задача считывает все вызовы к макросу Gettext (gettext/2
в примере выше) во время компиляции и записывает их в файлы с расширением .pot, которые выглядят следующим образом:
POT-файлы — это шаблоны, в которых хранится список строк для перевода. В приведённом примере msgid
— идентификатор строки для перевода, а msgstr
— сам перевод. Так как POT-файлы не создаются отдельно для каждого языка, то переводы хранятся не в них, а в файлах с расширением .po
, располагающихся в директории определённого языка. Если перевести эту строку, например, на итальянский, то файл будет выглядеть так:
На этапе компиляции Gettext сканирует такие PO-файлы, пытаясь как можно быстрее отыскать перевод нужных строк. Всё, что находится между %{
и }
, — интерполяционные переменные: они не подлежат переводу и во время работы приложения заменяются на динамические значения.
После создания POT- и PO-файлов перевод программно будет выглядеть так:
Перевод на несколько языков
С интернационализацией приложения мы разобрались, но каким образом осуществляется перевод? Приложение поддерживает множество различных языков, но члены нашей команды владеют только некоторыми из них, в связи с чем вариант выполнения перевода штатными сотрудниками отпадает.
Поэтому мы пользуемся
В большинстве случаев мы прибегаем к использованию внешних сервисов для перевода, однако некоторые сотрудники нашей компании являются носителями различных языков. С помощью Transifex они тоже могут работать над переводами, ведь интерфейс сайта прост и интуитивно понятен даже несведущему в компьютерной технике пользователю.
Интеграция с Gettext
Transifex взаимодействует со многими платформами для локализации приложений, в том числе и с Gettext. Загрузив PO/POT-файлы на Transifex, можно потом скачать их переводы в формате .po
. В Transifex существует понятие ресурсов, то есть различных областей перевода (например, уведомления — это один ресурс, сообщения об ошибках — другой и т. п.). Ресурсы Transifex удачно соотносятся с областями в Gettext: для извлечения переведённого текста из определённой области в Gettext можно использовать макрос dgettext/3
(gettext/2
использует область default
), после чего каждый домен помещается в отдельный PO(T)-файл (как default.pot в примере выше.
В общих чертах, порядок действий таков. Как было показано выше, сначала из исходного кода в POT-файл извлекаем необходимые для перевода строки с помощью mix-задачи mix gettext.extract
. Затем загружаем POT-файл на Transifex и подготавливаем его содержимое к переводу: добавляем и удаляем строки или обновляем файл целиком.
Ждём, когда перевод будет готов. Как только перевод будет готов, скачиваем с Transifex PO-файлы для всех необходимых языков.
Инструменты командной строки
Описанная выше схема справляется со своими задачами, но пользоваться ей не так удобно: многие действия приходится осуществлять вручную, чем больше количество языков локализации, тем медленнее она будет работать. К счастью, в Transifex имеется замечательный инструмент командной строки под названием tx
, позволяющий оправлять строки на перевод сразу же после запуска команды mix gettext.extract
и помещать переведённые строки в PO-файлы, как только те будут доступны.
Настроим tx
, отредактировав файл .tx/config
, расположенный в корневом каталоге приложения. Получаем следующее:
В этом файле мы создаём конфигурации ресурса pushboy.default
(который соотносится с областью default
из Gettext) и передаём инструменту tx
следующую информацию:
-
форматы используемых файлов (PO и POT)
-
местонахождение исходного текста (
priv/gettext/default.pot
) -
язык оригинала (English)
-
загруженные переводы должны находиться по адресу
priv/gettext
в каталоге с названием языка перевода (<lang>
заменяется черезtx
)
После приведения файла настроек к такому виду, строки можно будет отправлять на перевод командой $tx push --source
(--source
проследит, чтобы действия производились только с обновлённым POT-файлом), а получать переведённые строки — командой tx pull
.
Редактирование PO-файлов, загруженных с Transifex
В нашей компании существуют свои требования к оформлению кода, которым не удовлетворяют PO-файлы, созданные платформой Transifex. Для таких случаев в Gettext имеются специальные инструменты для парсинга и редактирования PO/POT-файлов. Достаточно выполнить mix-задачу mix translations.pull
, и она прекратит взаимодействие с tx
.
Сначала вызовется tx pull
, затем выполнится перебор всех PO-файлов и их форматирование согласно указанным правилам:
Окончательная схема работы приложения
Схема состоит из следующих действий:
-
закончив работу над исходным кодом, запускаем
mix gettext.extract
, чтобы получить набор обновлённых POT-файлов -
запускаем
tx push --source
, чтобы загрузить в Transifex обновлённые строки для перевода -
ждём, когда будет выполнен перевод обновлённых строк
-
запускаем
mix translations.pull
и получаем обновлённые переводы
Такая схема работы очень удобна, ведь она позволяет обновлять, отправлять и извлекать переводы программно, а также легко масштабировать приложение после добавления новых языков (схема остаётся прежней, нужно лишь заказать переводы для добавленных языков в Transifex).
Заключение
Теперь вы знаете удобную и быстро работающую схему осуществления перевода на несколько языков push-уведомлений для своего приложения, обеспечивающую хорошую масштабируемость при изменении количества языков перевода и объёма текста.