Als je ooit een Django-app in meer dan één taal hebt uitgebracht, ken je de procedure. Je wikkelt je strings in gettext(), draait makemessages, opent een .po-bestand met honderden regels en begint regel voor regel te vertalen. Voor twee talen en vijftig strings is dat te doen. Voor zes talen en vijfhonderd strings is het een volledige werkdag die je nooit meer terugkrijgt.
Deze gids behandelt de internationalisatie (i18n) pipeline van Django van begin tot eind, legt uit waar het misgaat en laat zien hoe je het pijnlijke deel automatiseert met AI-gestuurde vertaling.
De standaard Django i18n-workflow
Het ingebouwde i18n-systeem van Django is goed ontworpen. De kernlus ziet er zo uit:
Stap 1: Markeer strings voor vertaling in je Python-code en templates:
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>
Stap 2: Extraheer strings naar .po-bestanden:
python manage.py makemessages -l de -l fr -l nl
Dit scant je hele codebase en genereert één .po-bestand per taal, met daarin elke vertaalbare string:
#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""
#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""
Stap 3: Vertaal elke lege msgstr met de hand.
Stap 4: Compileer de voltooide .po-bestanden naar binaire .mo-bestanden:
python manage.py compilemessages
Stappen 1, 2 en 4 zijn snel. Stap 3 is waar het proces vastloopt.
Waarom handmatig vertalen niet schaalt
Een typische Django-applicatie heeft ergens tussen de 200 en 2.000 vertaalbare strings. Vermenigvuldig dat met het aantal doeltalen en je kijkt naar een serieuze tijdsinvestering.
Dit is geen theoretische klacht. In een bekende Django Forum-thread meldde een ontwikkelaar dat hij meer dan 8 uur per .po-bestand besteedde aan handmatige vertalingen. Een Django core contributor beschreef meer dan 10 uur te besteden aan het verwerken van door de community ingediende vertalingen in een enkele release, voornamelijk aan review, opmaakcorrecties en het repareren van kapotte placeholders.
De problemen stapelen zich op in de loop van de tijd:
- Placeholders gaan kapot. Kopieer een string als
Welcome, %(name)s!naar Google Translate en je krijgt vaakWillkommen, %(Name)s!ofBienvenue, %(nom)s!terug. Die subtiele corruptie veroorzaakt runtime-crashes. - Consistentie verdwijnt. Zonder een woordenlijst wordt "dashboard" in het ene bestand vertaald als "Instrumententafel" en in het andere als "Dashboard". Drie maanden later weet niemand meer welke opzettelijk was.
- Sprints voegen strings toe. Elke feature branch voegt nieuwe vertaalbare strings toe. Zelfs als je vorig kwartaal hebt betaald voor een volledige vertaalronde, heb je nu 40 onvertaalde regels verspreid over je
.po-bestanden. - AI-assistenten helpen één keer. Je kunt een
.po-bestand in ChatGPT of Claude plakken en redelijke resultaten krijgen. Maar volgende sprint, wanneer er 15 nieuwe strings verschijnen, prompt je vanaf nul, vertaal je het hele bestand opnieuw en hoop je dat het consistent blijft met wat er al was.
De grondoorzaak is dat vertaling wordt behandeld als een eenmalige gebeurtenis in plaats van een incrementeel, herhaalbaar proces.
Vertaling automatiseren met AI
Het idee is eenvoudig: in plaats van dat een mens elk .po-bestand opent en msgstr-waarden invult, leest een tool het bestand, stuurt onvertaalde strings naar een AI-model of vertaal-API, schrijft de resultaten terug en behoudt al het andere (opmerkingen, bestandsstructuur, placeholders, meervoudsvormen).
TranslateBot Django is een open-source pakket dat precies dit doet. Het sluit aan op het management command-systeem van Django, dus het past in de workflow die je al hebt.
Stapsgewijze installatie
1. Installeer het pakket
pip install translatebot-django
Of, als je uv gebruikt (aanbevolen):
uv add --dev translatebot-django
Installeren als dev-dependency is opzettelijk. Je hebt TranslateBot alleen nodig bij het genereren van vertalingen, niet tijdens runtime in productie.
2. Voeg toe aan INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
# ...
"translatebot_django",
]
3. Configureer je AI-provider
# settings.py
import os
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"
TranslateBot gebruikt LiteLLM onder de motorkap, wat betekent dat je elk van de 100+ modellen kunt inwisselen door één string te wijzigen:
| Provider | TRANSLATEBOT_MODEL-waarde |
|---|---|
| OpenAI | gpt-4o-mini, gpt-4o |
| Anthropic | claude-sonnet-4-5-20250929 |
gemini/gemini-2.5-flash |
|
| Azure OpenAI | azure/gpt-4o-mini |
| DeepL | Gebruik in plaats daarvan TRANSLATEBOT_PROVIDER = "deepl" |
Voor DeepL installeer je de extra: pip install translatebot-django[deepl]. De gratis tier van DeepL geeft je 500.000 tekens per maand zonder kosten, wat voldoende is voor de meeste kleine tot middelgrote projecten.
4. Definieer je talen
# settings.py
LANGUAGES = [
("en", "English"),
("de", "German"),
("fr", "French"),
("nl", "Dutch"),
("ja", "Japanese"),
]
5. Voer de vertaling uit
python manage.py translate
Dat is het. TranslateBot scant je project op .po-bestanden, identificeert onvertaalde regels, stuurt ze in geoptimaliseerde batches naar het geconfigureerde AI-model en schrijft de resultaten terug. Bestaande vertalingen worden niet aangeraakt.
Om een enkele taal te vertalen:
python manage.py translate --target-lang nl
De uitvoer ziet er zo uit:
Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings
6. Compileer zoals gebruikelijk
python manage.py compilemessages
Je volledige workflow is nu:
python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages
Drie commando's. Elke taal. Elke sprint.
Incrementeel van ontwerp
De belangrijkste functie voor een herhaalbare workflow is incrementele vertaling. TranslateBot vertaalt alleen regels waar msgstr leeg is. Als je 500 strings hebt en er 15 nieuw zijn deze sprint, worden alleen die 15 naar de API gestuurd.
Dit is om praktische redenen belangrijk:
- Kosten. Je betaalt alleen voor nieuwe strings, niet voor het hele bestand.
- Snelheid. Het vertalen van 15 strings duurt seconden, geen minuten.
- Stabiliteit. Vertalingen die je al hebt gereviewed en goedgekeurd worden nooit overschreven (tenzij je expliciet
--overwritemeegeeft).
Placeholder-veiligheid
Django gebruikt verschillende placeholder-formaten: %(name)s, %s, %d, {0}, {name} en inline HTML-tags zoals <strong> of <a href="...">. Als een van deze beschadigd raakt bij vertaling, krijg je runtime-fouten of kapotte opmaak.
TranslateBot instrueert het AI-model om alle placeholder-formaten te behouden en valideert de uitvoer. Een string als:
Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.
Wordt naar het Nederlands vertaald als:
Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.
Elke placeholder blijft intact.
Kwaliteit beheren met TRANSLATING.md
AI-modellen vertalen beter wanneer ze de context begrijpen. TranslateBot zoekt naar een TRANSLATING.md-bestand in je projectroot en neemt de inhoud op in elk vertaalverzoek.
# 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"
Dit bestand wordt samen met je code versiebeheerd, zodat je hele team dezelfde vertaalcontext deelt. Je kunt ook per app TRANSLATING.md-bestanden plaatsen voor apps met gespecialiseerde terminologie. Een module voor medische dossiers en een facturatiemodule kunnen elk hun eigen woordenlijst hebben.
Voorvertoning voor commit
De --dry-run-vlag toont precies wat er vertaald zou worden zonder API-aanroepen te doen of bestanden te wijzigen:
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
Dit is nuttig voor een grote vertaalronde of bij het inwerken van een nieuw teamlid dat wil begrijpen wat het commando doet voordat ze zich committeren aan API-kosten.
CI/CD-integratie
Vertalingen die verouderen is onvermijdelijk zonder handhaving. TranslateBot bevat een check_translations management command ontworpen voor CI-pipelines:
# .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
De --makemessages-vlag draait eerst makemessages -a --no-obsolete, zodat .po-bestanden de huidige broncode weerspiegelen voordat er gecontroleerd wordt. Als er onvertaalde of fuzzy regels zijn, eindigt het commando met code 1 en faalt de build:
locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed
De typische ontwikkelaarsworkflow wordt:
- Voeg nieuwe vertaalbare strings toe in een feature branch.
- CI faalt omdat die strings onvertaald zijn.
- Draai
python manage.py translatelokaal. - Commit de bijgewerkte
.po-bestanden. - CI slaagt.
Vertalingen raken nooit stilletjes uit sync.
Database-inhoud vertalen
Als je applicatie vertaalbare inhoud in de database opslaat (productnamen, blogtitels, categorielabels), integreert TranslateBot ook met 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
Dezelfde incrementele logica is van toepassing: alleen velden waar de doeltaalwaarde leeg is worden vertaald.
Kostenvergelijking
Een van de meest gestelde vragen is of AI-vertaling kosteneffectief is vergeleken met alternatieven. Hier is een ruwe vergelijking voor een project met 500 vertaalbare strings in 5 talen:
| Aanpak | Geschatte kosten | Tijdsinvestering |
|---|---|---|
| Handmatig (ontwikkelaarstijd) | $0 uit eigen zak, 20-40+ uur | Zeer hoog |
| Professionele vertaaldienst | $500-2.000+ | Laag (maar trage doorlooptijd) |
| SaaS-lokalisatieplatform | $50-200/maand | Gemiddeld |
| TranslateBot + GPT-4o-mini | ~$0,05 (eenmalig) | Minuten |
| TranslateBot + DeepL Free | $0 (tot 500k tekens/maand) | Minuten |
| TranslateBot + Claude/GPT-4o | ~$0,30 (eenmalig) | Minuten |
De cijfers verschuiven afhankelijk van het aantal strings en doeltalen, maar het verschil in orde van grootte is consistent. Voor doorlopend onderhoud (het vertalen van de 20-50 nieuwe strings die elke sprint worden toegevoegd) zijn de AI-kosten in wezen nul.
Best practices
Begin met --dry-run. Voordat je de eerste echte vertaalronde draait, bekijk wat er gaat gebeuren. Dit bouwt vertrouwen op en vangt configuratieproblemen vroegtijdig op.
Commit .po-bestanden voor het vertalen. Als er iets misgaat, brengt git checkout je direct terug naar een schone staat.
Schrijf vanaf dag één een TRANSLATING.md. Zelfs een kort bestand met je projectbeschrijving en een paar terminologieregels verbetert de vertaalkwaliteit meetbaar.
Voeg check_translations toe aan CI. Deze ene stap voorkomt de meest voorkomende i18n-foutmodus: strings die gemarkeerd zijn voor vertaling maar nooit daadwerkelijk vertaald.
Gebruik gpt-4o-mini of DeepL voor kostenefficiëntie. Bewaar premiummodellen zoals GPT-4o of Claude voor projecten waar precisie ertoe doet, zoals marketingtekst, juridische tekst of domeinspecifieke terminologie.
Review kritieke strings. AI-vertalingen zijn goed genoeg voor de meeste UI-tekst, maar laat een native speaker alles reviewen dat juridisch bindend is, veiligheidskritisch is of klantgericht is in een context met hoge inzet.
Van uren naar seconden
Het i18n-framework van Django is uitstekend in het extraheren en compileren van vertalingen. De kloof zat altijd in de vertaalstap zelf, het vervelende, foutgevoelige werk van het invullen van honderden msgstr-waarden in meerdere talen.
TranslateBot dicht die kloof. Installeer het, wijs het naar een AI-provider en draai één commando. Nieuwe strings worden vertaald. Bestaande strings blijven onaangetast. Placeholders blijven intact. CI vangt alles op dat erdoorheen glipt.
Je .po-bestanden zijn niet langer een karwei maar gewoon weer een onderdeel van de build.
pip install translatebot-django
Ga aan de slag op translatebot.dev.