Различия между версиями 8 и 9
Версия 8 от 2019-04-26 11:36:27
Размер: 12423
Редактор: FrBrGeorge
Комментарий:
Версия 9 от 2019-05-16 13:13:21
Размер: 12441
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 8: Строка 8:
'''TODO''' babel

Интернационализация

Лекция и видео 2015 года

... 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.pot.png

    • Из этого файла можно сделать заготовку для перевода — 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.pomsgfmt

Про память переводов

Очень важно соблюдать единообразие при переводе одинаковых надписей. Для этого все переводы по проекту можно сложить в т. н. 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
  • К сожалению, 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 (если знаете другой тулкит, можно его)

LecturesCMC/PythonDevelopment2019/10_I10n (последним исправлял пользователь FrBrGeorge 2019-05-16 13:13:21)