Интернационализация
... TODO копипаста плана лекции
TODO babel
Пример
Попробуем перевести пример из документации TkInter
Первичный перевод
ещё упростим и добавим картинку (её тоже надо переводить!)
вот такое добавление gettext ничего в работе не поменяет: перевода не найдётся, но функция _() появится, и будет возвращать непереведённые строки
Обратите внимание на то, что все строки, которые нужно переводить, заданы как "что-то там", а которые не нужно — как 'что-то там'
например, в vim достаточно такой команды :
:1,$s/\("[^"]*"\)/_(\1)/g
Используем GNU getttext или простой аналог на python3 (в каталоге /usr/lib64/python3.7/Tools/i18n)
Вынимаем из .py-файлов все конструкции вида _("строка") и формируем файл app.pot (шаблон перевода):
$ /usr/lib64/python3.7/Tools/i18n/pygettext.py -d app *.py
(примерно то же самое получается при использовании утилиты xgettext)
Получится файл, в котором некоторые части надо ещё заполнить (раскраска редактора vim):
Из этого файла можно сделать заготовку для перевода — app.po, в которой часть поле заполнит для нас утилита msginit, которая отыщет .pot-файл самостоятельно:
$ msginit -l ru_RU.UTF8 В новом каталоге сообщений должен быть указан адрес вашей электронной почты, чтобы пользователи могли присылать свои замечания по поводу ваших переводов, а также чтобы сопроводители программ могли связаться с вами на случай, если возникнут непредвиденные технические проблемы. Which is your email address? 1 george@altlinux.org 2 george@inspiron Please choose the number, or enter your email address. frbrgeorge@gmail.com A translation team for your language (ru) does not exist yet. If you want to create a new translation team for ru, please visit http://www.iro.umontreal.ca/contrib/po/HTML/teams.html http://www.iro.umontreal.ca/contrib/po/HTML/leaders.html http://www.iro.umontreal.ca/contrib/po/HTML/index.html Создано ru.po.
Ключ -d domain на самом деле определяет не имя файла, а т. н. домен — один из трёх ключей, (язык, тип, домен), по которым происходит поиск перевода. Просто в Linux это превращается в путь к файлу /usr/share/locale/язык/тип/домен.mo. Наша программа не будет ходить в /usr/share/locale, вместо этого переводы ожидаются в подкаталоге ru/LC_MESSAGES того каталога, откуда запущена программа (см. объект datapath)
- Создадим этот подкаталог и скомпилируем туда наш перевод
$ mkdir -p ru/LC_MESSAGES $ /usr/lib64/python3.7/Tools/i18n/msgfmt.py -o ru/LC_MESSAGES/app.mo ru.po
(можно было воспользоваться утилитой msgfmt)
- Создадим этот подкаталог и скомпилируем туда наш перевод
Редактировать .po-файл перевод можно очень разными редакторами (многие IDE поддерживают работу с переводами). Я пользуюсь vim + `vim-plugin-po-after-ftplugin
Обратите внимание на то, что имя файла с картинкой также «переведено» (русифицированный вариант картинки)
Обновление перевода
Допустим, мы изменили сообщение а программе
При этом .pot-файл тоже изменился:
#: app.py:19 -msgid "Feet to Meters" +msgid "Feet to meters" msgstr ""
Для сборки обновлённого перевода из (1) имеющегося перевода и (2) нового шаблона используется утилита msgmerge:
$ msgmerge -Uv ru.po app.pot .. Прочитано сообщений: старых 1 + новых 1; объединено 6, помечено неточными 1, недостающих 0, недействительных 0.
Т. н. «неточные переводы» помечаются значащим комментарием fuzzy.
При компиляции эти переводы не попадают в .mo-файл, но и не исчезают
- Неиспользованные переводы (которые были в старой версии, но отсутствуют в шаблоне), не удаляются, а комментируются
Дальнейшая работа с переводом — повторение цикла pygettext (или xgettext) → msgmerge → правка ru.po → msgfmt
Про память переводов
Очень важно соблюдать единообразие при переводе одинаковых надписей. Для этого все переводы по проекту можно сложить в т. н. compendium (но же translation memory, она же память переводов) — большой .po-файл, получаемый утилитой msgcat из всех имеющихся
Если в исходном проекте одинаковые надписи значат разное (например, «Copy» в одном месте — «Копировать», а в другом «Копия») — это плохой дизайн ,надписи надо менять
- Надписи типа «Save as…» или «Press button to continue» не придётся переводить по многу раз
- Появится больше автоматически подобранных fuzzy-переводов
- Фактически это будет ещё и словарь терминологии, который можно править при необходимости
Множественные формы
Наш перевод не слишком-то хорош: футы и метры показываются во множественном числе, независимо от значения полей. На самом деле это свойство не перевода, а исходного текста. Используем gettext для исправления ситуации.
Подготовим код: вынесем обновление меток в отдельную функцию
- Файл перевода сильно изменился, но ни одной строчки не «отъехало»
Воспользуемся функцией ngettext(), которая в английском варианте различает форму единственного и множественного числа (эту функцию надо отдельно попросить добавить в пространство имён при gettext.install())
- Убедимся, что в локали «C» для 1 фута выводится «foot», для 4 футов — «meter»)
$ LC_ALL=C python3 app.py
- Убедимся, что в локали «C» для 1 фута выводится «foot», для 4 футов — «meter»)
К сожалению, pygettext не умеет распознавать множественные формы, так что воспользуемся, наконец, утилитой xgettext:
$ xgettext -d app -o app.pot *.py $ msgmerge -Uv ru.po app.pot .. Прочитано сообщений: старых 1 + новых 1; объединено 5, помечено неточными 1, недостающих 1, недействительных 1. $ msgfmt -o ru/LC_MESSAGES/app.mo ru.po
Обратите внимание на работу «мозга» msgmerge: часть сообщений было сочтено fuzzy (и справедливо!), а часть — непереведёнными
Русский перевод имеет 3 множественные формы — единственное число, немного (2-4), и много (5 и больше), что и отразилось в ru.po
допереведём и проверим, что всё работает (футы: 0, 1, 2, 7, 777)
Описание того, какие числа какой множественной форме соответствуют содержится в заголовке ru.po (который нам сгенерировал msginit). Это описание компилируется в некоторый код .mo-файла, который gettext интерпретирует (замечание vslutov@, спасибо).
Взаимодействие с git
В репозитории нужно хранить только сам перевод и, возможно, память переводов, а .pot и .mo файлы — не надо (о чём сказано в .gitignore
Дополнительно в .gitignore добавлен шаблон *~ — это резервные файлы vim и msgmerge.
Д/З
- Провести интернационализацию проекта
Добавить перевод на альтернативный язык (проще русский делать альтернативным) с помощью pygettext (если знаете другой тулкит, можно его)