TranslateBot Django¶
AI translation for Django, covering both your .po files and the content in your database. Run one command after each change and only the new text gets translated.
The problem¶
Static strings are the easy part of translating a Django app. makemessages collects them into .po files, and plenty of tools can fill those in.
Database content is harder. Editors write product names, blog posts and category pages after you deploy, so that text never passes through gettext. With django-modeltranslation every language gets its own column, and someone has to work out which rows are missing which language. A translated slug still has to be a valid slug. Some of your existing translations may be machine output themselves, which makes them a poor source for the next language.
The usual options don't fit:
- Copying text into Google Translate works for 20 strings. At 200 it falls apart, and you fix every broken placeholder by hand.
- ChatGPT or Claude Code will translate a
.pofile well enough once. Next sprint you're prompting from scratch again, re-translating the whole file and hoping the terminology still matches. - Localization platforms charge per word. You also get portals and review workflows that a solo developer or small team doesn't need.
What TranslateBot does¶
TranslateBot adds a translate management command to your project. It translates whatever is missing and leaves existing translations alone.
Database content¶
With django-modeltranslation installed, python manage.py translate --models fills the empty language columns of every registered model. Pass model names to limit it to those models. See Model Translation.
- It translates from your default language whenever that column has text, since the other languages may already be machine translations. If it's empty, the first language with content is used.
- Rows created before you installed modeltranslation only have text in the original column. TranslateBot reads it from there.
- Slug fields are slugified again and cut to their
max_lengthat a word boundary. File and image fields are skipped. - Columns that already have a translation stay as they are unless you pass
--overwrite.
New content keeps arriving after you deploy, so the same function is available from Python. Call it from a Celery task or a signal handler when editors publish (see the Python API).
PO files¶
- Only new and changed strings are translated. Add 10 strings in a sprint and you pay for 10, not the whole file.
- A
TRANSLATING.mdfile in your repo holds your glossary, tone and brand rules. Every run uses it, so a term you translated last month comes out the same today. - Placeholders such as
%(name)s,{0}and%sand HTML tags are kept intact. LLM providers are told to preserve them, and DeepL gets them as protected tokens. - Every translation is checked before it's written, using the rules
compilemessagesapplies topython-formatandpython-brace-formatstrings. A translation that drops or changes a placeholder is retried once. If it fails again, an untranslated entry gets it as a#, fuzzydraft.compilemessagesskips fuzzy entries, so a bad translation never breaks your build, and the run ends with a list of drafts to review. - With LLM providers, each plural form of the target language gets its own translation (Polish, Russian, Arabic, …).
pgettextcontexts keep "May" the month apart from "May" the verb.
Everything else¶
- It works with OpenAI, Anthropic, Google Gemini, Azure and any provider LiteLLM supports, or with DeepL.
- One run covers every language in
LANGUAGES. Adding a locale takes one line in your settings. - Strings are batched into as few API requests as possible.
python manage.py check_translationsfails your CI build when strings are untranslated or fuzzy (CI Integration).- You configure it in Django settings, and
--llm-modeloverrides the model for a single run. The API key can also come from theTRANSLATEBOT_API_KEYenvironment variable. --dry-runshows what would be translated before anything is written.- The test suite covers 100% of the code.
Quick example¶
# Install
uv add --dev translatebot-django
# Configure (settings.py)
INSTALLED_APPS = ['translatebot_django', ...]
TRANSLATEBOT_API_KEY = "your-api-key"
# Translate!
python manage.py translate --target-lang nl
Supported versions¶
Each Django series is tested against the Python versions Django itself supports:
| Django | Python |
|---|---|
| 4.2 | 3.10, 3.11, 3.12 |
| 5.0 | 3.10, 3.11, 3.12 |
| 5.1 | 3.10, 3.11, 3.12, 3.13 |
| 5.2 | 3.10, 3.11, 3.12, 3.13, 3.14 |
| 6.0 | 3.12, 3.13, 3.14 |
| 6.1 | 3.12, 3.13, 3.14 |
Getting started¶
Ready to translate your Django app? Start with the Installation Guide.