Если вы когда-нибудь выпускали приложение на 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 часов на включение переводов, присланных сообществом, в один релиз — в основном на проверку, исправление форматирования и починку сломанных плейсхолдеров.
Проблемы накапливаются со временем:
- Плейсхолдеры ломаются. Скопируйте строку вроде
Welcome, %(name)s!в Google Translate, и вы часто получите обратноWillkommen, %(Name)s!илиBienvenue, %(nom)s!. Такое едва заметное повреждение вызывает ошибки во время выполнения. - Согласованность нарушается. Без глоссария "dashboard" переводится как "Instrumententafel" в одном файле и "Dashboard" в другом. Три месяца спустя никто не помнит, какой вариант был намеренным.
- Спринты добавляют строки. Каждая функциональная ветка добавляет новые переводимые строки. Даже если вы оплатили полный перевод в прошлом квартале, теперь у вас 40 непереведённых записей, разбросанных по файлам
.po. - ИИ-ассистенты помогают один раз. Вы можете вставить файл
.poв ChatGPT или Claude и получить приличные результаты. Но в следующем спринте, когда появятся 15 новых строк, вы снова составляете промпт с нуля, переводите весь файл заново и надеетесь, что он останется согласованным с тем, что уже было.
Корневая причина в том, что перевод рассматривается как разовое событие, а не как инкрементальный, повторяемый процесс.
Автоматизация перевода с помощью ИИ
Идея проста: вместо того чтобы человек открывал каждый файл .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 |
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.
Это важно по практическим причинам:
- Стоимость. Вы платите только за новые строки, а не за весь файл.
- Скорость. Перевод 15 строк занимает секунды, а не минуты.
- Стабильность. Переводы, которые вы уже проверили и утвердили, никогда не перезаписываются (если вы явно не передадите
--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
Типичный рабочий процесс разработчика становится таким:
- Добавить новые переводимые строки в функциональной ветке.
- CI проваливается, потому что эти строки не переведены.
- Запустить
python manage.py translateлокально. - Закоммитить обновлённые файлы
.po. - 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.