## Frustrerende situaties bij het gebruik van `gettext_lazy` als JSON-sleutel in Django {#sec-66ae94ff1145} > Samenvatting in één zin: Een **JSON-sleutel moet altijd een 'echte' string zijn**, maar `gettext_lazy` van Django retourneert eigenlijk geen string, maar een `__proxy__` object. ## 1. Waarom werkt code die altijd goed werkte ineens niet meer? {#sec-4a4b34e6a73c} Tijdens de ontwikkeling met Django is het gebruik van `gettext_lazy` voor meertalige ondersteuning dagelijkse kost. Maar soms, terwijl je het normaal gebruikt, kan er plotseling een serialisatiefout optreden tijdens het JSON-antwoordproces (JsonResponse). Meestal zie je dan vage foutmeldingen zoals `__proxy__` iets, wat verwarrend kan zijn. Maar als je de oorzaak nader bekijkt, zit de boosdoener op een verrassend eenvoudige plek. ![infographic over gettext_lazy en JSON-sleutelprobleem](/media/whitedec/blog_img/gettext_lazy_json_error.webp) ## 2. De boosdoener zat in de "Sleutel" {#sec-361c46af305d} Om meteen met de deur in huis te vallen: een `gettext_lazy`-object wordt stilzwijgend geaccepteerd als **waarde** in een dictionary, maar zodra het als **sleutel** wordt gebruikt, veroorzaakt het problemen. | Categorie | Gebruik als waarde | Gebruik als sleutel | | :--- | :--- | :--- | | **Werking** | Normaal (automatische `str`-conversie) | **Foutmelding** | | **Reden** | Automatische typeconversie wordt ondersteund bij JSON-serialisatie | Een JSON-sleutel moet altijd een 'echte' string zijn | ## 3. Waarom dit verschil? {#sec-80785a3802c2} Wat `gettext_lazy` retourneert, is geen echte string, maar een `__proxy__`-object. Zoals de naam al zegt, is het een belofte: "Ik geef je de vertaling wanneer die nodig is." `json.dumps()` van Python of `JsonResponse` van Django doorloopt de waarden van een dictionary en lost deze 'belofte' automatisch op naar een string (evaluatie). Maar voor een **sleutel van een dictionary** ligt het anders. Volgens de JSON-standaard moet een sleutel altijd een string zijn. In dit proces wordt het `__proxy__`-object niet automatisch geconverteerd en botst het direct, wat resulteert in een foutmelding. ```python # ✅ Geen probleem: de waarde wordt automatisch naar str geconverteerd. json.dumps({'language': _('Korean')}) # ❌ Foutmelding: de sleutel kan niet zelfstandig worden geconverteerd en wordt geweigerd. json.dumps({_('Korean'): 'language'}) ``` ## 4. Hoe lossen we dit op? {#sec-87b95d49caed} ### Methode 1: Gebruik gewoon `gettext` (het meest elegant) {#sec-d736d0465485} Als de 'lazy'-methode niet strikt noodzakelijk is, is het het meest praktisch om `gettext` te gebruiken, dat direct een string retourneert bij aanroep. ```python from django.utils.translation import gettext as _ LANGUAGE_MAP = { "en": _("English"), "ko": _("Korean"), } ``` * **Opmerking:** Houd er rekening mee dat bij deze methode de vertaling wordt bepaald op het moment dat de app wordt geladen, dus voorzichtigheid is geboden als een dynamische vertaalomgeving belangrijk is. ### Methode 2: Voeg `str()` toe vlak voor serialisatie {#sec-fc5762a0f995} Als je al uitgebreid gebruikmaakt van 'lazy'-objecten, kun je een geforceerde stringconversie uitvoeren vlak voordat je ze doorgeeft aan JSON. ```python # Wikkel de sleutel in str() voordat je deze als sleutel gebruikt om er een 'echte string' van te maken. lang_key = str(LANGUAGE_MAP.get(code)) ``` ### Methode 3: Delegeer de vertaling naar de client {#sec-f61be7ca95b2} Als je geen Django-templates gebruikt voor de frontend, maar een aparte frontend-client (wat tegenwoordig misschien wel de trend is), dan kan de Django (of DRF) server alleen codes zoals `en` en `ko` doorgeven. De feitelijke tekst die op het scherm wordt weergegeven, wordt dan afgehandeld door de i18n-bibliotheek van de frontend (zoals React, Vue, etc.). Dit heeft als voordeel dat de serverlogica lichter wordt. --- ## Conclusie {#sec-0d2251a657d4} Als je tijdens het gebruik van `json.dumps()` in combinatie met `gettext_lazy()` de situatie tegenkomt van "gisteren werkte het wel, waarom vandaag niet meer?", dan is de kans groot dat je het gisteren gelukkig alleen als waarde gebruikte, en vandaag als sleutel. `gettext_lazy` is handig, maar je moet er altijd rekening mee houden dat het uiteindelijk geen 'echte string' is. Vooral bij het omgaan met JSON is dit cruciaal. Ik hoop dat dit artikel nuttig is voor iedereen die met vergelijkbare fouten worstelt.