Куда складывать переведенные тексты и как с ними работать
Что проверяют
Различаете ли вы два вида переводов: строки интерфейса, которые живут вместе с кодом, и пользовательский контент, который живёт в базе. Следом спрашивают про множественное число и про то, как не потерять перевод при изменении исходной строки.
Как отвечать
Строки интерфейса храните в формате gettext, это стандарт для Python:
- структура:
locale/<язык>/LC_MESSAGES/<домен>.po, из них компилируются бинарные.mo, которые и читает программа; - цикл работы:
pybabel extractсобирает строки из кода в шаблон.pot,pybabel updateобновляет.poкаждого языка, переводчик заполняет,pybabel compileсобирает.mo. В Django то же делаютmakemessagesиcompilemessages, пути задаются вLOCALE_PATHS; - в коде:
gettextдля обычных строк,ngettextдля чисел,pgettextдля одинаковых слов в разном контексте. В Django на уровне модуля (поля моделей, формы) нуженgettext_lazy, иначе строка переведётся один раз при импорте; - форматирование: переменные только именованными плейсхолдерами внутри строки,
_("Hello, %(name)s"), чтобы переводчик мог переставить слова.
Контент из базы (названия товаров, статьи) в .po не кладут. Обычный вариант: отдельная таблица переводов (object_id, lang, title) с уникальным ключом на пару объекта и языка, либо JSONB-поле по языкам. В Django для этого есть django-parler и django-modeltranslation. Язык запроса берут из профиля пользователя или Accept-Language, а на случай пустого перевода задают откат к языку по умолчанию.
.po держат в Git, .mo собирают в CI или при сборке образа. Переводчикам удобна TMS, например Weblate, которая синхронизируется с репозиторием.
Где спотыкаются
Склеивают строку из кусков: _("Found") + str(n) + _("files"). Порядок слов и падежи в разных языках разные, такой перевод не собрать.
Делают множественное число через if n == 1. В русском три формы, в арабском шесть; правило записано в заголовке .po и работает только через ngettext.
Забывают, что изменённая исходная строка помечается как fuzzy, а msgfmt и compilemessages такие записи по умолчанию пропускают. На проде вместо перевода внезапно показывается исходный текст.