Различия между версиями 6 и 7
Версия 6 от 2021-12-10 11:51:38
Размер: 14367
Редактор: FrBrGeorge
Комментарий:
Версия 7 от 2021-12-10 12:00:25
Размер: 14458
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 135: Строка 135:
 * [[https://www.guyrutenberg.com/2014/11/01/gettext-with-autotools-tutorial/| Ещё простая методичка]]  * [[https://www.guyrutenberg.com/2014/11/01/gettext-with-autotools-tutorial/| Ещё простая методичка]] (на всякий случай [[FrBrGeorge/GettextAutotoolsGuyRutenberg|спёр её]])

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

Лекции прошлых лет:

Термины

  • Локализация (l10n) — адаптация культурных и языковых предпочтений ПО
  • Интернационализация (i18n) — приведение исходного кода в готовое для локализации состояние

Объекты ПО

  • Сообщения и тексты в составе ПО
    • Словоформы (в первую очередь — множественные)
  • Размер и оформление интерфейсных элементов (RTL, например)
  • Изображения: текст на них и культурная атрибуция
  • Управляющие клавиши (иероглифы, ага :( )

  • Параметры, чувствительные к локали (команда locale)

  • Ссылки на внешние ресурсы (поддержка, издатель и пр.; телефоны, url и пр.)
  • (в сложных случаях) Шрифты

Другие объекты продукта

  • Электронная документация
  • Непрограммные данные (шаблоны документов и форм и т. п.)
  • Бумажная документация и др. сопутствующие предметы

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

  • Общие словари (?)
  • Память перевода (локальные общие словари)
  • Нечёткий перевод (при лёгком изменении ресурса или при добавлении похожего)
  • … что ещё?

GNU Gettext

Документация

Создание перевода

  1. I18n:
    • Обмажем функцией gettext() все строки, нуждающиеся в переводе

      • Есть ещё ngettext(), см. ниже

  2. (xgettext) Создадим на основе i18n-ванного исходного кода шаблон перевода, файл domain.pot (domain — это довольно произвольное название того, что мы переводим)

    • Не удаляйте сгенерированные комментарии из файла, это не комментарии ☺!
  3. (msginit) Создадим прототип перевода (для русского — ru.po)

  4. (текстовый редактор или специализированный инструмент редактирования .po) Переведём все строки в ru.po

  5. (msgfmt) Скомпилируем перевод в файл ru.mo

Обновление перевода

Вышла новая версия программы (или сами поправили). Там «поехали» строки с сообщениями (появились новые, пропали/изменились/переместились старые).

  1. (xgettext) Сгенерируем новый шаблон

  2. (msgmerge) Обновим содержимое ru.po на основании шаблона и старого ru.po. У msgmerge много искусственного мозга:

    • Не теряет старые переводы (только комментирует)
    • Размечает новые сообщения возможными переводами из старых/законмментированных

  3. Допереводим ru.po

  4. (msgfmt) Компилируем новый перевод

LecturesCMC/PythonDevelopment2020/08_L10n/Gettext.svg.png

Ход работы

  • Преобразовать текст на Си
    • Традиционный макрос _() (не обязателен)

     #include <libintl.h>
     #include <locale.h>
     #define _(STRING) gettext(STRING)
    • В main()

     setlocale (LC_ALL, "")
     bindtextdomain ("домен", "путь к локализации");
     textdomain ("домен");
    • Во всей программе заменить строки "Something..." на _("Something...") (вызов gettext())

  • простая методичка:

    • Создание шаблона (шаблон — это генерат)
        $ xgettext --keyword=_ исходник -o шаблон.pot
      • Документация xgettext

      • Если не использовать «_», то и --keyword не нужен

    • Создание первоначального пустого перевода
        $ msginit -i шаблон.pot -l локаль -o перевод.po
      • Документация msginit

      • Большинство комментариев — значащие (например, "#, c-format"), лучше их не трогать

      • Некоторые поля следует заполнить заранее (vim выделяет их жёлтым)
    • Перевод
      • Строки msgstr — это переводы (поначалу пустые)

    • Компиляция перевода (нужна для интерпретации формулы множественного числа)
        $ msgfmt -o скомпилированный_перевод.mo перевод.po
    • Обновление перевода
      • Перегенерация шаблона (см. выше, точно той же командой xgettext)

      • Обновление старого перевода на основании нового шаблона
           $ msgmerge -U старый_перевод.po новый_щаблон.pot
      • При этом;
        • Совсем удалённые сообщения в переводе комментируются (но не удаляются — это translation memory!)
        • Некоторые новые сообщения не переведены, для других подобраны похожие переводы, и помечены #, fuzzy. Fuzzy-строки считаются непереведёнными, для того, чтобы они вступили в силу, эту часть комментария (и только ее!) надо удалить

  • Варианты «пути к локализации»:
    • Локальный — положить рядом с бинарником или в подкаталог po/

      • /!\ Так в Linux не принято!

    • Системный — положить в /usr/share/locale и/или в /usr/local/share/locale

      • /!\ Требует прав администратора и средств деинсталляции

    • Микс — предусмотреть два варианта сборки, определить переменную в configure и т. д.

    • С относительным путём:
      • сформировать путь относительно местоположения бинарника

        • если бинарник ставится в /usr/bin, а переводы — в /usr/share/locale, то путь получится ../share/locale

      • выполнить тестовую установку куда-нибудь в /tmp или /home/пользователь/что-то-там

      • оттуда и запускать
  • Использование множественных форм
  • Translation memory в комментариях
    • При составлении перевода msgmerge можно подключать файлы с другими переводами (ключ -C)

    • Закомментированные переводы тоже используются
  • Страшная формула в строке Plural-Forms:

    • Общий вид: "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"

      • nplurals=3 три словоформы, далее идёт C-style выражение:

      • plural=n%10==1 && n%100!=11 ? 0 — единственное число

      • : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 — малое число

      • : 2 — иначе большое число

    • Если увеличить nplurals до 4 и добавить в начало формулы plural == 1? 3 :, получим четвёртую словоформу — для ровно одного объекта ( в таких случаях можно число 1 не выводить)

gettext и autotools

Есть поддержка, она в первую очередь имеет смысл для больших проектов

  • Приносит довольно много заданного заранее workflow (как и любой мета инструмент сборки)
    • Вся работа с переводом заключается в запуске intltool-update язык, и каталог po полностью управляется автоматикой

    • Используется относительная схема размещения локализации (см. выше)

  • Наиболее вменяемая методичка в документации Debian

  • ещё одна, она сильно устарела, но зато простая

  • Ещё простая методичка (на всякий случай спёр её)

    • Кое-какие приёмы, например, копирование gettext.h, я бы не рекомендовал

Пример

В этом примере autotools использовались для всего, кроме переводов.

  • Так проще объяснить, что происходит, все команды видны в Makefile.am

  • Так легче читать (и писать тоже, пока у вас один файл на си и один перевод!)
  • <!> Формально говоря, это неправильный пример: общим каталогом для данных всего проекта объявляется каталог для русских переводов

Под конец пример переключается на autotools

  • Пример стал универсальным, можно добавлять переводы
  • В качестве бонуса реализовано единственное число (по методу выше)

После каждого коммита я делал

  • git clean -fd

  • autoreconf -fisv && ./configure && make && ./ahello

Д/З

  • За неимение лучшего почитать пример

  • Написать довольно тупую программу на Си, которая угадывает число 1…100 методом половинного деления

    • Первым делом просит загадать число от 1 до 100
    • Затем спрашивает «число больше 50?» (ответ тоже надо переводить)
    • На основании ответа выбирает пол-интервала и повторяет его по циклу
    • Когда догадается — отвечает
    • <!> Желающие могут реализовать проверку ошибок ввода (подсказка: почитайте scanf на предмет возвращаемого значения)

  • Оформить автосборку вокруг неё (autotools/CMake/Meson/как хотите)
  • Добавить перевод
  • Добавить
    • Либо поддержку перевода с помощью autotools как в конце репозитория с примерами
    • Либо автоматическое обновление/пересборку перевода и удаление генератов (как ранее в том же репозитории)
    • Обратите внимание: .po-файл (а в примере джо перехода на autotools ещё заголовочная часть .pot-файла) — не генераты; .mo, временный .pot и прочее — генераты

  • Положить результат в каталог (извините! ☺) 10_I18n отчётного репозитория

LecturesCMC/LinuxApplicationDevelopment2021/10_I18n (последним исправлял пользователь FrBrGeorge 2021-12-10 12:00:25)