Aperçu de la situation
En développant avec Django, il est fréquent d'utiliser gettext_lazy
pour prendre en charge plusieurs langues.
Cependant, il arrive que gettext_lazy
, qui fonctionne habituellement bien, génère des erreurs lors de la création d'une réponse JSON.
Dans cet article, nous allons expliquer pourquoi gettext_lazy
pose problème lors de la sérialisation JSON et comment le résoudre.
Fonctionnement normal vs erreur : comparaison des situations
Cas | Fonctionnement normal | Cas d'erreur |
---|---|---|
Position de la valeur renvoyée par LANGUAGE_MAP.get(...) |
Valeur du dictionnaire | Clé du dictionnaire |
Capacité de sérialisation | possible (aucun problème) | impossible (__proxy__ ne peut pas être converti en JSON) |
L'essence du problème : pourquoi cette différence existe-t-elle ?
Les objets renvoyés par gettext_lazy
sont de type __proxy__
. Ces objets ont l'apparence de chaînes, mais ne sont en réalité pas des vraies chaînes.
Les JsonResponse
de Django et json.dumps()
de Python suivent cette règle :
# ✅ possible : on peut utiliser des objets paresseux comme valeur (conversion str automatique)
json.dumps({'language': _('English')})
# ❌ échec : on ne peut pas utiliser d'objets paresseux comme clé
json.dumps({_('English'): 'language'})
En d'autres termes, pour être utilisés comme clés, ils doivent être de vraies chaînes.
Un objet __proxy__
ne se convertit pas automatiquement lorsqu'il est utilisé comme clé, ce qui entraîne une erreur.
Pourquoi n'y a-t-il pas de problème avec les valeurs mais des problèmes avec les clés ?
Les objets gettext_lazy
ne posent pas de problème lorsqu'ils sont utilisés comme valeurs dans un dictionnaire, car Django ou Python les convertissent automatiquement en chaînes lors du processus de sérialisation JSON.
En revanche, lorsqu'ils sont utilisés comme clés, la norme JSON impose qu'une clé doive être une chaîne. Dans ce cas, les objets gettext_lazy
ne se convertissent pas automatiquement et provoquent une erreur de sérialisation.
Conclusion :
- Lorsqu'ils sont utilisés comme valeurs, ils passent sans problème grâce à une conversion interne en str.
- Lorsqu'ils sont utilisés comme clés, la conversion ne se fait pas automatiquement, entraînant une erreur.
Solutions
Méthode 1 : Passer à gettext
(ne pas utiliser de lazy)
C'est la méthode la plus sûre. N'utilisez pas lazy et utilisez directement les valeurs converties en chaînes.
from django.utils.translation import gettext as _ # pas de lazy!
LANGUAGE_MAP = {
"en": _("English"),
"ko": _("Korean"),
"ja": _("Japanese"),
}
- Avantage : pas de traitement supplémentaire nécessaire
- Inconvénient : la traduction est déterminée au moment de l'importation initiale, ce qui peut différer de certains besoins de traduction dynamique
Méthode 2 : Appliquer str()
juste avant la sérialisation JSON
Si vous souhaitez continuer à utiliser des objets lazy, convertissez la clé en str()
avant de l'insérer dans le JSON.
lang = str(LANGUAGE_MAP.get(lang_code, lang_code.upper()))
- Avantage : peu ou pas de modifications requises dans le code existant
- Inconvénient : besoin de faire attention à chaque conversion str
Divers : traiter la traduction côté client
Il est également possible de ne pas effectuer de traduction multilingue côté serveur et de gérer cela entièrement côté frontend.
- Le serveur envoie uniquement le code de langue
- Le JavaScript client gère le tableau de traductions.
Cette méthode peut être choisie selon le projet.
Pour résumer
- Ne jamais utiliser
gettext_lazy
comme clé de dictionnaire - S'assurer que la conversion en chaîne se fait avant la sérialisation JSON
- La méthode la plus sûre est d'utiliser
gettext
pour une conversion immédiate en chaîne - Si la préservation du code existant est nécessaire, n'oubliez pas de faire
str(...)
Commentaires de Jesse
Ce problème est une erreur courante qui se produit à la frontière subtile entre le traitement multilingue dans Django et la gestion des réponses JSON.
Pensez désormais à "Pourquoi ça fonctionnait auparavant ?" plutôt qu'à "Pourquoi ça ne fonctionne pas maintenant ?" et revérifiez votre code.
Le moment où les compétences d'un développeur s'améliorent, c'est lorsqu'il comprend ces 'subtilités'. En comprenant ce principe, vous pouvez rendre la gestion multilingue de Django et les réponses JSON beaucoup plus robustes !
Add a New Comment