Tutoriel¶
Cette page va d'un répertoire vide à un programme qui salue en japonais. Cinq étapes, aucune expérience de gettext supposée, et chaque commande est montrée avec la sortie qu'elle produit réellement — à chaque étape, vous savez donc si vous êtes sur la bonne voie.
Il vous faut Python 3.14 ou plus récent, car les t-strings sont une syntaxe
nouvelle de la version 3.14. Le japonais est la langue cible d'exemple de
cette page, mais rien ne dépend de ce choix. Pour une autre langue, remplacez
ja à l'étape 4 — ce code de locale est la seule chose qui la nomme.
1. Installer¶
L'extra [babel] installe Babel, l'outil qui collecte vos messages dans des
fichiers catalogues à l'étape 3. C'est un outil de développement : le code de
production rend les messages avec la seule bibliothèque standard.
2. Marquer un message dans votre code¶
Créez app.py :
t"Hello {name}" ressemble à une f-string, mais le préfixe t garde le texte
et la valeur séparés au lieu de les fusionner sur place. C'est cette séparation
qui permet à tr() de chercher une traduction pour la phrase complète
Hello {name} puis d'insérer la valeur ensuite.
Exécutez-le dès maintenant :
Aucune traduction n'est encore installée, le texte source est donc rendu tel quel. Un programme qui utilise cette bibliothèque n'exige jamais de catalogue pour fonctionner — l'anglais (ou votre langue source, quelle qu'elle soit) est le repli intégré.
3. Extraire les messages¶
Les traducteurs travaillent en général à partir de catalogues plutôt que du code source : un petit fichier appelé catalogue voyage donc entre vous et eux. La première étape vers ce catalogue consiste à collecter chaque message marqué dans le code.
Indiquez à Babel comment trouver vos messages en créant babel.cfg :
Puis extrayez vers un fichier modèle (.pot) :
$ mkdir -p locales
$ pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
locales/messages.pot contient désormais une entrée par message :
msgid est la clé que votre code recherchera. Le msgstr vide est l'endroit
où va une traduction — mais pas dans ce fichier : un .pot est un modèle,
et l'étape suivante le copie une fois par langue.
4. Traduire et compiler¶
Créez le catalogue japonais à partir du modèle :
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Ouvrez locales/ja/LC_MESSAGES/messages.po et remplissez le msgstr :
Gardez {name} exactement tel quel — le marqueur est ce qui permet à la valeur
de trouver sa place dans la phrase traduite, et la traduction est libre de le
déplacer là où la langue cible l'exige. Sur un vrai projet, ce fichier .po
est ce que vous remettez à un traducteur ou téléversez sur une plateforme de
traduction ; le format est le même dans les deux cas.
Les catalogues s'éditent en texte mais se chargent sous une forme binaire
(.mo), donc compilez :
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Cette commande est aussi un filet de sécurité. Si la traduction avait endommagé
le marqueur — {nome} au lieu de {name}, par exemple — elle refuserait de
passer :
$ pybabel compile -d locales
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nome} is not in the source message
1 errors encountered.
Une réserve qu'il vaut mieux connaître dès maintenant : elle signale l'erreur
et sort avec un statut non nul, mais écrit tout de même le .mo. Sur un vrai
projet, c'est à la CI de s'arrêter sur ce statut de sortie —
En production met cela en place.
5. Exécuter¶
Les étapes 2 à 4 utilisaient tr(), qui cherche un catalogue et n'en trouve
aucun. Maintenant qu'il en existe un, chargez-le et liez-le une fois pour
toutes : Translator détient un catalogue pour que les sites d'appel n'aient
pas à le nommer, et _ est le nom gettext conventionnel du résultat.
Pointez app.py vers le catalogue compilé. Cliquez sur les pastilles pour
voir ce que fait chaque ligne :
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- La bibliothèque standard charge le
.mocompilé, etTranslatorle lie à un appelable._est le nom gettext conventionnel pour « traduis ceci » — court parce qu'il apparaît sur chaque chaîne destinée à l'utilisateur. Il effectue la même traduction quetr, lié à un seul catalogue. - À l'appel : le texte de la t-string devient la clé de recherche
Hello {name}, le catalogue répondこんにちは {name}, la réponse est vérifiée contre les marqueurs de la source, et alors seulement la valeur est mise en place.
Voilà toute la boucle, et elle vaut d'être vue en une seule image :
flowchart LR
mark["1–2 marquer<br>t-strings dans le code"] --> extract["3 extraire<br>messages.pot"]
extract --> translate["4 traduire<br>ja/…/messages.po"]
translate --> compile["4 compiler<br>ja/…/messages.mo"]
compile --> run["5 exécuter<br>こんにちは Ada"]
Marquer → extraire → traduire → compiler → exécuter. Tout le reste de ce site est un approfondissement de l'une de ces cinq étapes.
Pour continuer¶
- Pourquoi les t-strings — ce dont cette conception vous
protège, comparée à
%(name)s,.format()et aux chaînes$. - Guide — pluriels, langue par requête, chaînes différées et ce qui se passe à l'exécution quand un catalogue est malgré tout incorrect.
- En production — cette même boucle telle qu'une équipe la fait tourner, semaine après semaine : mise à jour des catalogues, barrières de CI et plateformes de traduction.
- Extraction — la référence
pybabelcomplète : noms de fonctions personnalisés, mode strict pour la CI et les contrôles qui protègent vos catalogues. - Migration — si le projet dans lequel vous voulez vraiment faire cela possède déjà des catalogues gettext.
- Pour les traducteurs — la page à remettre à qui remplira
ces lignes
msgstr.