## Quand `gettext_lazy` de Django devient un casse-tête en tant que clé JSON {#sec-66ae94ff1145} > Pour résumer en une phrase : **Une clé JSON doit impérativement être une 'vraie' chaîne de caractères**, or, `gettext_lazy` de Django ne renvoie pas une chaîne, mais un objet `__proxy__`. ## 1. Pourquoi mon code, qui fonctionnait parfaitement, s'est-il soudainement mis à planter ? {#sec-4a4b34e6a73c} En développement Django, l'utilisation de `gettext_lazy` pour la gestion du multilinguisme est monnaie courante. On l'utilise sans problème jusqu'au jour où, soudainement, une erreur de sérialisation survient lors d'une réponse JSON (`JsonResponse`). Généralement, les logs d'erreur affichent des messages énigmatiques comme `__proxy__`, ce qui est déroutant. Pourtant, en y regardant de plus près, la cause est étonnamment simple. ![Infographie sur le problème de gettext_lazy et des clés JSON](/media/whitedec/blog_img/gettext_lazy_json_error.webp) ## 2. Le coupable ? La "clé" elle-même. {#sec-361c46af305d} Pour faire court, un objet `gettext_lazy` passe inaperçu lorsqu'il est utilisé comme **valeur** dans un dictionnaire, mais pose problème dès qu'il est employé comme **clé**. | Distinction | Utilisation en tant que valeur | Utilisation en tant que clé | | :--- | :--- | :--- | | **Fonctionnement** | Normal (conversion automatique en str) | **Erreur** | | **Raison** | Conversion de type automatique supportée lors de la sérialisation JSON | Une clé JSON doit impérativement être une 'vraie' chaîne de caractères | ## 3. Pourquoi une telle différence ? {#sec-80787b3802c2} Ce que `gettext_lazy` retourne n'est pas une vraie chaîne de caractères, mais un objet `__proxy__`. Comme son nom l'indique, c'est une promesse : « je te donnerai la traduction quand tu en auras besoin ». Les fonctions `json.dumps()` de Python ou `JsonResponse` de Django parcourent les valeurs d'un dictionnaire et transforment automatiquement cette 'promesse' en chaîne de caractères (évaluation). Mais pour les **clés d'un dictionnaire**, c'est une autre histoire. Selon la norme JSON, une clé doit impérativement être une chaîne de caractères. Dans ce contexte, l'objet `__proxy__` n'est pas automatiquement converti et provoque une erreur. ```python # ✅ Pas de problème : la valeur est automatiquement convertie en str. json.dumps({'language': _('Korean')}) # ❌ Erreur : la clé n'est pas convertie et est rejetée. json.dumps({_('Korean'): 'language'}) ``` ## 4. Comment résoudre ce problème ? {#sec-87b95d49caed} ### Méthode 1 : Utiliser simplement `gettext` (la solution la plus simple) {#sec-d736d0465485} Si une approche "lazy" n'est pas strictement nécessaire, la solution la plus simple est d'utiliser `gettext`, qui renvoie une chaîne de caractères immédiatement lors de l'appel. ```python from django.utils.translation import gettext as _ LANGUAGE_MAP = { "en": _("English"), "ko": _("Korean"), } ``` * **Note :** Gardez à l'esprit que cette méthode détermine la traduction au moment du chargement de l'application. Soyez vigilant si un environnement de traduction dynamique est crucial. ### Méthode 2 : Forcer la conversion avec `str()` juste avant la sérialisation {#sec-fc5762a0f995} Si vous utilisez déjà des objets "lazy" de manière extensive, forcez leur conversion en chaîne de caractères juste avant de les passer au format [[JSON]]. ```python # Enveloppez la clé avec str() avant de l'utiliser comme clé pour en faire une 'vraie chaîne de caractères'. lang_key = str(LANGUAGE_MAP.get(code)) ``` ### Méthode 3 : Déléguer la traduction au client {#sec-f61be7ca95b2} Si vous utilisez un client frontal distinct sans les templates de Django (ce qui semble être la tendance actuelle), le serveur [[Django]] (ou [[DRF]]) ne renvoie que des codes comme `en` ou `ko`. La traduction et l'affichage du texte à l'écran sont alors gérés par une bibliothèque i18n côté frontend (React, Vue, etc.). Cela a l'avantage d'alléger la logique du serveur. --- ## En guise de conclusion {#sec-0d2251a657d4} Si, en utilisant `json.dumps()` et `gettext_lazy()`, vous vous êtes retrouvé dans une situation où « ça marchait hier, mais plus aujourd'hui », il est fort probable qu'hier vous ayez eu la chance de l'utiliser uniquement comme valeur, et aujourd'hui comme clé. `gettext_lazy` est pratique, mais il faut toujours garder à l'esprit qu'il ne s'agit pas d'une 'vraie chaîne de caractères'. C'est particulièrement vrai lorsque vous manipulez du [[JSON]]. J'espère que cet article sera utile à ceux qui rencontrent des problèmes similaires.