## Una situación frustrante al usar `gettext_lazy` de Django como clave JSON {#sec-66ae94ff1145} > En resumen: **una clave JSON debe ser una cadena de texto 'real'**, pero `gettext_lazy` de Django no devuelve una cadena, sino un objeto `__proxy__`. ## 1. ¿Por qué un código que funcionaba bien de repente falla? {#sec-4a4b34e6a73c} Durante el desarrollo con Django, usar `gettext_lazy` para el manejo de la internacionalización (i18n o multilingüe) es algo común. Sin embargo, puede ocurrir que, mientras lo usas sin problemas, de repente salte un error de serialización (Serialization) durante el proceso de respuesta JSON (JsonResponse). Normalmente, el registro de errores solo muestra mensajes confusos como `__proxy__` o similar, lo que suele generar frustración. Pero si analizamos la causa, encontraremos que el culpable está en un lugar sorprendentemente simple. ![Infografía sobre el problema de gettext_lazy y las claves JSON](/media/whitedec/blog_img/gettext_lazy_json_error.webp) ## 2. El culpable estaba en la "clave" {#sec-361c46af305d} Para ir directo al grano, el objeto `gettext_lazy` se comporta bien cuando se usa como **Value** en un diccionario, pero causa problemas en el momento en que se utiliza como **Key**. | Categoría | Al usar como Value | Al usar como Key | | :--- | :--- | :--- | | **Funcionamiento** | Normal (conversión automática a `str`) | **Error** | | **Razón** | La serialización JSON soporta la conversión automática de tipos | La clave JSON debe ser una cadena de texto 'real' | ## 3. ¿Por qué esta diferencia? {#sec-80787a3802c2} Lo que devuelve `gettext_lazy` no es una cadena de texto (String) real, sino un objeto llamado `__proxy__`. Como su nombre indica, es un objeto que 'promete' proporcionar la traducción cuando sea necesaria en el futuro. Funciones como `json.dumps()` de Python o `JsonResponse` de Django recorren los valores del diccionario y 'despliegan' (evalúan) automáticamente esta 'promesa' en una cadena de texto. Sin embargo, la situación es diferente para las **claves de un diccionario**. Según el estándar [[JSON]], las claves deben ser obligatoriamente cadenas de texto, y en este proceso, el objeto `__proxy__` no se convierte automáticamente, lo que provoca el error. ```python # ✅ Sin problema: el valor se convierte automáticamente a str. json.dumps({'language': _('Korean')}) # ❌ Error: la clave no se convierte automáticamente y es rechazada. json.dumps({_('Korean'): 'language'}) ``` ## 4. ¿Cómo solucionarlo? {#sec-87b95d49caed} ### Opción 1: Usar `gettext` directamente (la más limpia) {#sec-d736d0465485} Si el enfoque *lazy* no es estrictamente necesario, la forma más sencilla es usar `gettext`, que devuelve la cadena de texto inmediatamente al ser invocada. ```python from django.utils.translation import gettext as _ LANGUAGE_MAP = { "en": _("English"), "ko": _("Korean"), } ``` * **Nota:** Sin embargo, con este método, la traducción se determina en el momento en que se carga la aplicación, por lo que se debe tener precaución si un entorno de traducción dinámico es crucial. ### Opción 2: Insertar `str()` justo antes de la serialización {#sec-fc5762a0f995} Si ya estás utilizando objetos *lazy* de forma extensiva, puedes forzar la conversión a cadena de texto justo antes de pasarlos a JSON. ```python # Antes de usarlo como clave, envuélvelo con str() para convertirlo en una 'cadena de texto real'. lang_key = str(LANGUAGE_MAP.get(code)) ``` ### Opción 3: Delegar la traducción al cliente {#sec-f61be7ca95b2} Si no utilizas las plantillas de Django para el *frontend* y, en su lugar, empleas un cliente *frontend* independiente (quizás esta sea la tendencia actual), el servidor Django (o [[DRF]]) solo enviaría códigos como `en` o `ko`. El texto real que se muestra en pantalla sería gestionado por las librerías de i18n del *frontend* (React, Vue, etc.). Esto tiene la ventaja de aligerar la lógica del servidor. --- ## Conclusión {#sec-0d2251a657d4} Si alguna vez te encuentras usando `json.dumps()` junto con `gettext_lazy()` y piensas: "¿Por qué funcionaba ayer y hoy no?", es muy probable que ayer lo hayas usado por suerte solo como *Value* y hoy como *Key*. `gettext_lazy` es una herramienta útil, pero siempre debemos recordar que no es una 'cadena de texto real'. Esto es especialmente crucial al trabajar con [[JSON]]. Espero que este artículo sea de ayuda para quienes estén lidiando con errores similares.