Назад к блогу

Django i18n: полное руководство по автоматизации перевода .po файлов

2026-01-28 9 мин чтения
Django i18n: полное руководство по автоматизации перевода .po файлов

Если вы когда-нибудь выпускали приложение на Django более чем на одном языке, вы знаете этот процесс. Вы оборачиваете строки в gettext(), запускаете makemessages, открываете файл .po с сотнями записей и начинаете переводить строку за строкой. Для двух языков и пятидесяти строк это терпимо. Для шести языков и пятисот строк — это целый рабочий день, который вы никогда не вернёте.

Это руководство охватывает конвейер интернационализации (i18n) Django от начала до конца, объясняет, где он даёт сбой, и показывает, как автоматизировать самую болезненную часть с помощью перевода на базе ИИ.

Стандартный рабочий процесс Django i18n

Встроенная система i18n Django хорошо спроектирована. Основной цикл выглядит так:

Шаг 1: Отметьте строки для перевода в вашем Python-коде и шаблонах:

from django.utils.translation import gettext as _

def dashboard(request):
    welcome = _("Welcome back, %(name)s!") % {"name": request.user.first_name}
    return render(request, "dashboard.html", {"welcome": welcome})
{% load i18n %}
<h1>{% trans "Account Settings" %}</h1>
<p>{% blocktrans %}You have {{ count }} unread messages.{% endblocktrans %}</p>

Шаг 2: Извлеките строки в файлы .po:

python manage.py makemessages -l de -l fr -l nl

Это сканирует всю вашу кодовую базу и генерирует по одному файлу .po для каждого языка, содержащему все переводимые строки:

#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""

#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""

Шаг 3: Переведите каждый пустой msgstr вручную.

Шаг 4: Скомпилируйте готовые файлы .po в бинарные файлы .mo:

python manage.py compilemessages

Шаги 1, 2 и 4 быстрые. Шаг 3 — это то место, где процесс разваливается.

Почему ручной перевод не масштабируется

Типичное приложение на Django содержит от 200 до 2 000 переводимых строк. Умножьте это на количество целевых языков, и вы столкнётесь с серьёзными временными затратами.

Это не теоретическая жалоба. В известном треде на Django Forum разработчик сообщил, что потратил более 8 часов на один файл .po при ручном переводе. Один из основных контрибьюторов Django описал, как потратил более 10 часов на включение переводов, присланных сообществом, в один релиз — в основном на проверку, исправление форматирования и починку сломанных плейсхолдеров.

Проблемы накапливаются со временем:

Корневая причина в том, что перевод рассматривается как разовое событие, а не как инкрементальный, повторяемый процесс.

Автоматизация перевода с помощью ИИ

Идея проста: вместо того чтобы человек открывал каждый файл .po и заполнял значения msgstr, инструмент читает файл, отправляет непереведённые строки в модель ИИ или API перевода, записывает результаты обратно и сохраняет всё остальное (комментарии, структуру файла, плейсхолдеры, формы множественного числа).

TranslateBot Django — это пакет с открытым исходным кодом, который делает именно это. Он встраивается в систему management-команд Django, поэтому вписывается в рабочий процесс, который у вас уже есть.

Пошаговая настройка

1. Установите пакет

pip install translatebot-django

Или, если вы используете uv (рекомендуется):

uv add --dev translatebot-django

Установка в качестве dev-зависимости сделана намеренно. TranslateBot нужен только при генерации переводов, а не в продакшене во время выполнения.

2. Добавьте в INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    # ...
    "translatebot_django",
]

3. Настройте провайдера ИИ

# settings.py
import os

TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"

TranslateBot использует LiteLLM под капотом, что означает, что вы можете переключиться на любую из 100+ моделей, изменив одну строку:

Провайдер Значение TRANSLATEBOT_MODEL
OpenAI gpt-4o-mini, gpt-4o
Anthropic claude-sonnet-4-5-20250929
Google gemini/gemini-2.5-flash
Azure OpenAI azure/gpt-4o-mini
DeepL Используйте TRANSLATEBOT_PROVIDER = "deepl" вместо этого

Для DeepL установите дополнение: pip install translatebot-django[deepl]. Бесплатный тариф DeepL даёт вам 500 000 символов в месяц бесплатно, чего достаточно для большинства малых и средних проектов.

4. Определите ваши языки

# settings.py
LANGUAGES = [
    ("en", "English"),
    ("de", "German"),
    ("fr", "French"),
    ("nl", "Dutch"),
    ("ja", "Japanese"),
]

5. Запустите перевод

python manage.py translate

Вот и всё. TranslateBot сканирует ваш проект в поисках файлов .po, определяет непереведённые записи, отправляет их в настроенную модель ИИ оптимизированными пакетами и записывает результаты обратно. Существующие переводы остаются нетронутыми.

Для перевода одного языка:

python manage.py translate --target-lang nl

Вывод выглядит так:

Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings

6. Скомпилируйте как обычно

python manage.py compilemessages

Ваш полный рабочий процесс теперь выглядит так:

python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages

Три команды. Все языки. Каждый спринт.

Инкрементальность по замыслу

Самая важная функция для повторяемого рабочего процесса — инкрементальный перевод. TranslateBot переводит только записи, где msgstr пуст. Если у вас 500 строк и 15 новых в этом спринте, только эти 15 отправляются в API.

Это важно по практическим причинам:

  1. Стоимость. Вы платите только за новые строки, а не за весь файл.
  2. Скорость. Перевод 15 строк занимает секунды, а не минуты.
  3. Стабильность. Переводы, которые вы уже проверили и утвердили, никогда не перезаписываются (если вы явно не передадите --overwrite).

Безопасность плейсхолдеров

Django использует несколько форматов плейсхолдеров: %(name)s, %s, %d, {0}, {name}, а также встроенные HTML-теги вроде <strong> или <a href="...">. Если любой из них будет повреждён при переводе, вы получите ошибки во время выполнения или сломанную разметку.

TranslateBot инструктирует модель ИИ сохранять все форматы плейсхолдеров и валидирует вывод. Строка вроде:

Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.

Переводится на нидерландский как:

Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.

Каждый плейсхолдер сохраняется в целости.

Управление качеством с помощью TRANSLATING.md

Модели ИИ переводят лучше, когда понимают контекст. TranslateBot ищет файл TRANSLATING.md в корне вашего проекта и включает его содержимое в каждый запрос на перевод.

# Translation Context

## About This Project
A B2B project management tool for construction companies.

## Terminology
- "project" means a construction project, not a software project
- "plan" means a building plan/blueprint, not a subscription plan
- Keep "Gantt chart" as-is in all languages

## Tone
- German: use formal "Sie" form (business context)
- French: use formal "vous" form
- Dutch: use informal "je" form

## Do Not Translate
- Brand name: "BuildFlow"
- Feature names: "SmartSchedule", "CostTracker"

Этот файл находится под контролем версий вместе с вашим кодом, поэтому вся команда разделяет один и тот же контекст перевода. Вы также можете размещать файлы TRANSLATING.md для отдельных приложений со специализированной терминологией. Модуль медицинских записей и модуль выставления счетов могут иметь собственные глоссарии.

Предварительный просмотр перед коммитом

Флаг --dry-run показывает, что именно будет переведено, без вызовов API и изменения файлов:

python manage.py translate --target-lang fr --dry-run
Found 15 untranslated entries
Dry run mode: skipping LLM translation

Would translate 'Welcome to our site'
Would translate 'Hello, %(name)s!'
...

Dry run complete: 15 entries would be translated

Это полезно перед большим запуском перевода или когда новый член команды хочет понять, что делает команда, прежде чем нести расходы на API.

Интеграция с CI/CD

Без принудительных проверок переводы неизбежно устаревают. TranslateBot включает management-команду check_translations, предназначенную для CI-конвейеров:

# .github/workflows/ci.yml
jobs:
  translations:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v4
        with:
          enable-cache: true
      - run: uv python install
      - run: uv sync --frozen
      - name: Install gettext
        run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gettext
      - name: Check translations
        run: uv run python manage.py check_translations --makemessages

Флаг --makemessages сначала запускает makemessages -a --no-obsolete, гарантируя, что файлы .po отражают текущий исходный код перед проверкой. Если какие-либо записи непереведены или помечены как fuzzy, команда завершается с кодом 1 и проваливает сборку:

locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed

Типичный рабочий процесс разработчика становится таким:

  1. Добавить новые переводимые строки в функциональной ветке.
  2. CI проваливается, потому что эти строки не переведены.
  3. Запустить python manage.py translate локально.
  4. Закоммитить обновлённые файлы .po.
  5. CI проходит.

Переводы никогда не рассинхронизируются незаметно.

Перевод контента базы данных

Если ваше приложение хранит переводимый контент в базе данных (названия продуктов, заголовки статей блога, метки категорий), TranslateBot также интегрируется с django-modeltranslation:

pip install translatebot-django[modeltranslation]
# Translate all registered model fields
python manage.py translate --target-lang de --models

# Translate specific models only
python manage.py translate --target-lang de --models Product Category

Та же инкрементальная логика применяется: переводятся только поля, где значение целевого языка пусто.

Сравнение затрат

Один из самых частых вопросов — является ли перевод с помощью ИИ экономически эффективным по сравнению с альтернативами. Вот приблизительное сравнение для проекта с 500 переводимыми строками на 5 языках:

Подход Ориентировочная стоимость Затраты времени
Ручной (время разработчика) $0 из кармана, 20-40+ часов Очень высокие
Профессиональная служба перевода $500-2 000+ Низкие (но долгие сроки)
SaaS-платформа локализации $50-200/мес. Средние
TranslateBot + GPT-4o-mini ~$0,05 (разово) Минуты
TranslateBot + DeepL Free $0 (до 500 тыс. символов/мес.) Минуты
TranslateBot + Claude/GPT-4o ~$0,30 (разово) Минуты

Цифры меняются в зависимости от количества строк и целевых языков, но разница на порядок остаётся стабильной. Для текущего обслуживания (перевод 20-50 новых строк, добавляемых каждый спринт) стоимость ИИ практически равна нулю.

Лучшие практики

Начните с --dry-run. Перед первым реальным запуском перевода посмотрите, что произойдёт. Это укрепляет уверенность и выявляет проблемы конфигурации на ранних этапах.

Закоммитьте файлы .po перед переводом. Если что-то пойдёт не так, git checkout мгновенно вернёт вас к чистому состоянию.

Напишите TRANSLATING.md с первого дня. Даже краткий файл с описанием вашего проекта и несколькими терминологическими правилами заметно улучшает качество перевода.

Добавьте check_translations в CI. Этот единственный шаг предотвращает самый распространённый режим сбоя i18n: строки, которые были отмечены для перевода, но так и не были переведены.

Используйте gpt-4o-mini или DeepL для экономии. Приберегите премиум-модели вроде GPT-4o или Claude для проектов, где важна точность — маркетинговые тексты, юридические документы или узкоспециализированная терминология.

Проверяйте критически важные строки. Переводы ИИ достаточно хороши для большинства текстов интерфейса, но для юридически обязывающих, критически важных для безопасности или клиентских материалов в высокорисковом контексте привлеките носителя языка для проверки.

От часов к секундам

Фреймворк i18n в Django отлично справляется с извлечением и компиляцией переводов. Пробел всегда был в самом шаге перевода — утомительной, подверженной ошибкам работе по заполнению сотен значений msgstr на нескольких языках.

TranslateBot закрывает этот пробел. Установите его, укажите провайдера ИИ и запустите одну команду. Новые строки переводятся. Существующие строки остаются нетронутыми. Плейсхолдеры остаются целыми. CI ловит всё, что проскочило.

Ваши файлы .po перестают быть рутиной и становятся просто ещё одной частью сборки.

pip install translatebot-django

Начните на translatebot.dev.

Прекратите редактировать .po файлы вручную

TranslateBot автоматизирует переводы Django с помощью ИИ. Одна команда, все ваши языки, копейки за перевод.