Démystifier gettext vs gettext_lazy dans Django (Comprendre le moment d’évaluation)
Lorsque vous utilisez l’internationalisation de Django, vous vous demandez souvent quel est le bon choix entre gettext() et gettext_lazy(). La plupart des confusions proviennent de la tentative de mémoriser les différences terminologiques.
Le principe est simple :
gettexttraduit immédiatement (évaluation immédiate, eager)gettext_lazyattend pour traduire (évaluation paresseuse, lazy)
Un seul concept d’évaluation suffit pour clarifier la plupart des cas.
Pourquoi le moment de la traduction est-il important ?
Dans Django, la langue change généralement à chaque requête.

- Le middleware active la langue du thread/corps de la requête via
activate("ko")ouactivate("en"). - La traduction doit se produire au moment du rendu du template, du formulaire ou de l’interface d’administration.
En d’autres termes, le moment où vous traduisez une chaîne détermine le résultat.
gettext() : traduire immédiatement et retourner la chaîne
from django.utils.translation import gettext as _
def view(request):
message = _("Welcome") # traduit selon la langue active au moment de l’exécution
return HttpResponse(message)
- Appelé dans une vue ou une fonction de service (runtime) → fonctionne comme prévu.
- Appelé au moment de l’importation du module → problème.
Piège courant : utiliser gettext() dans les constantes de module
# app/constants.py
from django.utils.translation import gettext as _
WELCOME = _("Welcome") # ❌ peut être « figé » dans la langue du démarrage du serveur
Dans ce cas, WELCOME reste la traduction effectuée lors de l’importation, même si la langue change par la suite.
gettext_lazy() : retourner un proxy qui se traduit plus tard
from django.utils.translation import gettext_lazy as _
WELCOME = _("Welcome") # ✅ un objet proxy, pas encore traduit
gettext_lazy() renvoie généralement un objet proxy paresseux.
- Lors du rendu du formulaire/template/admin, l’objet est traduit avec la langue active.
Résumé en une phrase : Dans les endroits où la langue est déterminée au moment du rendu, le lazy est la solution.
Où utiliser quoi : règles pratiques
1) Vous créez immédiatement une réponse ou un message → gettext
from django.utils.translation import gettext as _
def signup_done(request):
return JsonResponse({"message": _("Signup completed.")})
2) Vous définissez des attributs de classe, des métadonnées ou des champs de formulaire qui seront évalués lors de l’importation → gettext_lazy
verbose_name,help_textde modèleslabel,help_textde champs de formulairelabelde sérialiseur DRFlist_displayd’admin
from django.db import models
from django.utils.translation import gettext_lazy as _
class Article(models.Model):
title = models.CharField(_("title"), max_length=100)
status = models.CharField(
_("status"),
max_length=20,
choices=[
("draft", _("Draft")),
("published", _("Published")),
],
help_text=_("Visibility of the article."),
)
3) Vous avez des constantes ou des choix réutilisables au niveau du module → généralement gettext_lazy
from django.utils.translation import gettext_lazy as _
STATUS_CHOICES = [
("draft", _("Draft")),
("published", _("Published")),
]
4) Vous envoyez une chaîne vers un système externe (logs, API tierce, en-têtes) → gettext ou forcez l’évaluation du lazy
from django.utils.translation import gettext_lazy as _
from django.utils.encoding import force_str
msg = _("Welcome")
logger.info(force_str(msg)) # ✅ convertit en chaîne réelle
5) Vous combinez ou formatez des chaînes → utilisez format_lazy ou la substitution interne
from django.utils.translation import gettext_lazy as _
from django.utils.text import format_lazy
title = format_lazy("{}: {}", _("Error"), _("Invalid token"))
ou
from django.utils.translation import gettext as _
message = _("Hello, %(name)s!") % {"name": user.username}
Trois erreurs fréquentes
Erreur 1 : créer une traduction figée au moment de l’importation avec gettext()
- Si vous avez des constantes ou des choix, privilégiez le lazy.
Erreur 2 : insérer un objet lazy directement dans JSON ou les logs
- Utilisez
force_str()pour obtenir une chaîne.
Erreur 3 : assembler des chaînes traduites avec f‑string {#sec-76316b53a754}
# ❌ non recommandé
_("Hello") + f" {user.username}"
- La traduction se fait en morceaux et l’ordre peut changer selon la langue.
- Utilisez la substitution interne :
# ✅ recommandé
_("Hello, %(name)s!") % {"name": user.username}
Astuces pour réduire la confusion
Uniformisez l’usage de _ selon le type de fichier :
models.py,forms.py,admin.py:from django.utils.translation import gettext_lazy as _views.py,services.py:from django.utils.translation import gettext as _
Cette convention crée un point de référence qui diminue les erreurs.
Résumé rapide
- Évaluation immédiate (runtime) :
gettext - Évaluation paresseuse (définition/metadata/constantes) :
gettext_lazy - Chaînes sortantes : utilisez
force_strsi nécessaire - Lazy + formatage :
format_lazyou substitution interne
Avec ces règles, vous choisissez automatiquement la bonne fonction sans confusion.
Liens connexes - Problèmes et solutions lors de l'utilisation de gettext_lazy comme clé JSON
Aucun commentaire.