## Wenn `gettext_lazy` in Django als JSON-Schlüssel Kopfschmerzen bereitet {#sec-66ae94ff1145} > Zusammenfassend lässt sich sagen: Ein **JSON-Schlüssel muss ein 'echter' String sein**, doch Django's `gettext_lazy` gibt tatsächlich kein String, sondern ein `__proxy__`-Objekt zurück. ## 1. Warum plötzlich Probleme mit funktionierendem Code? {#sec-4a4b34e6a73c} Bei der Django-Entwicklung ist die Verwendung von [[gettext_lazy]] für die Mehrsprachigkeit Routine. Doch manchmal tritt plötzlich ein [[Serialisierungsfehler]] auf, wenn man eine [[JSON-Antwort]] (JsonResponse) erstellt, obwohl es zuvor immer reibungslos funktionierte. Meistens verwirren die Fehlermeldungen im Log, die nur kryptische "__proxy__"-Hinweise enthalten. Doch bei genauerer Betrachtung liegt die Ursache oft an einer überraschend einfachen Stelle. ![Infografik zum Problem mit gettext_lazy und JSON-Schlüsseln](/media/whitedec/blog_img/gettext_lazy_json_error.webp) ## 2. Der Übeltäter: Der "Key" {#sec-361c46af305d} Um es auf den Punkt zu bringen: Ein [[gettext_lazy]]-Objekt wird als **Value** in einem Dictionary problemlos akzeptiert, verursacht aber sofort Probleme, sobald es als **Key** verwendet wird. | Eigenschaft | Bei Verwendung als Value | Bei Verwendung als Key | | :--- | :--- | :--- | | **Funktionsweise** | Normal (automatische String-Konvertierung) | **Fehler tritt auf** | | **Grund** | Automatische Typumwandlung bei JSON-Serialisierung unterstützt | JSON-Schlüssel muss ein 'echter' String sein | ## 3. Warum gibt es diesen Unterschied? {#sec-80787e3802c2} Was [[gettext_lazy]] zurückgibt, ist kein echter String, sondern ein `__proxy__`-Objekt. Es ist, wie der Name schon sagt, ein Platzhalter, der verspricht: "Ich liefere die Übersetzung, wenn sie tatsächlich benötigt wird." [[Python]]s `json.dumps()` oder [[Django]]s `JsonResponse` durchlaufen die Werte eines Dictionaries und lösen dieses "Versprechen" (Evaluation) automatisch in einen String auf. Beim **Schlüssel eines Dictionaries** sieht die Sache jedoch anders aus. Laut [[JSON-Standard]] muss ein Schlüssel immer ein String sein. Da das `__proxy__`-Objekt in diesem Prozess nicht automatisch konvertiert wird und direkt auf diese Anforderung trifft, kommt es zu einem Fehler. ```python # ✅ Kein Problem: Der Value wird automatisch in einen String umgewandelt. json.dumps({'language': _('Korean')}) # ❌ Fehler: Der Key kann nicht selbst konvertiert werden und wird abgelehnt. json.dumps({_('Korean'): 'language'}) ``` ## 4. Wie lässt sich das Problem lösen? {#sec-87b95d49caed} ### Methode 1: Einfach `gettext` verwenden (Die sauberste Lösung) {#sec-d736d0465485} Wenn der Lazy-Ansatz nicht zwingend erforderlich ist, ist es am unkompliziertesten, [[gettext]] zu verwenden, das sofort einen String zurückgibt. ```python from django.utils.translation import gettext as _ LANGUAGE_MAP = { "en": _("English"), "ko": _("Korean"), } ``` * **Hinweis:** Bei dieser Methode wird die Übersetzung jedoch zum Zeitpunkt des App-Ladevorgangs festgelegt. Ist eine dynamische Übersetzungsumgebung wichtig, ist Vorsicht geboten. ### Methode 2: `str()` direkt vor der Serialisierung einfügen {#sec-fc5762a0f995} Wenn Sie [[Lazy-Objekte]] bereits weit verbreitet verwenden, wandeln Sie diese direkt vor der Übergabe an [[JSON]] erzwungenermaßen in Strings um. ```python # Vor der Verwendung als Key mit str() umschließen, um einen 'echten String' zu erhalten. lang_key = str(LANGUAGE_MAP.get(code)) ``` ### Methode 3: Die Übersetzungsverantwortung an den Client übertragen {#sec-f61be7ca95b2} Wenn Sie das Frontend nicht mit [[Django]]-Templates, sondern mit einem separaten Frontend-Client entwickeln (was heutzutage vielleicht ein Trend ist), kann der [[Django]]- (oder [[DRF]]-)Server lediglich Codes wie "en" oder "ko" übermitteln. Die eigentliche Textanzeige auf dem Bildschirm würde dann von einer [[i18n]]-Bibliothek im Frontend (z.B. [[React]], [[Vue]]) übernommen. Dies hat den Vorteil, dass die Serverlogik schlanker wird. --- ## Fazit {#sec-0d2251a657d4} Wenn Sie bei der Verwendung von `json.dumps()` zusammen mit [[gettext_lazy]] auf die Situation stoßen: "Gestern ging es noch, warum heute nicht mehr?", liegt es wahrscheinlich daran, dass Sie es gestern glücklicherweise nur für Values verwendet haben, während Sie es heute als Key eingesetzt haben. [[gettext_lazy]] ist zwar praktisch, doch man sollte immer bedenken, dass es letztendlich kein "echter String" ist. Dies gilt insbesondere beim Umgang mit [[JSON]]. Ich hoffe, dieser Artikel hilft all jenen, die sich mit ähnlichen Fehlern herumschlagen.