Training Menu

Internationalisation et régionalisation dans Django

Kevin TIAKOUANG DJOU
Kevin TIAKOUANG DJOU
Jan. 11, 2025 · 61.00 min read
0
Django
Internationalisation et régionalisation dans Django

Introduction

Aperçu

L’internationalisation et la régionalisation sont des étapes essentielles dans le développement d’applications web modernes, visant à adapter le contenu et les formats pour un public mondial. Ces concepts permettent à une application unique de répondre aux besoins de différents utilisateurs, en leur offrant une expérience localisée dans leur langue et selon leurs conventions culturelles.

Django intègre des fonctionnalités robustes pour gérer la traduction des textes, la mise en forme des dates, heures, et nombres, ainsi que la gestion des fuseaux horaires.

En résumé, Django facilite deux aspects principaux :

  1. Permettre aux développeurs et aux créateurs de gabarits de marquer les éléments de leur application à traduire ou à formater selon les paramètres locaux.

  2. Appliquer ces paramètres pour adapter dynamiquement l’application en fonction des préférences des utilisateurs.

La traduction dépend de la langue cible, tandis que la mise en forme est souvent déterminée par les conventions du pays. Ces informations sont généralement transmises par les navigateurs via l’en-tête Accept-Language.

 

Définitions

Les termes « internationalisation » et « régionalisation » sont souvent confondus. Voici une définition simplifiée :

Internationalisation

  • Préparation du logiciel pour permettre sa régionalisation. Généralement mise en œuvre par les développeurs.

Régionalisation

  • Adaptation du contenu et des formats selon une langue et une culture spécifique. Cela inclut la traduction et est généralement réalisée par des traducteurs.

 

Terminologie importante

Voici quelques termes clés à connaître pour travailler avec l’internationalisation dans Django :

  • Nom de locale
     Une chaîne indiquant soit une langue (par exemple fr), soit une combinaison langue-pays (par exemple fr_CA). Les langues sont en minuscules, les pays en majuscules (ex. : es_MX, en_US).

  • Code de langue
     Le format utilisé dans l’en-tête Accept-Language des navigateurs pour indiquer les langues acceptées. Exemple : fr, en-us.

  • Fichier de messages
     Fichiers .po contenant les chaînes à traduire et leurs équivalents traduits.

  • Chaîne à traduire
     Texte marqué dans l’application comme nécessitant une traduction.

  • Format de fichier
     Modules Python définissant les formats locaux pour les dates, heures, nombres, etc.

 

 

 

 

Mise en œuvre de l’internationalisation et de la régionalisation dans un projet concret

Prérequis

Système d’exploitation Ubuntu, ou tout autres systèmes d’exploitation Linux, Python 3, GNU gettext.

Pour la l’installation de Python 3 si ce n’est pas encore le cas : Dans un terminal utilisez la commande sudo apt update puis sudo apt install python3

Pour GNU gettext utiliser toujours dans un terminal la commande sudo apt install gettext.

 

Initialisation

Après avoir créé un environnement virtuel(optionnel) utiliser la commande, on installe django puis on crée un projet et en suite une application.

Configuration

Après l’initialisation du projet passons donc à la configuration du projet, et nous commençons par se rassurer que l’application que nous avons créée est bien dans la liste des applications enregistrer au travers de la constante INSTALLED_APPS.

Ensuite nous passons à l’active l’internationalisation et la régionalisation, puis nous choisissons la langue par défaut et on met la liste des langues pris en charge dans le projet et enfin on précise le chemin vers les fichiers de traduction :
 USE_I18N = True

USE_L10N = True

LANGUAGE_CODE = 'en'

LANGUAGES = [

    ('en', _('English')),

    ('fr', _('French')),

]

LOCALE_PATHS = [

    os.path.join(BASE_DIR, 'locale'),

]

 

En dernier position, on ajoute l’intergiciel (middleware) django.middleware.locale.LocaleMiddleware, qui joue un rôle crucial dans l’internationalisation et la régionalisation, surtout en détectant et en configurant la langue active de l'application pour chaque requête en fonction des préférences utilisateur (sessions, cookies ou en-têtes HTTP) ou des informations dans l'URL, afin de présenter le contenu et les formats adaptés à la langue et à la culture locales.
 MIDDLEWARE = [

    'django.middleware.security.SecurityMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',

    'django.middleware.locale.LocaleMiddleware',

    'django.middleware.common.CommonMiddleware',

    'django.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.auth.middleware.AuthenticationMiddleware',

    'django.contrib.messages.middleware.MessageMiddleware',

    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

 

Mise en œuvre

Dans un projet Django, il existe plusieurs endroits où l'on peut gérer la traduction afin de rendre l'application accessible dans différentes langues. Ces endroits incluent les fichiers Python, tels que les vues et les modèles, les gabarits (templates), et même le code JavaScript pour la traduction côté client.

I. Traduction dans les fichiers Python (.py)

Le module django.utils.translation fournit plusieurs fonctions qui facilitent la traduction du texte dans les fichiers Python de votre projet. Ces fonctions permettent de marquer les chaînes de caractères pour qu'elles soient traduites dans les fichiers de messages (.po). Voici un aperçu de ces fonctions, avec des exemples simples pour mieux comprendre leur utilisation :

1. gettext

Utilisée pour traduire une chaîne simple.

Exemple :

from django.utils.translation import gettext as _

message = _("Welcome to our platform!")

2. ngettext

Utilisée pour les chaînes dépendantes du nombre (pluriel/singulier).

Exemple :

from django.utils.translation import ngettext

message = ngettext(

    "You have one new message.",

    "You have {count} new messages.",

    count=3

)

3. pgettext

Ajoute un contexte à une chaîne pour éviter les ambiguïtés dans la traduction.

Exemple :

from django.utils.translation import pgettext

message = pgettext("salutation", "Hello")

4. npgettext

Combine la gestion du pluriel et le contexte.

Exemple :

from django.utils.translation import npgettext

message = npgettext(

    "email notification",

    "You have one new email.",

    "You have {count} new emails.",

    count=2

)

5. gettext_noop

Marque une chaîne pour la traduction, mais ne la traduit pas immédiatement. Utile pour les chaînes stockées dans la base de données ou les constantes.

Exemple :

from django.utils.translation import gettext_noop

GREETING = gettext_noop("Welcome back!")

6. Fonctions "lazy"

Les versions différées (gettext_lazy, ngettext_lazy, etc.) sont utilisées lorsque la traduction doit être retardée jusqu'à ce que la chaîne soit réellement affichée, par exemple dans les modèles ou les formulaires.

Exemple :

from django.utils.translation import gettext_lazy as _

class MyModel(models.Model):

    title = models.CharField(max_length=100, verbose_name=_("Title"))

 

II. Traduction dans les gabarits (templates)

Django offre un support complet pour l'internationalisation directement dans les gabarits HTML, grâce à des balises et filtres spécialement conçus. Cela permet de traduire efficacement le contenu visible par les utilisateurs dans différentes langues. Pour utiliser ces outils, il est nécessaire d'ajouter {% load i18n %} au début du gabarit. Cette balise doit être incluse dans chaque fichier où des traductions sont nécessaires, même si le gabarit hérite d’un autre qui a déjà chargé la bibliothèque i18n.

  • Balise {% translate %}

La balise {% translate %} est utilisée pour traduire une chaîne statique ou une variable.

  • Exemple simple :

<p>{% translate "Hello, World!" %}</p>

  • Traduction de variables :

<p>{% translate greeting_variable %}</p>

  • Option noop :

Pour marquer un texte comme nécessitant une traduction ultérieure, utilisez l'option noop.

<p>{% translate "This text will be translated later" noop %}</p>

  • Utilisation avec une variable traduite :

{% translate "Site title" as site_title %}

<title>{{ site_title }}</title>

 

  • Balise {% blocktranslate %}

Pour des textes plus complexes qui incluent des variables ou des substitutions, on utilise {% blocktranslate %}. Cette balise permet de combiner texte et logique de traduction.

  • Exemple avec une variable :

{% blocktranslate %}

Hello, {{ username }}! Welcome to our platform.

{% endblocktranslate %}

 

  • Pluriels :

Pour gérer les pluriels, la balise accepte l'option count et une balise {% plural %} pour définir les formes singulière et plurielle.

{% blocktranslate count item_count=items|length %}

 

There is {{ item_count }} item in your cart.

 

{% plural %}

 

There are {{ item_count }} items in your cart.

 

{% endblocktranslate %}

 

  • Utilisation de variables dynamiques :

Pour traduire des expressions plus complexes, vous pouvez utiliser l'option with pour définir des variables locales.

{% blocktranslate with price=product.price %}

This product costs ${{ price }}.

{% endblocktranslate %}

 

  • Option trimmed :

Cette option permet de supprimer les espaces ou sauts de ligne inutiles pour améliorer la lisibilité et simplifier la traduction dans les fichiers .po.

{% blocktranslate trimmed %}

  This is the first line.

  This is the second line.

{% endblocktranslate %}

  • Traduction des chaînes passées en argument à une balise ou un filtre :

Pour transmettre une chaîne traduite à une balise ou un filtre, utilisez la fonction _().

{% some_tag _("Page not found") %}

     Cela traduit automatiquement la chaîne avant de l’envoyer à la balise ou au filtre.

 

III.    Commentaire pour les traducteurs

Dans le code Python de Django, on peut ajouter des commentaires pour les traducteurs en utilisant # Translators: avant les chaînes à traduire. Ces commentaires aident à préciser le contexte, comme l'emplacement du texte, et sont inclus dans les fichiers .po pour guider les traducteurs.

  • Exemple en Python :

# Translators: This message appears on the home page only

output = gettext("Welcome to my site.")

Dans les gabarits, des commentaires sont aussi possibles avec {% comment %} ou {# … #} pour fournir des précisions avant les balises de traduction comme {% translate %}. Ces notes apparaissent également dans les fichiers .po.

  • Exemple en template :

{# Translators: Label of a button that triggers search #}

<button type="submit">{% translate "Go" %}</button>

 

IV.   Traduction côté client (JavaScript)

La traduction côté client dans un projet Django se fait principalement via l'utilisation de la vue JavaScriptCatalog. Cette vue génère un fichier JavaScript contenant des fonctions qui simulent l'interface de traduction de gettext pour le côté client, permettant ainsi d'effectuer des traductions directement dans le code JavaScript exécuté sur le navigateur de l'utilisateur.

  • Vue JavaScriptCatalog

Django propose la vue JavaScriptCatalog pour intégrer la traduction côté client. Cette vue génère un fichier JavaScript contenant un ensemble de fonctions et un tableau de chaînes traduites. Vous pouvez inclure ce fichier dans vos pages HTML de manière dynamique. Voici un exemple de configuration :

from django.views.i18n import JavaScriptCatalog

from django.urls import path

 

urlpatterns = [

    path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"),

]

La vue JavaScriptCatalog vous permet de générer un fichier contenant les traductions de votre projet en utilisant les mêmes chaînes présentes dans vos fichiers .po ou .mo, mais adaptées pour être utilisées en JavaScript.

  • Intégration du catalogue JavaScript

Pour utiliser les traductions dans vos fichiers JavaScript, il suffit d'inclure le fichier généré par la vue JavaScriptCatalog dans vos pages HTML :

<script src="{% url 'javascript-catalog' %}"></script>

Cela permet à votre code JavaScript d'utiliser des fonctions de traduction telles que gettext, ngettext, interpolate, et bien d'autres, de manière similaire à la traduction côté serveur.

 

  • Fonctions disponibles en JavaScript

Voici une liste des principales fonctions disponibles après l'intégration du fichier JavaScript des traductions :

  1. gettext : Permet de traduire une chaîne de texte simple.

document.write(gettext("Welcome to the site!"));

  1. ngettext : Utilisée pour la traduction de chaînes avec pluriels, en fonction d'un nombre donné.

const itemsCount = 2;

const string = ngettext('There is one item', 'There are multiple items', itemsCount);

  1. interpolate : Permet d'insérer des variables dans une chaîne de format.

const message = interpolate("You have %(count)s new messages", {count: 5});

  1. get_format : Permet d'accéder à des formats de date, heure, ou de nombre régionalisés.

const dateFormat = get_format('DATE_FORMAT');

Voici les autres réglages possibles :

DATE_INPUT_FORMATS

DATETIME_FORMAT

DATETIME_INPUT_FORMATS

DECIMAL_SEPARATOR

FIRST_DAY_OF_WEEK

MONTH_DAY_FORMAT

NUMBER_GROUPING

SHORT_DATE_FORMAT

SHORT_DATETIME_FORMAT

THOUSAND_SEPARATOR

TIME_FORMAT

TIME_INPUT_FORMATS

YEAR_MONTH_FORMAT

  1. gettext_noop : Fonction utilisée pour marquer des chaînes qui seront traduites plus tard.

document.write(gettext_noop("This will not be translated immediately."));

  1. pgettext : Permet de traduire une chaîne en prenant en compte le contexte.

document.write(pgettext("month name", "January"));

  1. npgettext : Version plurielle de pgettext, utile pour les chaînes de texte pluriels avec contexte.

document.write(npgettext('group', 'party', 1));

document.write(npgettext('group', 'party', 2));

  1. pluralidx : Détermine la nécessité d'un pluriel en fonction du nombre donné.

document.write(pluralidx(1));  // false

document.write(pluralidx(2));  // true

 

 

V. Internationalisation dans les motifs d'URL

     Django propose deux mécanismes pour gérer l'internationalisation des URL :

  • Ajout du préfixe de langue : Utilise LocaleMiddleware pour détecter la langue à partir de l'URL demandée.

  • Traduction des motifs d'URL : Utilisation de gettext_lazy() pour rendre les motifs eux-mêmes traduisibles.

Avertissement 

L'usage de ces mécanismes requiert que LocaleMiddleware soit inclus dans le réglage MIDDLEWARE de votre projet pour garantir qu'une langue active soit définie pour chaque requête.

  • Préfixe de langue dans les motifs d'URL

La fonction i18n_patterns() permet de préfixer automatiquement les motifs d'URL avec le code de la langue active. Le paramètre prefix_default_language=False

permet d'éviter le préfixe pour la langue par défaut.

  • Exemple de configuration des URL :

from django.conf.urls.i18n import i18n_patterns

from django.urls import include, path

 

news_patterns = [

    path("", news_views.index, name="index"),

    path("category/<slug:slug>/", news_views.category, name="category"),

    path("<slug:slug>/", news_views.details, name="detail"),

]

 

urlpatterns += i18n_patterns(

    path("about/", about_views.main, name="about"),

    path("news/", include(news_patterns, namespace="news")),

)

 

  • Exemple d'utilisation des URL traduites :

from django.urls import reverse

from django.utils.translation import activate

 

activate("en")

reverse("news:index"# '/en/news/'

 

activate("nl")

reverse("news:detail", kwargs={"slug": "news-slug"})  # '/nl/news/news-slug/'

 

  • Avec prefix_default_language=False et LANGUAGE_CODE='en' :

reverse("news:index"# '/news/'

 

               Avertissements 

  • Limitation : i18n_patterns() doit être utilisé uniquement dans la configuration d'URL racine.

  • Précaution : Evitez d'avoir des motifs d'URL non préfixés qui pourraient être confondus avec ceux utilisant le préfixe de langue.

 

VI.  Régionalisation : Comment créer les fichiers de langues

Pour gérer la traduction des chaînes marquées dans le code Django, il est nécessaire de créer des fichiers de messages pour chaque langue cible. Ces fichiers contiennent toutes les chaînes à traduire et leurs traductions. Les fichiers de messages ont l'extension .po.

  • Création de fichiers de messages

Django propose la commande makemessages pour générer et mettre à jour ces fichiers de messages de manière automatisée. Par exemple, pour créer ou mettre à jour un fichier de messages pour l'allemand, vous pouvez utiliser la commande suivante :

python manage.py makemessages -l de

Cette commande génère ou met à jour un fichier .po dans le répertoire locale/de/LC_MESSAGES/django.po. Le répertoire doit être présent sous locale/LANG/LC_MESSAGES, où LANG représente le code de la langue (par exemple, de pour l'allemand).

 

  • Fonctionnement de makemessages

Lorsque vous lancez makemessages depuis le répertoire racine de votre projet ou d'une de vos applications Django, il parcourt l'arborescence des sources du projet pour extraire les chaînes marquées à traduire. Il crée ou met à jour le fichier .po correspondant dans les répertoires appropriés.

 

Par défaut, makemessages examine les fichiers avec les extensions .html, .txt et .py. Si vous souhaitez spécifier d'autres extensions, utilisez l'option --extension ou -e :

python manage.py makemessages -l de -e txt

 

  • Option -d pour préciser le domaine

L'option -d permet de spécifier le domaine du fichier de traduction, qui détermine le contexte d'extraction des chaînes. Par défaut, le domaine est django, mais si vous travaillez avec des fichiers JavaScript, vous devez utiliser djangojs comme domaine :

python manage.py makemessages -l de -d djangojs

Cela garantit que les traductions de JavaScript seront extraites sous le bon domaine.

  • Utilisation avec Javascript

Lorsque vous créez des fichiers de messages à partir du code JavaScript, il est nécessaire d'utiliser le domaine djangojs plutôt que d'utiliser l'extension -e js. Cela garantit que les traductions seront correctement extraites et associées.

  • Limitations de makemessages

Si les utilitaires gettext ne sont pas installés, makemessages génère des fichiers vides. Dans ce cas, il est recommandé d'installer les utilitaires gettext ou d'utiliser un fichier .po vide comme point de départ.

Pour les projets utilisant des gabarits Jinja2, il est préférable d'utiliser Babel pour extraire les chaînes, car makemessages ne prend pas en charge la syntaxe spécifique des gabarits Jinja2.

Aperçu d’un fichier de traduction :
 # SOME DESCRIPTIVE TITLE.

# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER

# This file is distributed under the same license as the PACKAGE package.

# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.

#

#, fuzzy

msgid ""

msgstr ""

"Project-Id-Version: PACKAGE VERSION\n"

"Report-Msgid-Bugs-To: \n"

"POT-Creation-Date: 2025-01-10 11:36+0100\n"

"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"

"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"

"Language-Team: LANGUAGE <LL@li.org>\n"

"Language: \n"

"MIME-Version: 1.0\n"

"Content-Type: text/plain; charset=UTF-8\n"

"Content-Transfer-Encoding: 8bit\n"

"Plural-Forms: nplurals=2; plural=(n > 1);\n"

 

#: LearnI18N/settings.py:96

msgid "English"

msgstr "Anglais"

 

#: LearnI18N/settings.py:97

msgid "French"

msgstr "Français"

 

#: home/apps.py:8

msgid "Home App"

msgstr "Application Home"

 

#: home/models.py:14

#, python-format

msgid "This greeting has %(count)s word."

msgid_plural "This greeting has %(count)s words."

msgstr[0] "Cette salutation a %(count)s mot."

msgstr[1] "Cette salutation a %(count)s mots."

 

Conclusion

L'internationalisation et la localisation dans Django offrent des outils puissants pour rendre vos applications accessibles à un public mondial. En suivant les bonnes pratiques présentées dans cet article, vous pouvez adapter votre interface utilisateur, vos motifs d’URL et vos fichiers de traduction pour répondre aux besoins de différents utilisateurs et cultures.

Pour mieux comprendre et appliquer ces concepts, vous pouvez explorer un exemple de projet disponible sur GitHub. Ce dépôt fournit un code prêt à l’emploi pour expérimenter les fonctionnalités i18n et l10n dans Django.

 

0

Applaudissez pour montrer votre soutien

Kevin TIAKOUANG DJOU

Kevin TIAKOUANG DJOU

2 Followers · Writer for Django

Passionné de Django pour sa facilité à créer des applications web robustes, je serais ravi de mettre mes compétences en Python-Django au service to… Read more