Интернационализация и локализация
Лекции прошлых лет:
LecturesCMC/LinuxApplicationDevelopment2012/09
на сайте esyr.org (лекцию читал Андрей Черепанов, а на фото — не он ☺)
- Python:
Термины
- Локализация (l10n) — адаптация культурных и языковых предпочтений ПО
- Интернационализация (i18n) — приведение исходного кода в готовое для локализации состояние
Объекты ПО
- Сообщения и тексты в составе ПО
- Словоформы (в первую очередь — множественные)
- Размер и оформление интерфейсных элементов (RTL, например)
- Изображения: текст на них и культурная атрибуция
Управляющие клавиши (иероглифы, ага )
Параметры, чувствительные к локали (команда locale)
- Ссылки на внешние ресурсы (поддержка, издатель и пр.; телефоны, url и пр.)
- (в сложных случаях) Шрифты
Другие объекты продукта
- Электронная документация
- Непрограммные данные (шаблоны документов и форм и т. п.)
- Бумажная документация и др. сопутствующие предметы
Локализация: инструменты
- Общие словари (?)
- Память перевода (локальные общие словари)
- Нечёткий перевод (при лёгком изменении ресурса или при добавлении похожего)
- … что ещё?
GNU Gettext
Создание перевода
- I18n:
Обмажем функцией gettext() все строки, нуждающиеся в переводе
Есть ещё ngettext(), см. ниже
(xgettext) Создадим на основе i18n-ванного исходного кода шаблон перевода, файл domain.pot (domain — это довольно произвольное название того, что мы переводим)
- Не удаляйте сгенерированные комментарии из файла, это не комментарии ☺!
(msginit) Создадим прототип перевода (для русского — ru.po)
(текстовый редактор или специализированный инструмент редактирования .po) Переведём все строки в ru.po
(msgfmt) Скомпилируем перевод в файл ru.mo
Обновление перевода
Вышла новая версия программы (или сами поправили). Там «поехали» строки с сообщениями (появились новые, пропали/изменились/переместились старые).
(xgettext) Сгенерируем новый шаблон
(msgmerge) Обновим содержимое ru.po на основании шаблона и старого ru.po. У msgmerge много искусственного мозга:
- Не теряет старые переводы (только комментирует)
Размечает новые сообщения возможными переводами из старых/законмментированных
Допереводим ru.po
(msgfmt) Компилируем новый перевод
Пример
TODO: подробнее
- Традиционно это делается с помощью
#include <libintl.h> #include <locale.h> #define _(STRING) gettext(STRING
и в main()-е
setlocale (LC_ALL, "") bindtextdomain ("домен", "путь к локализации"); textdomain ("домен");
- Создание шаблона
- Создание перевода
- Обновление перевода
- Два варианта "путь к локализации" — локальный и системный
- Использование множественных форм
- Если успеем — translation memory в комментариях
- Если успеем — 4 формы (для неупоминания 1)
gettext и autotools
Есть поддержка, но она имеет смысл для больших проектов
Приносит очень много магии (работа с несколькими файлами / языками; хитрые хаки для чтения локальных переводов при тестировании и /usr/share/locale при эксплуатации и т. д.)
Наиболее вменяемая методичка в документации Debian
Пример
В этом примере autotools использовались для всего, кроме переводов.
- Так проще объяснить, что происходит
- Так легче читать (и писать тоже, пока у вас один файл на си и один перевод!)
Формально говоря, это неправильный пример: общим каталогом для данных всего проекта объявляется каталог для русских переводов ☺
После каждого коммита я делал
git clean -fd
autoreconf -fisv && ./configure && make && ./ahello
Д/З
За неимение лучшего почитать пример
Написать довольно тупую программу на Си, которая угадывает число 1…100 методом половинного деления
- Первым делом просит загадать число от 1 до 100
- Затем спрашивает «число больше 50?» (ответ тоже надо переводить)
- На основании ответа выбирает пол-интервала и повторяет его по циклу
- Когда догадается — отвечает
Желающие могут реализовать проверку ошибок ввода (подсказка: почитайте scanf на предмет возвращаемого значения)
- Оформить автосборку вокруг неё (autotools/CMake/Meson/как хотите)
- Добавить перевод (при запуске из каталога сборки)
- Добавить автоматическое обновление/пересборку перевода и удаление генератов
Обратите внимание: .po-файл (а в примере ещё заголовочная часть .pot-файла) — не генераты; .mo, временный .pot и прочее — генераты
Положить результат в каталог (извините! ☺) 09_I18nL10n отчётного репозитория