Перейти к содержанию

Переводите сообщения целиком
с помощью 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 -m pip install gettext-tstrings

Нужен Python 3.14 или новее. У рендеринга нет зависимостей — используется только gettext из стандартной библиотеки.

Извлечение и проверка каталогов идут через Babel, поэтому ставьте этот extra везде, где запускается pybabel, — а это обычно среда разработки или CI, а не продакшен-образ:

python -m pip install "gettext-tstrings[babel]"

Что читать дальше

Начало работы — опыт работы с 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 — как раз то время, когда об интерфейсе ещё стоит спорить.

Сообщество