Django: gettext vs gettext_lazy – Klarheit durch das Timing der Auswertung
Wenn man Django i18n nutzt, schwankt man ständig, ob man gettext() oder gettext_lazy() einsetzen soll. Der wahre Grund für die Verwirrung liegt darin, dass man die Unterschiede als reine Terminologie auswendig lernen will.
Das Wesentliche ist ein einziges Prinzip.
gettextübersetzt sofort (eager)gettext_lazyübersetzt erst später (lazy)
Dieses Timing‑Prinzip fasst fast alle Anwendungsfälle zusammen.
Warum ist das Timing der Übersetzung wichtig?
In Django ändert sich die Sprache üblicherweise bei jeder Anfrage.

- Middleware erkennt die Anfrage und ruft
activate("ko")/activate("en")auf, um die aktuelle Sprache für den Thread/Context zu aktivieren. - Beim Rendern von Templates, Forms oder im Admin muss die Übersetzung bereits in dieser Sprache erfolgen.
Kurz gesagt: Wann man einen String übersetzt, bestimmt das Ergebnis.
gettext() : „Jetzt“ übersetzen und den String zurückgeben
from django.utils.translation import gettext as _
def view(request):
message = _("Welcome") # wird zur Laufzeit in der aktiven Sprache übersetzt
return HttpResponse(message)
- Wird innerhalb einer View oder eines Funktionsaufrufs (runtime) aufgerufen, funktioniert es wie erwartet.
- Wird jedoch beim Importieren eines Moduls ausgeführt, kann es zu Problemen kommen.
Häufiges Problem: gettext() in Modulkonstanten
# app/constants.py
from django.utils.translation import gettext as _
WELCOME = _("Welcome") # ❌ wird beim Serverstart/Import in der aktuellen Sprache festgelegt
In diesem Fall bleibt WELCOME ein fester, bereits übersetzter String, selbst wenn die Sprache später wechselt (besonders in Umgebungen, in denen das Modul nur einmal importiert wird).
gettext_lazy() : „Später“ übersetzbare Proxy‑Objekte zurückgeben
from django.utils.translation import gettext_lazy as _
WELCOME = _("Welcome") # ✅ kein echter String, sondern ein Objekt, das bei Bedarf übersetzt wird
gettext_lazy() liefert in der Regel ein lazy object.
- Beim Rendern von Forms, Templates oder Admin wird es in den aktiven String übersetzt.
Kurz gesagt: In Bereichen, in denen die Sprache erst beim Rendern feststeht, ist lazy die richtige Wahl.
Praktische Regeln für die Verwendung
1) „Jetzt“ eine Antwort oder Log erzeugen → gettext
from django.utils.translation import gettext as _
def signup_done(request):
return JsonResponse({"message": _("Signup completed.")})
2) „Definition vor Rendern“ (z. B. Klassenattribute, Meta‑Daten, Form‑Labels) → gettext_lazy
verbose_name,help_textin Modellenlabel,help_textin Formslabelin DRF‑Serializerslist_display‑Beschreibungen im 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) Wiederverwendbare Konstanten/Choices → meist gettext_lazy
from django.utils.translation import gettext_lazy as _
STATUS_CHOICES = [
("draft", _("Draft")),
("published", _("Published")),
]
4) Strings an externe Systeme senden (Logs, APIs, Header) → gettext oder explizite Auswertung
from django.utils.translation import gettext_lazy as _
from django.utils.encoding import force_str
msg = _("Welcome")
logger.info(force_str(msg)) # ✅ wird in einen echten String umgewandelt
5) String‑Konkatenation/Formatierung → format_lazy oder Platzhalter in der Übersetzung
from django.utils.translation import gettext_lazy as _
from django.utils.text import format_lazy
title = format_lazy("{}: {}", _("Error"), _("Invalid token"))
oder mit %‑Formatierung:
from django.utils.translation import gettext as _
message = _("Hello, %(name)s!") % {"name": user.username}
Häufigste Fehler (3)
Fehler 1: gettext() beim Import festlegt
- Bei Konstanten/Choices sollte lazy in Betracht gezogen werden.
Fehler 2: Lazy‑Objekte direkt in JSON oder Logs verwenden
- Verwenden Sie
force_str().
Fehler 3: f‑Strings mit Übersetzungen mischen
# ❌ nicht empfohlen
_("Hello") + f" {user.username}"
- Die Reihenfolge der Wörter kann je nach Sprache variieren.
- Stattdessen:
# ✅ empfohlen
_("Hello, %(name)s!") % {"name": user.username}
Tipps zur Vermeidung von Verwirrung
Eine klare Trennung nach Dateityp hilft enorm:
- In
models.py,forms.py,admin.py(Definition zuerst):from django.utils.translation import gettext_lazy as _ - In
views.py,services.py(Ausführung zuerst):from django.utils.translation import gettext as _
So entsteht ein konsistentes Muster, das Fehler reduziert.
Kurzfassung
- Runtime‑Logik →
gettext - Definition/Meta/Choices/Labels →
gettext_lazy - Ausgehende Strings → ggf.
force_str - Lazy + Formatierung →
format_lazyoder Platzhalter in der Übersetzung
Mit diesen Regeln wird die Wahl fast automatisch.
Verwandte Artikel - Probleme und Lösungen bei der Verwendung von gettext_lazy mit JSON-Schlüsseln
Es sind keine Kommentare vorhanden.