Skip to content

TranslateBot Django

PyPI Downloads Tests Coverage License: MPL 2.0

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 .po file 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_length at 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.md file 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 %s and 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 compilemessages applies to python-format and python-brace-format strings. A translation that drops or changes a placeholder is retried once. If it fails again, an untranslated entry gets it as a #, fuzzy draft. compilemessages skips 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, …). pgettext contexts 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_translations fails your CI build when strings are untranslated or fuzzy (CI Integration).
  • You configure it in Django settings, and --llm-model overrides the model for a single run. The API key can also come from the TRANSLATEBOT_API_KEY environment variable.
  • --dry-run shows 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.