Retour au blog

Django i18n : le guide complet pour automatiser la traduction des fichiers .po

2026-01-28 10 min de lecture
Django i18n : le guide complet pour automatiser la traduction des fichiers .po

Si vous avez déjà livré une application Django dans plus d'une langue, vous connaissez la routine. Vous encapsulez vos chaînes dans gettext(), vous exécutez makemessages, vous ouvrez un fichier .po avec des centaines d'entrées, et vous commencez à traduire ligne par ligne. Pour deux langues et cinquante chaînes, c'est tolérable. Pour six langues et cinq cents chaînes, c'est une journée entière de travail que vous ne récupérerez jamais.

Ce guide couvre le pipeline d'internationalisation (i18n) de Django du début à la fin, explique où il échoue, et montre comment automatiser la partie pénible avec la traduction assistée par IA.

Le workflow standard de Django i18n

Le système i18n intégré de Django est bien conçu. La boucle principale ressemble à ceci :

Étape 1 : Marquer les chaînes pour la traduction dans votre code Python et vos 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>

Étape 2 : Extraire les chaînes dans des fichiers .po :

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

Cela analyse l'ensemble de votre base de code et génère un fichier .po par langue, contenant chaque chaîne traduisible :

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

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

Étape 3 : Traduire chaque msgstr vide à la main.

Étape 4 : Compiler les fichiers .po terminés en fichiers binaires .mo :

python manage.py compilemessages

Les étapes 1, 2 et 4 sont rapides. L'étape 3 est celle où le processus s'effondre.

Pourquoi la traduction manuelle ne passe pas à l'échelle

Une application Django typique contient entre 200 et 2 000 chaînes traduisibles. Multipliez cela par le nombre de langues cibles, et vous faites face à un engagement de temps considérable.

Ce n'est pas une plainte théorique. Dans un fil de discussion bien connu du Django Forum, un développeur a rapporté avoir passé plus de 8 heures par fichier .po pour des traductions manuelles. Un contributeur principal de Django a décrit avoir passé plus de 10 heures à intégrer les traductions soumises par la communauté dans une seule release, principalement pour la revue, les corrections de formatage et la réparation des marqueurs de substitution cassés.

Les problèmes s'accumulent avec le temps :

La cause racine est que la traduction est traitée comme un événement ponctuel plutôt que comme un processus incrémental et reproductible.

Automatiser la traduction avec l'IA

L'idée est simple : au lieu qu'un humain ouvre chaque fichier .po et remplisse les valeurs msgstr, un outil lit le fichier, envoie les chaînes non traduites à un modèle d'IA ou une API de traduction, écrit les résultats en retour, et préserve tout le reste (commentaires, structure du fichier, marqueurs de substitution, formes plurielles).

TranslateBot Django est un package open source qui fait exactement cela. Il s'intègre au système de commandes de gestion de Django, et s'inscrit donc dans le workflow que vous avez déjà.

Configuration étape par étape

1. Installer le package

pip install translatebot-django

Ou, si vous utilisez uv (recommandé) :

uv add --dev translatebot-django

L'installer comme dépendance de développement est intentionnel. Vous n'avez besoin de TranslateBot que lors de la génération des traductions, pas à l'exécution en production.

2. Ajouter à INSTALLED_APPS

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

3. Configurer votre fournisseur d'IA

# settings.py
import os

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

TranslateBot utilise LiteLLM en interne, ce qui signifie que vous pouvez passer à n'importe lequel des 100+ modèles en changeant une seule chaîne :

Fournisseur Valeur de 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 Utilisez TRANSLATEBOT_PROVIDER = "deepl" à la place

Pour DeepL, installez l'extra : pip install translatebot-django[deepl]. Le niveau gratuit de DeepL vous donne 500 000 caractères par mois sans frais, ce qui est suffisant pour la plupart des projets de petite à moyenne taille.

4. Définir vos langues

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

5. Lancer la traduction

python manage.py translate

C'est tout. TranslateBot analyse votre projet à la recherche de fichiers .po, identifie les entrées non traduites, les envoie au modèle d'IA configuré par lots optimisés, et écrit les résultats en retour. Les traductions existantes restent intactes.

Pour traduire une seule langue :

python manage.py translate --target-lang nl

La sortie ressemble à ceci :

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

6. Compiler comme d'habitude

python manage.py compilemessages

Votre workflow complet est maintenant :

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

Trois commandes. Toutes les langues. Chaque sprint.

Incrémental par conception

La fonctionnalité la plus importante pour un workflow reproductible est la traduction incrémentale. TranslateBot ne traduit que les entrées où msgstr est vide. Si vous avez 500 chaînes et que 15 sont nouvelles ce sprint, seules ces 15 sont envoyées à l'API.

Cela compte pour des raisons pratiques :

  1. Coût. Vous ne payez que pour les nouvelles chaînes, pas pour le fichier entier.
  2. Vitesse. Traduire 15 chaînes prend des secondes, pas des minutes.
  3. Stabilité. Les traductions que vous avez déjà revues et approuvées ne sont jamais écrasées (sauf si vous passez explicitement --overwrite).

Sécurité des marqueurs de substitution

Django utilise plusieurs formats de marqueurs de substitution : %(name)s, %s, %d, {0}, {name}, et des balises HTML en ligne comme <strong> ou <a href="...">. Si l'un d'entre eux est altéré lors de la traduction, vous obtenez des erreurs à l'exécution ou du balisage cassé.

TranslateBot demande au modèle d'IA de préserver tous les formats de marqueurs de substitution et valide la sortie. Une chaîne comme :

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

Est traduite en néerlandais comme :

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

Chaque marqueur de substitution survit intact.

Contrôler la qualité avec TRANSLATING.md

Les modèles d'IA traduisent mieux quand ils comprennent le contexte. TranslateBot cherche un fichier TRANSLATING.md à la racine de votre projet et inclut son contenu dans chaque requête de traduction.

# 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"

Ce fichier est versionné avec votre code, de sorte que toute votre équipe partage le même contexte de traduction. Vous pouvez également placer des fichiers TRANSLATING.md par application pour les apps avec une terminologie spécialisée. Un module de dossiers médicaux et un module de facturation peuvent chacun avoir leur propre glossaire.

Prévisualiser avant de committer

Le drapeau --dry-run montre exactement ce qui serait traduit sans effectuer d'appels API ni modifier de fichiers :

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

C'est utile avant une grande session de traduction ou quand un nouveau membre de l'équipe veut comprendre ce que fait la commande avant de s'engager sur les coûts d'API.

Intégration CI/CD

L'obsolescence des traductions est inévitable sans enforcement. TranslateBot inclut une commande de gestion check_translations conçue pour les pipelines 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

Le drapeau --makemessages exécute d'abord makemessages -a --no-obsolete, garantissant que les fichiers .po reflètent le code source actuel avant vérification. Si des entrées sont non traduites ou floues, la commande se termine avec le code 1 et fait échouer le 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

Le workflow typique du développeur devient :

  1. Ajouter de nouvelles chaînes traduisibles dans une branche de fonctionnalité.
  2. Le CI échoue parce que ces chaînes ne sont pas traduites.
  3. Exécuter python manage.py translate localement.
  4. Committer les fichiers .po mis à jour.
  5. Le CI passe.

Les traductions ne se désynchronisent jamais silencieusement.

Traduire le contenu de la base de données

Si votre application stocke du contenu traduisible dans la base de données (noms de produits, titres d'articles de blog, libellés de catégories), TranslateBot s'intègre également avec 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

La même logique incrémentale s'applique : seuls les champs où la valeur de la langue cible est vide sont traduits.

Comparaison des coûts

L'une des questions les plus courantes est de savoir si la traduction par IA est rentable par rapport aux alternatives. Voici une comparaison approximative pour un projet avec 500 chaînes traduisibles en 5 langues :

Approche Coût estimé Investissement en temps
Manuel (temps développeur) 0 $ de poche, 20-40+ heures Très élevé
Service de traduction professionnel 500-2 000 $+ Faible (mais délai long)
Plateforme de localisation SaaS 50-200 $/mois Moyen
TranslateBot + GPT-4o-mini ~0,05 $ (ponctuel) Minutes
TranslateBot + DeepL Free 0 $ (jusqu'à 500k caractères/mois) Minutes
TranslateBot + Claude/GPT-4o ~0,30 $ (ponctuel) Minutes

Les chiffres varient selon le nombre de chaînes et de langues cibles, mais la différence d'ordre de grandeur est constante. Pour la maintenance continue (traduire les 20-50 nouvelles chaînes ajoutées chaque sprint), le coût de l'IA est essentiellement nul.

Bonnes pratiques

Commencez par --dry-run. Avant votre première vraie session de traduction, prévisualisez ce qui va se passer. Cela renforce la confiance et détecte les problèmes de configuration tôt.

Committez les fichiers .po avant de traduire. Si quelque chose tourne mal, git checkout vous ramène instantanément à un état propre.

Rédigez un TRANSLATING.md dès le premier jour. Même un fichier succinct avec la description de votre projet et quelques règles de terminologie améliore de manière mesurable la qualité de traduction.

Ajoutez check_translations au CI. Cette seule étape prévient le mode de défaillance i18n le plus courant : des chaînes marquées pour traduction mais jamais réellement traduites.

Utilisez gpt-4o-mini ou DeepL pour l'efficacité des coûts. Réservez les modèles premium comme GPT-4o ou Claude pour les projets où la précision compte, comme les textes marketing, les textes juridiques ou la terminologie spécifique à un domaine.

Relisez les chaînes critiques. Les traductions par IA sont suffisamment bonnes pour la plupart des textes d'interface, mais faites relire par un locuteur natif tout ce qui est juridiquement contraignant, critique pour la sécurité ou destiné au client dans un contexte à fort enjeu.

De heures à secondes

Le framework i18n de Django est excellent pour extraire et compiler les traductions. Le manque a toujours été l'étape de traduction elle-même, le travail fastidieux et sujet aux erreurs de remplir des centaines de valeurs msgstr dans plusieurs langues.

TranslateBot comble ce manque. Installez-le, pointez-le vers un fournisseur d'IA, et exécutez une commande. Les nouvelles chaînes sont traduites. Les chaînes existantes restent intactes. Les marqueurs de substitution restent intacts. Le CI attrape tout ce qui passe entre les mailles.

Vos fichiers .po cessent d'être une corvée et deviennent simplement une partie du build.

pip install translatebot-django

Commencez sur translatebot.dev.

Arrêtez d'éditer les fichiers .po manuellement

TranslateBot automatise les traductions Django avec l'IA. Une commande, toutes vos langues, des centimes par traduction.