Recherche…


Syntaxe

  • gettext (message)
  • ngettext (singulier, pluriel, nombre)
  • ugettext (message)
  • ungettext (singulier, pluriel, nombre)
  • pgettext (contexte, message)
  • npgettext (contexte, singulier, pluriel, nombre)
  • gettext_lazy (message)
  • ngettext_lazy (singulier, pluriel, nombre = aucun)
  • ugettext_lazy (message)
  • ungettext_lazy (singulier, pluriel, nombre = aucun)
  • pgettext_lazy (contexte, message)
  • npgettext_lazy (contexte, singulier, pluriel, nombre = aucun)
  • gettext_noop (message)
  • ugettext_noop (message)

Introduction à l'internationalisation

Mise en place

settings.py

from django.utils.translation import ugettext_lazy as _

USE_I18N = True  # Enable Internationalization
LANGUAGE_CODE = 'en'  # Language in which original texts are written
LANGUAGES = [  # Available languages
    ('en', _("English")),
    ('de', _("German")),
    ('fr', _("French")),
]

# Make sure the LocaleMiddleware is included, AFTER SessionMiddleware
# and BEFORE middlewares using internationalization (such as CommonMiddleware)
MIDDLEWARE_CLASSES = [
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.locale.LocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
]

Marquage des chaînes comme traduisible

La première étape de la traduction consiste à marquer les chaînes comme pouvant être traduites . Cela les fait passer par l’une des fonctions de gettext (voir la section Syntaxe ). Par exemple, voici un exemple de définition de modèle:

from django.utils.translation import ugettext_lazy as _
# It is common to import gettext as the shortcut `_` as it is often used
# several times in the same file.

class Child(models.Model):

    class Meta:
        verbose_name = _("child")
        verbose_name_plural = _("children")

    first_name = models.CharField(max_length=30, verbose_name=_("first name"))
    last_name = models.CharField(max_length=30, verbose_name=_("last name"))
    age = models.PositiveSmallIntegerField(verbose_name=_("age"))

Toutes les chaînes encapsulées dans _() sont maintenant marquées comme traduisibles. Une fois imprimées, elles seront toujours affichées en tant que chaîne encapsulée, quelle que soit la langue choisie (car aucune traduction n’est encore disponible).

Traduire les chaînes

Cet exemple est suffisant pour commencer avec la traduction. La plupart du temps, vous ne voudrez que marquer des chaînes comme traduisibles pour anticiper l’internationalisation prospective de votre projet. Ainsi, cela est couvert dans un autre exemple .

Traduction paresseuse vs non paresseuse

Lorsque vous utilisez une traduction non paresseuse, les chaînes sont traduites immédiatement.

>>> from django.utils.translation import activate, ugettext as _
>>> month = _("June")
>>> month
'June'
>>> activate('fr')
>>> _("June")
'juin'
>>> activate('de')
>>> _("June")
'Juni'
>>> month
'June'

Lorsque vous utilisez la paresse, la traduction ne se produit que lorsqu'elle est réellement utilisée.

>>> from django.utils.translation import activate, ugettext_lazy as _
>>> month = _("June")
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> str(month)
'June'
>>> activate('fr')
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> "month: {}".format(month)
'month: juin'
>>> "month: %s" % month
'month: Juni'

Vous devez utiliser la traduction paresseuse dans les cas où:

  • La traduction ne peut pas être activée (langue non sélectionnée) lorsque _("some string") est évalué
  • Certaines chaînes peuvent être évaluées uniquement au démarrage (par exemple, attributs de classe tels que les définitions de champs de modèle et de formulaire)

Traduction en gabarits

Pour activer la traduction dans les modèles, vous devez charger la bibliothèque i18n .

{% load i18n %}

La traduction de base est faite avec l'étiquette de modèle trans .

{% trans "Some translatable text" %}
{# equivalent to python `ugettext("Some translatable text")` #}

La balise de modèle trans prend en charge le contexte:

{% trans "May" context "month" %}
{# equivalent to python `pgettext("May", "month")` #}

Pour inclure des espaces réservés dans votre chaîne de traduction, comme dans:

_("My name is {first_name} {last_name}").format(first_name="John", last_name="Doe")

Vous devrez utiliser la blocktrans template blocktrans :

{% blocktrans with first_name="John" last_name="Doe" %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

Bien sûr, au lieu de "John" et "Doe" vous pouvez avoir des variables et des filtres:

{% blocktrans with first_name=user.first_name last_name=user.last_name|title %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

Si first_name et last_name sont déjà dans votre contexte, vous pouvez même omettez la with clause:

{% blocktrans %}My name is {{ first_name }} {{ last_name }}{% endblocktrans %}

Cependant, seules les variables de contexte de "niveau supérieur" peuvent être utilisées. Cela ne fonctionnera pas:

{% blocktrans %}
    My name is {{ user.first_name }} {{ user.last_name }}
{% endblocktrans %}

C'est principalement parce que le nom de la variable est utilisé comme espace réservé dans les fichiers de traduction.

La blocktrans modèle blocktrans accepte également la pluralisation.

{% blocktrans count nb=users|length }}
    There is {{ nb }} user.
{% plural %}
    There are {{ nb }} users.
{% endblocktrans %}

Enfin, quelle que soit la bibliothèque i18n , vous pouvez transmettre des chaînes traduisibles aux balises de modèle à l'aide de la syntaxe _("") .

{{ site_name|default:_("It works!") }}
{% firstof var1 var2 _("translatable fallback") %}

Ceci est un système de modèle de django intégré magique pour imiter une syntaxe d'appel de fonction mais ce n'est pas un appel de fonction. _("It works!") Est passé à la default étiquette de modèle comme une chaîne '_("It works!")' Qui est ensuite analysé une chaîne traduisible, tout comme le name serait analysé comme une variable et "name" serait analysé comme une chaîne.

Traduire les chaînes

Pour traduire des chaînes, vous devrez créer des fichiers de traduction. Pour ce faire, Django est livré avec la commande de gestion makemessages .

$ django-admin makemessages -l fr
processing locale fr

La commande ci-dessus détectera toutes les chaînes marquées comme traduisibles dans vos applications installées et créera un fichier de langue pour chaque application pour la traduction française. Par exemple, si vous n'avez qu'une seule application myapp contenant des chaînes traduisibles, cela créera un fichier myapp/locale/fr/LC_MESSAGES/django.po . Ce fichier peut ressembler à ceci:

# 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: 2016-07-24 14:01+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: myapp/models.py:22
msgid "user"
msgstr ""

#: myapp/models.py:39
msgid "A user already exists with this email address."
msgstr ""

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""

Vous devrez d'abord remplir les espaces réservés (accentués par des majuscules). Ensuite, traduisez les chaînes. msgid est la chaîne marquée comme traduisible dans votre code. msgstr est l'endroit où vous devez écrire la traduction de la chaîne ci-dessus.

Lorsqu'une chaîne contient des espaces réservés, vous devrez également les inclure dans votre traduction. Par exemple, vous traduirez le dernier message comme suit:

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""
"En vous inscrivant, vous acceptez nos <a href=\"%(terms_url)s\" "
"target=_blank>Conditions d'utilisation</a>"

Une fois votre fichier de traduction terminé, vous devrez compiler les fichiers .po dans des fichiers .mo . Cela se fait en appelant la commande compilemessages management:

$ django-admin compilemessages

Ça y est, maintenant les traductions sont disponibles.

Pour mettre à jour vos fichiers de traduction lorsque vous apportez des modifications à votre code, vous pouvez réexécuter django-admin makemessages -l fr . Cela mettra à jour .po fichiers .po , conservera vos traductions existantes et ajoutera les nouvelles. Les chaînes supprimées seront toujours disponibles dans les commentaires. Pour mettre à jour .po fichiers .po pour toutes les langues, lancez django-admin makemessages -a . Une fois vos fichiers .po mis à jour, n'oubliez pas de lancer à nouveau django-admin compilemessages pour générer des fichiers .mo .

Cas d'utilisation Noop

(u)gettext_noop vous permet de marquer une chaîne comme traduisible sans la traduire réellement.

Un cas d'utilisation typique est lorsque vous souhaitez enregistrer un message pour les développeurs (en anglais) mais que vous souhaitez également l'afficher sur le client (dans la langue demandée). Vous pouvez transmettre une variable à gettext , mais son contenu ne sera pas découvert en tant que chaîne traduisible car elle est, par définition, variable. .

# THIS WILL NOT WORK AS EXPECTED
import logging 
from django.contrib import messages

logger = logging.getLogger(__name__)

error_message = "Oops, something went wrong!"
logger.error(error_message)
messages.error(request, _(error_message))

Le message d'erreur n'apparaîtra pas dans le fichier .po et vous devrez vous souvenir qu'il existe pour l'ajouter manuellement. Pour résoudre ce problème, vous pouvez utiliser gettext_noop .

error_message = ugettext_noop("Oops, something went wrong!")
logger.error(error_message)
messages.error(request, _(error_message))

Maintenant la chaîne "Oops, something went wrong!" sera découvert et disponible dans le fichier .po lors de sa génération. Et l'erreur sera toujours enregistrée en anglais pour les développeurs.

Pièges communs

traductions floues

Parfois, les makemessages peuvent penser que la chaîne trouvée pour la traduction est quelque peu similaire à la traduction existante. Il le marquera dans le fichier .po avec un commentaire fuzzy spécial comme ceci:

#: templates/randa/map.html:91
#, fuzzy
msgid "Country"
msgstr "Länderinfo"

Même si la traduction est correcte ou si vous l'avez mise à jour pour la corriger, elle ne sera pas utilisée pour traduire votre projet, sauf si vous supprimez fuzzy ligne de commentaire fuzzy .

Cordes multilignes

makemessages analyse les fichiers dans différents formats, du texte brut au code python et n'est pas conçu pour suivre toutes les règles possibles pour avoir des chaînes multi-lignes dans ces formats. La plupart du temps, cela fonctionnera très bien avec des chaînes de caractères simples, mais si vous avez une construction comme celle-ci:

translation = _("firstline"
"secondline"
"thirdline")

Il ne ramasser firstline pour la traduction. La solution consiste à éviter d'utiliser des chaînes multilignes lorsque cela est possible.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow