Как реализовать механизм замены русских текстов на переведенные в приложении
Что проверяют
Знаете ли вы стандартную схему интернационализации в Python и умеете ли перевести на неё приложение, где русские строки уже зашиты в код. Следом спрашивают про множественное число, подстановку переменных и выбор языка для каждого запроса в веб-приложении.
Как отвечать
Основа это gettext и инструменты Babel:
- разметка: каждую видимую строку оборачиваете в
_(). В готовом коде такие строки находят поиском по кириллице, регуляркой[А-Яа-яЁё], и проходят модуль за модулем; - извлечение:
pybabel extract -F babel.cfg -o messages.pot .собирает шаблон,pybabel initсоздаёт.poдля нового языка,pybabel updateподтягивает новые строки в существующие файлы; - компиляция:
pybabel compileилиmsgfmtпревращает.poв бинарный.mo, который и читает приложение; - загрузка:
gettext.translation("messages", localedir, languages=[lang], fallback=True). Сfallback=Trueнепереведённая строка вернётся как есть, а не уронит запрос.
Подстановку делайте после перевода: _("Здравствуйте, {name}").format(name=user.name), чтобы переводчик видел шаблон целиком и мог переставить слова. Для чисел нужен ngettext: в русском три формы, и .po задаёт их в заголовке Plural-Forms с nplurals=3. Одинаковое слово с разным смыслом разводят через pgettext с контекстом.
В веб-приложении язык свой у каждого запроса, поэтому глобальный install() не годится. Объекты перевода кешируют по локали, а текущую локаль держат в contextvars. В Django всё это уже есть: LocaleMiddleware, makemessages, compilemessages и gettext_lazy для строк, объявленных на уровне модуля.
Где спотыкаются
Пишут f-строку внутри _(). Она вычисляется до поиска перевода, ключ каждый раз получается новым, а extract такую строку вообще не видит.
Склеивают фразу из кусков: _("Найдено") + " " + str(n). В другом языке порядок слов и падежи другие, и перевести такой обрывок правильно нельзя.
Оставляют русский текст ключом и правят его прямо в коде. Исправление опечатки меняет msgid, строка помечается fuzzy, и до ручной проверки перевод на все языки не показывается.