## 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." Pythons `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.