Situatieoverzicht
Bij het ontwikkelen van Django komen we vaak situaties tegen waarin we gettext_lazy
gebruiken voor meertalige ondersteuning.
Echter, soms kan gettext_lazy
een fout veroorzaken bij het maken van een JSON-respons.
In dit artikel zal ik uitgelegd worden waarom gettext_lazy
problemen veroorzaakt bij JSON-serialisatie en hoe dit kan worden opgelost.
Normale werking vs. fout: situatievergelijking
Geval | Normaal functionerend geval | Foutgevend geval |
---|---|---|
LANGUAGE_MAP.get(...) returnwaarde locatie |
Waarde van het woordenboek | Sleutel van het woordenboek |
Serialisatie mogelijkheid | Mogelijk (geen probleem) | Onmogelijk (__proxy__ sleutel kan niet naar JSON worden omgezet) |
De kern van het probleem: waarom is deze afwijking ontstaan?
Het object dat door gettext_lazy
wordt geretourneerd, is van het type __proxy__
. Dit object lijkt op een string, maar is eigenlijk geen echte string.
Django's JsonResponse
of Python's json.dumps()
volgen de volgende regels:
# ✅ Oké: je kunt lazy-objecten gebruiken voor waardes (automatische str-conversie)
json.dumps({'language': _('English')})
# ❌ Fout: je kunt geen lazy-objecten gebruiken voor sleutels
json.dumps({_('English'): 'language'})
Met andere woorden, de sleutel van een woordenboek moet altijd een echte string zijn.
__proxy__
objecten worden niet automatisch omgezet wanneer ze als sleutel worden gebruikt, wat de fout veroorzaakt.
Waarom zijn er geen problemen met waardes, maar wel met sleutels?
De gettext_lazy
objecten zijn geen probleem wanneer ze als waarde in een woordenboek worden gebruikt. Dit komt omdat Django of Python de waarde automatisch naar een string omzet tijdens het JSON-serialisatieproces.
Echter, als ze als sleutel worden gebruikt, vereist de JSON-standaard dat sleutels strengen zijn. In dat geval wordt het gettext_lazy
object niet automatisch omgezet, wat resulteert in een serialisatiefout.
Conclusie:
- Bij gebruik als waarde vindt er intern een str-conversie plaats, wat zonder problemen doorgaat.
- Als sleutel vindt er echter geen automatische conversie plaats, wat tot fouten leidt.
Oplossingsmethoden
Methode 1: Overstappen op gettext
(Geen lazy gebruiken)
Dit is de meest zekere methode. Gebruik onmiddellijk de waarden die naar strings zijn omgezet zonder lazy.
from django.utils.translation import gettext as _ # geen lazy!
LANGUAGE_MAP = {
"en": _("English"),
"ko": _("Koreaans"),
"ja": _("Japans"),
}
- Voordeel: geen extra verwerking nodig
- Nadeel: de vertaling wordt beslist bij het eerste importmoment, wat mogelijk niet overeenkomt met bepaalde dynamische vertaalvereisten
Methode 2: Forceer str() net voor JSON-serialisatie
Als je lazy-objecten wilt blijven gebruiken, zet dan de sleutel om in een string met str()
voordat je deze in JSON gaat zetten.
lang = str(LANGUAGE_MAP.get(lang_code, lang_code.upper()))
- Voordeel: je hoeft de bestaande code bijna niet aan te passen
- Nadeel: je moet telkens op de str-conversie letten
Bonus: Vertaling aan de clientzijde verwerken
Er is ook een mogelijkheid om meertalige vertalingen helemaal niet op de server te verwerken en deze oplossingen aan de frontend over te laten.
- De server stuurt alleen de taalkode
- De client-side javascript beheert de vertalingen.
Deze methode kan gekozen worden, afhankelijk van het project.
Samenvattend
- Gebruik
gettext_lazy
absoluut niet als woordenboeksleutel. - Zorg ervoor dat je altijd de string omzet voor JSON-serialisatie.
- De veiligste methode is om direct naar strings om te zetten met
gettext
. - Vergeet niet om
str(...)
te gebruiken als je de bestaande code wilt behouden.
Jesse's opmerking
Dit probleem is een veelvoorkomende fout die voorkomt in het delicate evenwicht van meertalige verwerking en JSON-reactieverwerking in Django.
In de toekomst, beschouw het als "het werkte eerder, waarom nu niet?" meer als "het was eerder geluk" en controleer je code.
Het moment waarop de vaardigheid van de ontwikkelaar toeneemt, is wanneer men deze 'delicate' nuances begrijpt. Wanneer je dit principe begrijpt, kun je zowel de meertalige verwerkingen in Django als de JSON-reacties veel robuuster maken!
댓글이 없습니다.