Извлечение¶
Извлечение — это шаг, который собирает все помеченные сообщения из исходного
кода в шаблон .pot для переводчиков — шаг 3 цикла из
учебника. Эта страница — справочник по этому шагу: настройка,
собственные имена функций, строгий режим для CI и проверки, которые затем
охраняют ваши каталоги.
Для извлечения нужен extra babel:
Процесс¶
Создайте babel.cfg:
Затем используйте обычные команды Babel:
pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
pybabel init -i locales/messages.pot -d locales -l ja
pybabel compile -d locales
init выполняется один раз на язык; дальше pybabel update вливает каждый
свежий шаблон в существующие каталоги. Этот регулярный цикл — и что его
записи fuzzy значат для релиза — разобран в разделе
В продакшене.
Экстрактор обрабатывает также _(), gettext() и ngettext(). Одно
сопоставление покрывает смешанный код с tr(), ntr(), lazy_gettext() и
lazy_pgettext().
Включите комментарии для переводчиков через -c
Передайте -c "Translators:", чтобы собрать комментарии для переводчиков,
как в обычном gettext. Без этого флага извлечение всё равно работает —
просто комментарии никогда не доходят до каталога, где они
самый дешёвый рычаг качества
во всём процессе.
Собственные имена функций¶
В INI значение — строка с разделителями-пробелами или запятыми; TOML принимает список. Опции охватывают все шесть семейств функций gettext.
-k не видит t-string
Helper вроде mytr(t"…") нужно объявить в этих опциях. Механизм Babel
--keyword не читает литералы t-string:
pybabel extract -k mytr пропустит их без предупреждения.
Поддерживается только стандартный порядок аргументов.
Снисходительно локально, строго в CI¶
По умолчанию один плохой файл не срывает весь запуск:
- Отклонённая t-строка отмечается предупреждением и пропускается.
- Неразбираемый файл изолируется тем же способом.
- Файл, отклонённый только
tokenize, также изолируется.
Это удобно, пока вы правите код, и опасно, когда уже не правите: пропущенное
сообщение просто отсутствует в POT, поэтому оно никогда не будет переведено
и никто об этом не скажет. Ставьте strict = true в опциях сопоставления
везде, где за извлечением не следит человек:
Каждое предупреждение выше тогда становится жёсткой ошибкой. Считайте такую настройку продакшен-настройкой, а поведение по умолчанию — локальной.
Проверка существующими инструментами¶
Babel добавляет стандартный флаг:
Перевод こんにちは {nombre} обнаруживается без настройки:
$ msgfmt --check-format -o /dev/null locales/ja/LC_MESSAGES/messages.po
locales/ja/LC_MESSAGES/messages.po:25: a format specification for argument
'name' doesn't exist in 'msgstr'
msgfmt: found 1 fatal error
Weblate документирует эту проверку как Python brace format, а у коммерческих платформ есть собственный QA заполнителей, привязанный к тому же флагу. Поведение каждой платформы — её собственное дело; здесь проверены два инструмента ниже: msgfmt и поставляемый checker Babel.
pybabel compile применяет checker к каждому отмеченному сообщению:
$ pybabel compile -d locales -l ja
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nombre} is not in the source message
1 errors encountered.
Для множественного числа ошибка называет форму:
error: locales/ru/LC_MESSAGES/messages.po:31: msgstr[1]: translation does not
match the source placeholders: {n} is missing
pybabel compile всё равно записывает .mo
Ошибка выше сообщается, статус выхода равен 1 — и неверный каталог
всё равно компилируется. Остановить pipeline от его выпуска может только
этот статус выхода; Что проверяет CI
показывает шаг сборки, который это делает.
Проверки не дублируют друг друга: checker из этого пакета строже как минимум в
двух случаях — он отдельно проверяет
экранированные скобки и каждую множественную форму там, где msgfmt может принять
файл. ASCII-имена позволяют участвовать всем инструментам; сама библиотека
принимает любое str.isidentifier().
Шаблоны и другие инструменты¶
t-строки — синтаксис Python. Jinja2 ({% trans %}), Django и другие шаблоны
сохраняют свои экстракторы, записывая в тот же PO-каталог.
pygettext пока не разбирает t-строки. Другие экстракторы могут реализовать
правила спецификации.