Переводите сообщения целиком
с помощью t-строк Python¶
gettext-tstrings соединяет t-строки Python 3.14+ со стандартными каталогами
gettext и инструментами Babel. Значения и форматирование остаются в коде
приложения; переводчик работает с полным сообщением и простыми заполнителями
{name}:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales"))
name = "Ada"
print(_(t"Hello {name}")) # with a Japanese catalog: こんにちは Ada
В каталог попадает Hello {name}. Перевод может переставить или повторить
{name}. Если он удаляет, переименовывает или переформатирует заполнитель,
проверка каталога сообщает об ошибке. Если неверная запись всё-таки добралась
до продакшена, библиотека пишет предупреждение в журнал и выводит исходное
сообщение вместо сбоя.
Начать пятиминутный учебник Сравнить с альтернативами
Alpha · Python 3.14+ · стандартные каталоги PO/MO · без сторонних зависимостей во время выполнения
Этот сайт применяет то, что документирует: каждая языковая версия —
навигация, подписи и отчёт сборки с множественными формами — рендерится из
PO-каталогов
самой gettext-tstrings.
Подходит ли это вам?¶
Подходит уже сейчас, если ваше приложение работает на Python 3.14 или новее; вы уже пользуетесь gettext и Babel — или хотите перейти на их процесс с PO/MO; и вам нужен синтаксис t-строк с именованными заполнителями, которые проверяются до рендеринга.
Пока не подходит, если вам нужен Python 3.13 или старше; вам требуется стабильный Python API — это alpha, и устоявшаяся её часть — спецификация; или почти весь переводимый текст у вас живёт в языке шаблонов, а не в исходниках Python.
Каталоги уже есть? Они продолжат работать. _("Hello {name}").format(name=name)
и tr(t"Hello {name}") дают один и тот же msgid, поэтому существующие переводы
переживут переход — Миграция описывает его целиком.
Что может сказать каталог¶
Перевод не может изменить структуру сообщения, которое он переводит. В этом
и состоит всё обещание, а из него следует и весь остальной сайт. Перевод может
переставить или повторить {name} и может переписать вокруг него любое другое
слово. Он не может удалить заполнитель, выдумать новый, дотянуться через него
до ваших объектов или добавить собственное форматирование.
Библиотека проверяет это на входе — при компиляции каталогов — и ещё раз при рендеринге, и в этом вся разница между ошибкой, найденной на ревью, и ошибкой, найденной пользователем.
Впервые видите gettext? Весь процесс в четырёх предложениях
gettext — стандартный способ перевода программ, в Python и далеко за
его пределами. Ваш код помечает переводимые строки; экстрактор собирает
их в файл-шаблон (.pot); переводчик — обычно не программист — заполняет
один файл каталога (.po) на язык, который компилируется в двоичный
.mo, загружаемый приложением во время выполнения. Традиционное имя
функции перевода — _, поэтому _(t"Hello {name}") читается как
«переведи это предложение». Учебник проходит весь путь
— пометить, извлечь, перевести, скомпилировать, запустить — примерно за
пять минут.
Решаемая проблема¶
К моменту вызова любой библиотеки f-строка уже интерполирована —
f"Hello {name}" превратилась в "Hello Ada", а перевод фрагментов вокруг
значения ломает грамматику большинства языков. t-строка (PEP 750) сохраняет
отдельно статический текст, вычисленные значения, исходные выражения,
преобразования и спецификации формата — именно такое разделение нужно каталогу
сообщений.
Что это меняет по сравнению с %(name)s, .format() и
$-строками.
При этом ни gettext, ни Babel не определяют, как превратить t-строку в сообщение. Эта библиотека фиксирует решение в версионируемой спецификации и поставляет набор тестов на соответствие.
Правила проектирования¶
- Переводить полные сообщения, а не части предложений.
- Разрешать только простые имена переменных, например
{name}. - Оставлять
!rи:.2fпод контролем приложения и вне каталога. - Разрешать перестановку и повтор известных заполнителей, но не доступ к атрибутам и не добавление форматирования.
- Использовать обычные POT-, PO- и MO-файлы и существующие инструменты.
И встречный список того, что она намеренно не трогает: она не локализует числа, валюты и даты — отформатируйте их заранее с помощью Babel; она не экранирует отрендеренный вывод для HTML, оболочки или терминала; и она не способна судить, верен ли перевод, — только цел ли набор его заполнителей.
Установка¶
Нужен Python 3.14 или новее. У рендеринга нет зависимостей — используется
только gettext из стандартной библиотеки.
Извлечение и проверка каталогов идут через Babel, поэтому ставьте этот extra
везде, где запускается pybabel, — а это обычно среда разработки или CI, а не
продакшен-образ:
Что читать дальше¶
Начало работы — опыт работы с gettext не предполагается:
- Учебник — от пустой директории до работающего японского перевода за пять шагов, каждая команда показана с её выводом.
- Зачем нужны t-строки — одно сообщение четырьмя
способами и что
%(name)s,.format()и$-строки отдают каталогу.
Использование — рабочие справочники:
- Руководство — API времени выполнения: какую точку входа выбрать, множественное число, язык запроса, отложенные строки и что происходит, когда каталог неверен.
- Извлечение — справочник по
pybabel: настройка, собственные имена функций и как существующие инструменты бесплатно проверяют эти каталоги. - В продакшене — цикл, как его ведёт команда: цикл обновления, записи fuzzy, ворота CI, платформы перевода и поставка.
- Миграция — как перейти на это в проекте, где каталоги уже есть, по одной точке вызова за раз.
- Переводчикам — одна страница, которую можно передать
тому, кто правит
.po-файлы.
Устройство — от истории к реализации:
- Предыстория — почему существует эта библиотека: тридцать лет gettext, две PEP и обсуждение в stdlib, закрытое без ответа.
- Подводные камни — что на самом деле сломалось при переводе этого сайта на тридцать пять языков и какую половину способен поймать инструмент.
- Как это работает — от объекта шаблона PEP 750 до отрендеренной строки и кэши, которые делают проверку дешёвой.
Справочник — контракты:
- API — всё, что экспортирует пакет, на одной странице.
- Спецификация — соглашение t-строка ↔ msgid как стабильный версионируемый контракт с машиночитаемым набором тестов соответствия.
Состояние¶
| Версия пакета | 0.1.0a8 |
| Стабильность API | alpha — Python API ещё может измениться |
| Спецификация | v1, с набором тестов на соответствие |
| Python | 3.14 и новее; протестировано на 3.14, 3.14t (free-threaded) и 3.15 |
| Babel | 2.18 или новее, и только там, где запускается pybabel |
| Зависимости времени выполнения | нет — gettext из стандартной библиотеки |
| Формат каталогов | обычные POT, PO и MO |
| Изменения | CHANGELOG |
Alpha. Контракт намеренно небольшой, и спецификация — его стабильная часть; Python API ещё может измениться. До стабильного выпуска нужны более широкий набор языковых примеров, постоянные измерения производительности, обзор API от тех, кто всерьёз работает с gettext и Babel, и проверка совместимости со всеми поддерживаемыми выпусками Python и Babel.
Issues и pull requests приветствуются: alpha — как раз то время, когда об интерфейсе ещё стоит спорить.
Сообщество¶
- Выберите ограниченную good first issue.
- Задавайте вопросы об использовании в Q&A Discussions.
- Приносите рабочие процессы gettext из продакшена и идеи по API в Ideas Discussions.
- Перед pull request прочитайте руководство для участников.