Utiliser msgctxt : Ajouter du contexte aux traductions Gettext

Vous traduisez le mot anglais « Book » en allemand, et votre traducteur retourne avec confiance « Buch ». Trois semaines plus tard, un rapport de bug arrive : le bouton « Book a table » de votre formulaire de réservation indique maintenant « Buch a table » - le nom, et non le verbe. Le mot était correct. Le contexte manquait. Il s'agit de l'une des défaillances silencieuses les plus courantes dans la localisation logicielle, et la solution existe dans Gettext depuis des décennies : msgctxt.
Si vous avez déjà livré une traduction où une seule chaîne anglaise était correcte à un endroit et absurde à un autre, vous avez rencontré le problème de l'ambiguïté. Le même mot source correspond à différentes traductions selon l'endroit où il apparaît. Sans msgctxt, le traducteur (humain ou IA) n'a aucun moyen de distinguer ces cas, car tout ce qu'il voit est la chaîne brute msgid "Book". Ce guide explique comment msgctxt fonctionne dans Gettext, comment baliser votre code source avec _x() et _ex(), comment il apparaît dans vos fichiers .po, et pourquoi un pipeline de traduction sensible au contexte est le seul moyen fiable d'obtenir ces chaînes correctement à grande échelle.
Le problème de l'ambiguïté : un mot, plusieurs significations
Le langage naturel est plein de mots qui se réduisent à un seul jeton anglais mais se divisent en plusieurs mots dans d'autres langues. Le traducteur ne voit que la chaîne source, donc lorsque deux éléments d'interface utilisateur sans rapport partagent le même mot anglais, ils partagent le même msgid - et Gettext les fusionne en une seule entrée.
Mots qui se divisent selon les langues
Considérez trois exemples classiques :
- « Book » - le nom (un objet sur une étagère) versus le verbe (« Book a flight », réserver un vol). Allemand : Buch versus buchen.
- « Post » - publier du contenu versus envoyer du courrier. Français : publier versus courrier.
- « Order » - une séquence/un tri versus un achat. Espagnol : orden versus pedido.
En anglais, votre code utilise la même chaîne littérale aux deux endroits :
// Somewhere in a library catalog screen
echo __( 'Book', 'mytextdomain' );
// Somewhere in a reservation form button
echo __( 'Book', 'mytextdomain' );
Comment les chaînes identiques se réduisent à une seule entrée
Lorsque vous exécutez wp i18n make-pot ou xgettext, les deux appels se réduisent à une seule entrée .po :
#: catalog.php:42 reservation-form.php:88
msgid "Book"
msgstr ""
Il n'y a qu'un seul msgstr à remplir. Quoi que le traducteur choisisse, l'un des deux écrans sera incorrect. Le traducteur ne peut pas corriger cela même s'il comprend le problème, car le format lui-même ne lui permet pas de fournir deux traductions pour un seul msgid. L'ambiguïté est intrinsèque aux données.
Qu'est-ce que msgctxt et comment résout-il l'ambiguïté ?
msgctxt est une chaîne de contexte attachée à une entrée de traduction. La réponse courte : elle ajoute une deuxième clé à côté de msgid, de sorte que Gettext traite (context, msgid) comme une paire unique. Deux entrées avec le même msgid mais un msgctxt différent deviennent deux chaînes distinctes, traduisibles indépendamment.
Dans le modèle de recherche de Gettext, une traduction est normalement indexée uniquement par la chaîne source. Avec msgctxt, la clé devient la combinaison du contexte et de la source. C'est l'intégralité du mécanisme, et c'est pourquoi il fonctionne si proprement : vous ne modifiez pas le texte affiché, seulement la clé de recherche interne.
La ligne msgctxt dans un fichier .po
Dans un fichier .po, le contexte apparaît sur sa propre ligne directement au-dessus du msgid :
#: catalog.php:42
msgctxt "noun"
msgid "Book"
msgstr "Buch"
#: reservation-form.php:88
msgctxt "verb"
msgid "Book"
msgstr "Reservieren"
Maintenant, il y a deux entrées. Elles ont des valeurs msgid identiques mais des valeurs msgctxt distinctes, de sorte que chacune obtient son propre msgstr. Le catalogue affiche Buch ; le bouton de réservation affiche Reservieren. L'exécution choisit la bonne parce que votre code lui a dit quel contexte utiliser.
Comparez cela à la version cassée à entrée unique ci-dessus. La différence n'est pas la qualité de la traduction - c'est si le modèle de données permet même à la bonne réponse d'exister.
Baliser votre code : _x() et _ex()
Pour émettre msgctxt dans votre template .po, vous appelez une fonction de traduction sensible au contexte au lieu de la fonction simple. Dans WordPress, il s'agit de _x() et de sa fonction sœur d'écho _ex() ; dans Gettext brut, elles correspondent à pgettext().
Choisir entre _x() et _ex()
La fonction simple __() prend la chaîne et le domaine de texte. La variante contextuelle insère le contexte comme deuxième argument :
// Without context - ambiguous
__( 'Book', 'mytextdomain' );
// With context - the second argument is the msgctxt
_x( 'Book', 'noun', 'mytextdomain' ); // returns the translated string
_ex( 'Book', 'verb', 'mytextdomain' ); // echoes it directly
// Real-world disambiguation
_x( 'Post', 'verb: publish content', 'mytextdomain' );
_x( 'Post', 'noun: mail item', 'mytextdomain' );
_x( 'Order', 'sequence or sorting', 'mytextdomain' );
_x( 'Order', 'customer purchase', 'mytextdomain' );
Le deuxième argument est l'étiquette de contexte. Elle n'est jamais montrée à vos utilisateurs - elle existe uniquement pour lever l'ambiguïté, à la fois pour la recherche Gettext et pour quiconque (ou quoi que ce soit) effectue la traduction. Écrivez les contextes comme des indices courts et descriptifs : 'noun', 'verb', 'button label', 'admin menu'. Un contexte vague comme '1' est techniquement valide mais inutile pour un traducteur.
Lorsque vous régénérez le template, l'extracteur reconnaît ces appels et émet la ligne msgctxt. Des outils comme Poedit et d'autres éditeurs PO regroupent alors les entrées visiblement par contexte, de sorte qu'un traducteur humain voit immédiatement que « Book (nom) » et « Book (verbe) » sont deux tâches différentes. Si vous êtes encore en train de configurer votre chaîne d'outils d'extraction ou de vous battre avec la façon dont les variables interagissent avec ces chaînes, notre guide sur la traduction de fichiers PO sans casser les variables de code couvre en profondeur le flux de travail environnant.
Pourquoi les traducteurs naïfs - et de nombreux outils d'IA - se trompent
Voici la partie délicate. L'ajout de msgctxt à votre source est nécessaire mais pas suffisant. Le contexte n'aide que si l'entité effectuant la traduction le lit réellement.
Le mode d'échec du contexte ignoré
Un script de traduction par lots naïf procède comme suit : il parcourt les entrées, prend chaque msgid, l'envoie à une API de traduction et écrit le résultat dans msgstr. Il ne regarde jamais la ligne msgctxt. Ainsi, même si vous avez soigneusement écrit _x( 'Book', 'noun' ) et _x( 'Book', 'verb' ), le script envoie deux requêtes identiques - « traduire Book » - et colle la même réponse dans les deux. Tout votre effort de balisage est ignoré à la dernière étape.
De nombreux outils de traduction par IA à usage général ont le même angle mort. Ils sont conçus pour traduire du texte, et msgctxt est des métadonnées, pas du texte. Si l'outil aplatit votre fichier .po en une liste de chaînes avant de l'envoyer au modèle, le contexte n'atteint jamais l'invite du modèle. Le modèle, dépourvu de tout signal, se base sur le sens le plus courant statistiquement du mot - généralement le nom pour « Book », le sens de publication pour « Post » - et traduit silencieusement de manière erronée le cas minoritaire. Vous ne verrez pas d'erreur. Vous verrez un rapport de bug d'un utilisateur allemand des semaines plus tard.
Le contexte et les pluriels partagent la même cause profonde
C'est aussi là que la gestion des pluriels et le contexte se recoupent, car tous deux dépendent de la capacité de l'outil à comprendre la structure de Gettext plutôt que de traiter le fichier comme du texte plat. Si vos chaînes impliquent également des formes basées sur le nombre, la même conscience structurelle est importante - nous détaillons cela dans comprendre les pluriels Gettext.
Comment un pipeline sensible au contexte utilise msgctxt
Un pipeline de traduction qui respecte msgctxt fait l'inverse du script naïf. Il analyse le fichier .po comme des données structurées, maintient le contexte de chaque entrée attaché à sa chaîne source, et transmet ce contexte à l'IA comme partie de l'invite - ainsi le modèle sait qu'il traduit « Book » spécifiquement comme un verbe, et non dans l'abstrait.
Le contexte comme signal de première classe
C'est exactement ainsi que SimplePoTranslate aborde le problème. Son IA sensible au contexte lit la ligne msgctxt comme un signal de première classe : lorsque deux entrées partagent un msgid mais diffèrent par le contexte, elles sont traduites comme les chaînes distinctes qu'elles sont réellement, et l'indice de contexte informe le choix de mots du modèle. Le résultat est que « Book (nom) » revient comme Buch tandis que « Book (verbe) » revient comme buchen ou reservieren - automatiquement, sans que vous ayez à corriger manuellement chaque terme ambigu.
Tout aussi important, le pipeline préserve la ligne msgctxt dans la sortie. Un outil moins performant pourrait supprimer le contexte lors des allers-retours, fusionnant discrètement vos deux entrées en une seule et réintroduisant l'ambiguïté lors de la prochaine fusion. Un support Gettext complet signifie que le contexte survit à la traduction, à la compilation .mo et à toute réimportation ultérieure - ainsi votre désambiguïsation est durable, et non un correctif manuel ponctuel. Combiné au verrouillage syntaxique pour les placeholders à l'intérieur de ces chaînes, vous obtenez des traductions à la fois contextuellement correctes et structurellement intactes.
Vous êtes toujours responsable de la décision de balisage - vous seul savez qu'un « Book » donné est un verbe. Mais une fois que vous avez annoté votre source avec _x() et _ex(), un pipeline sensible au contexte transforme cette annotation en traductions correctes dans toutes les langues cibles sans surveillance chaîne par chaîne.
Conclusion
Le problème de l'ambiguïté - un mot anglais, plusieurs significations - n'est pas une bizarrerie que vous pouvez ignorer ; c'est une caractéristique structurelle de la façon dont Gettext stocke les chaînes. La solution est msgctxt : annotez les chaînes ambiguës dans votre source avec _x() et _ex(), donnez à chaque occurrence une étiquette de contexte claire, et laissez Gettext indexer la traduction sur la paire (context, msgid). Cette partie dépend de vous, et cela prend quelques minutes.
La partie la plus difficile est de s'assurer que votre étape de traduction respecte réellement ce contexte au lieu de le jeter. Les scripts naïfs et les outils d'IA basés uniquement sur le texte ignorent msgctxt et réintroduisent le bug exact que vous essayiez d'éviter. Un pipeline sensible au contexte lit le contexte, traduit correctement chaque entrée désambiguïsée et le préserve à travers la compilation et les réimportations.
Prêt à cesser de livrer des traductions erronées dues à un manque de contexte ? Essayez SimplePoTranslate gratuitement — aucune carte de crédit requise. La version gratuite gère les vrais fichiers
.poet.potavec un support complet du contexte msgctxt, afin que vos chaînes désambiguïsées soient traduites correctement du premier coup.