Szenario Übersicht

Infografik über die Probleme von gettext_lazy und JSON-Schlüsseln

Bei der Entwicklung mit Django kommt es häufig vor, dass gettext_lazy genutzt wird, um mehrsprachige Unterstützung zu gewährleisten. Allerdings kann es vorkommen, dass gettext_lazy plötzlich beim Erstellen von JSON-Antworten Fehler verursacht.

In diesem Artikel wird ausführlich erklärt, wieso gettext_lazy Probleme bei der JSON-Serialisierung verursacht und wie man sie lösen kann.

Funktioniert normal vs. Fehler aufgetreten: Szenario Vergleich

Fall Wenn es normal funktioniert Wenn ein Fehler aufgetreten ist
LANGUAGE_MAP.get(...) Rückgabeposition Wert des Dictionaries Schlüssel des Dictionaries
Serialisierbarkeit Ja (kein Problem) Nein (__proxy__ Schlüssel ist nicht in JSON umwandelbar)

Kern des Problems: Warum gibt es diesen Unterschied?

Das Objekt, das gettext_lazy zurückgibt, ist vom Typ __proxy__. Dieses Objekt sieht aus wie ein String, ist aber tatsächlich kein echter String.

Djangos JsonResponse oder Pythons json.dumps() folgt diesen Regeln:

# ✅ Möglich: Lazy-Objekte können als Wert verwendet werden (automatische str-Umwandlung)
json.dumps({'language': _('English')})

# ❌ Fehlgeschlagen: Lazy-Objekte können nicht als Schlüssel verwendet werden
json.dumps({_('English'): 'language'})

Das bedeutet, dass um als Schlüssel im Dictionary verwendet zu werden, es unbedingt ein echter String sein muss. Das __proxy__ Objekt wird beim Gebrauch als Schlüssel nicht automatisch umgewandelt, was zu einem Fehler führt.

Warum gibt es mit dem Wert kein Problem, aber mit dem Schlüssel?

Das gettext_lazy Objekt verursacht beim Einsatz als Wert des Dictionaries keine Schwierigkeiten, weil Django oder Python bei der JSON-Serialisierung den Wert automatisch in einen String umwandelt.

Als Schlüssel muss jedoch die JSON-Norm besagen, dass der Schlüssel unbedingt ein String sein muss. In diesem Fall wird das gettext_lazy Objekt nicht automatisch umgewandelt und verursacht einen Serialisierungsfehler.

Fazit:

  • Bei der Verwendung als Wert erfolgt intern eine str-Umwandlung, was problemlos funktioniert.
  • Bei der Verwendung als Schlüssel findet die Umwandlung nicht automatisch statt, sodass ein Fehler auftritt.

Lösungsmöglichkeiten

Methode 1: Wechsel zu gettext (Nicht lazy)

Das ist der sicherste Ansatz. Verwenden Sie den sofort in einen String umgewandelten Wert, ohne lazy.

from django.utils.translation import gettext as _  # nicht lazy!

LANGUAGE_MAP = {
    "en": _("English"),
    "ko": _("Koreanisch"),
    "ja": _("Japanisch"),
}
  • Vorteil: Keine zusätzlichen Bearbeitungen erforderlich
  • Nachteil: Da die Übersetzung beim ersten Importzeitpunkt festgelegt wird, kann dies nicht mit einigen dynamischen Übersetzungsanforderungen übereinstimmen.

Methode 2: Zwangsweise str() kurz vor der JSON-Serialisierung anwenden

Wenn Sie weiterhin das lazy-Objekt verwenden möchten, wandeln Sie den Schlüssel vor dem Hinzufügen zu JSON mit str() um.

lang = str(LANGUAGE_MAP.get(lang_code, lang_code.upper()))
  • Vorteil: Bestehender Code muss kaum geändert werden
  • Nachteil: Man muss ständig an die str-Umwandlung denken.

Zusatz: Übersetzungsbearbeitung auf der Client-Seite

Es gibt auch die Möglichkeit, ganz auf mehrsprachige Verarbeitung auf dem Server zu verzichten und diese im Frontend zu bearbeiten.

  • Der Server sendet nur den Sprachcode
  • Client-JavaScript verwaltet die Übersetzungstabelle.

Diese Methode kann je nach Projekt gewählt werden.

Zusammenfassend

  • gettext_lazy sollte niemals als Dictionary-Schlüssel verwendet werden.
  • Vor der JSON-Serialisierung sollten Sie unbedingt in einen String umwandeln.
  • Die sicherste Methode ist die sofortige Umwandlung in einen String mit gettext.
  • Wenn der bestehende Code beibehalten werden muss, vergessen Sie nicht str(...) zu verwenden.

Jesses Kommentar

Dieses Problem tritt an der sehr feinen Grenze zwischen mehrsprachiger Verarbeitung in Django und der Behandlung von JSON-Antworten auf.

Denken Sie in Zukunft nicht: "Früher hat es funktioniert, warum jetzt nicht?", sondern betrachten Sie es als: "Früher hatten Sie Glück" und überprüfen Sie Ihren Code.

Der Moment, in dem die Fähigkeiten eines Entwicklers wachsen, ist genau dann, wenn man solche 'Feinheiten' versteht. Wenn Sie dieses Prinzip verstehen, können Sie sowohl die mehrsprachige Verarbeitung in Django als auch die JSON-Antworten viel robuster gestalten!