Как работать с переводами
В примере используются файлы каталогов GNU gettext:
locale/messages.pot— шаблон с текстами, извлечёнными из исходного кода.locale/<язык>/LC_MESSAGES/messages.po— переводы для конкретного языка.messages.mo— скомпилированный каталог, который использует приложение.
Формат gettext поддерживается многими онлайн-сервисами перевода, например Crowdin и Transifex. Для работы с файлами .po также есть специальные редакторы, например Poedit.
Подробное руководство по переводу приложений с помощью gettext есть в статье Lokalise.
Для повторяющихся действий в примере настроены задачи Poe the Poet. Запускайте их из каталога example/. Эти задачи особенно удобны, когда в приложении несколько языков: они обновляют или компилируют каталоги всех языков за один запуск, поэтому не нужно повторять команды для каждого языка отдельно.
Перед запуском установите GNU gettext и Poe the Poet. Если Poe ещё не установлен, это можно сделать командой:
uv tool install poethepoet
Именно такие определения задач используются в example/pyproject.toml:
[tool.poe.tasks]
run = "streamlit run app.py"
xgettext.shell = "xgettext -d messages -o ./locale/messages.pot *.py --from-code=UTF-8 --no-location"
msgfmt = "find ./locale -name \\*.po -execdir msgfmt messages.po -o messages.mo \\;"
msgmerge.shell = "find locale -name '*.po' -exec msgmerge -U {} locale/messages.pot \\; && find locale -name '*.po~' -delete"
xgettext собирает строки из Python-файлов в общий шаблон. msgmerge обновляет по нему все существующие каталоги .po и удаляет резервные файлы, а msgfmt компилирует все каталоги .po в файлы .mo. Все эти команды входят в GNU gettext, а Poe лишь запускает настроенные задачи.
1. Пометьте текст для перевода
Оборачивайте строки, которые увидит пользователь, в gettext (обычно импортированную как _). Для форм единственного и множественного числа используйте ngettext. Например:
st.write(_("Squirrel application"))
ngettext("One squirrel", "%(num)d squirrels", count)
2. Соберите строки из кода
После добавления или изменения переводимых строк сформируйте шаблон сообщений:
poe xgettext
Задача запускает xgettext для Python-файлов в каталоге example/ и обновляет locale/messages.pot.
3. Обновите каталоги и добавьте переводы
Объедините свежий шаблон со всеми существующими каталогами .po:
poe msgmerge
Откройте файлы locale/<язык>/LC_MESSAGES/messages.po и переведите значения msgstr. Не меняйте подстановки вроде %(num)d. Для множественных форм переведите все варианты msgstr[n], необходимые для языка.
При обновлении каталога msgmerge может пометить запись флагом fuzzy, если исходный текст изменился, но похож на прежнюю строку. Старый перевод переносится как подсказка, однако он может уже не подходить. Проверьте его и удалите флаг fuzzy: msgfmt пропускает такие записи, поэтому приложение не сможет их использовать.
Задача обновляет уже существующие каталоги. Чтобы добавить новый язык, сначала создайте для него файл .po.
4. Скомпилируйте переводы и проверьте результат
Скомпилируйте каталоги переводов в файлы .mo:
poe msgfmt
Запустите пример и проверьте переводы в приложении:
poe run
Когда исходные строки изменятся, снова выполните poe xgettext и poe msgmerge, переведите новые или изменившиеся записи и пересоберите каталоги.