Traduction WordPress : Vous faites fausse route !
Je voudrais vous parler de la façon dont on développe son plugin ou thème dans le but de le rendre traduisible.
Y penser c’est déjà bien, mais il y a beaucoup d’erreurs à éviter, en voici une liste non exhaustive.
Rappels
Il existe en PHP une fonction _()
qui est un alias de gettext()
. Gettext est un outil unix qui gère la traduction de chaà®ne, pour faire simple.
Dans WordPress, cet équivalent plus simple à utiliser est __()
. WordPress a créé d’autres fonctions utilisant gettext()
afin de simplifier encore plus la vie des développeurs.
Par exemple, au lieu de faire echo __()
il existe _e()
. Aussi dans les fonctions de sécurité connues comme esc_attr()
, il existe esc_attr__()
et esc_attr_e()
.
La documentation de chacune de ces fonctions se trouve en bas de la page de celle de la fonction __() sur le codex.
Dans le reste de l’article je vais dire « plugin » mais cela fonctionne aussi pour un thème.
Erreurs à éviter
Bande de français !
La première erreur est une erreur française. Nous sommes français, nous développons pour nos clients français ou pour notre communauté française, ou alors nous n’estimons pas possible que d’autres personnes hors France utilisent notre plugin.
C’est bien sà»r faux, si votre plugin est sur le repository officiel, alors il sera téléchargé par le monde entier.
Cette erreur est donc tout simplement de NE PAS traduire son plugin et de tout mettre en dur :
Il faut donc penser de suite, dès les premières lignes de code à permettre l’internationalisation de votre code. La fonction __()
fera très bien l’affaire ici :
Domaine
En me corrigeant, j’en vient déjà à la 2ème erreur, je n’ai pas renseigné le dernier paramètre qui est le text domain.
Ce text domain est une chaine qui va servir à regrouper les traductions de mon plugin et ainsi ne pas les mélanger avec le core de WordPress ou d’autres plugins.
C’est une paramètre optionnel MAIS obligatoire dans le cas où c’est votre phrase ou mot que vous souhaitez traduire.
Je vais utiliser dans cet article le text domain « plugin-domain« .
Domaine ²
Avez-vous dans l’entête de votre plugin indiqué le text domain justement ?
Voici un exemple :
Cette valeur doit être identique au nom du dossier de votre plugin, autrement dit, le slug de votre plugin.
Elle va permettre à WordPress de pouvoir mettre à jour les fichiers de langue de votre plugin sans que ayez besoin de faire une nouvelle version.
Merci !
Et déjà la 3ème erreur, j’ai laissé mon texte en français.
Le fait de laisser son texte en français dans du code prêt à traduire signifie que si je suis sur une installation sans langue, je serais donc en en_US (anglais US), SAUF mon plugin en français !
Déroutant non ? Ha non, pas pour vous qui avez votre installation en français, vous ne vous êtes aperçu de rien, forcément.
Il faut TOUJOURS développer en anglais, même les noms de vos variables d’ailleurs, évitez $champ
et utilisez $field
par exemple.
$name
Je suis content, enfin réussi, mais ça me chagrine de devoir mettre le nom de l’utilisateur à remercier dans mon code, je voudrai le récupérer d’une variable, voici ce qui est (mal) fait :
Super non ? NON !?
Et non, car vous essayez de donner à gettext le mot $name
à traduire. Si dans votre site cela fonctionne, c’est parce qu’ici le code PHP est évalué et la variable remplacée par sa valeur.
Hors gettext n’est pas du php mais un outil unix qui n’évaluera pas cette variable !
Il existe des outils et des cas où cette façon de faire ne fonctionnera pas, il ne faut donc PAS mettre de variable de cette façon.
CONcat
Tentons une correction :
Mieux ? MMmnnnon, pas encore. La concaténation de la variable fonctionne, certes, dans votre site, tout est parfait, très bien.
MAIS dans certaines langues, il est fort possible que le nom de la personne se positionne en premier dans la phrase, l’ordre des mots change parfois.
La concaténation me force ici à dire « merci » avant le nom.
Et ne pensez pas à me dire « et si on traduisait le Thank you en vide ??? » car toutes les autres occurrences du mot « Thank you » seraient alors vides aussi.
Il nous faut utiliser une fonction de formatage de texte comme sprintf()
ou printf()
.
Cot cot cot
Me voilà enfin propre avec ma chaà®ne ! Pardon ? Pas encore ??
Vous utilisez des guillemets, les « double quotes ». Alors, oui ça fonctionne là , mais … ne prenez pas cette habitude car vous risquez de vous faire avoir, puisqu’une variable PHP contenue dans une chaà®ne entre guillemets sera évaluée.
Modifions un peu notre exemple :
Ici on reste bon, le contenu de $foo
est :
Mais imaginons qu’en français nous préférons mettre en avant les utilisateurs et ensuite les tickets, il me suffirait de traduire la chaà®ne en :
Ce qui me donne sur mon site :
Aà¯e … les quantités ne sont pas bonnes ! Je ne peut PAS intervertir mes %d
à remplacer !
Ouf, sprintf()
permet de le faire :
On voit bien maintenant que le premier paramètre et le second sont ordonnés, je peux traduire en :
Ce qui me donne sur mon site :
Quoi ?? Mais oui regardez, la variable $d
de la chaà®ne %1$d
a été évaluée et comme elle n’existe pas, elle vaut NULL
.
Voilà , vous avez compris pourquoi il FAUT utiliser uniquement les apostrophes, la single quote.
Corrigeons :
Ce qui me donne sur mon site :
Parfait.
Chariot
Je trouve que mes lignes sont trop longues, je vais les couper, je peux ?
Non !
Non plus ! Aucune concaténation dans vos chaà®nes. Cela peut fonctionner dans POEdit par exemple, mais pas forcément ailleurs, dans des logiciels qui vous sont inconnus.
Si vous avez de longues phrases et que vous ne souhaitez pas avoir des lignes de code de plus de 255 caractères, COUPEZ vos lignes :
$foo
a été concaténée avec .=
et le nom de la fonction __()
+ la chaà®ne à traduire + le domaine sont sur la même ligne de code, parfait.
Plural form
Ho mais attendez ! Je vois que ces deux quantités valent 1, alors que j’avais mis tickets et users au pluriel, c’est moche !
Ok j’ai une idée !
Mieux, mais pas très pro. Encore ?
à‡a fonctionne. En français. Car par exemple en anglais le 0 est pluriel, hors dans ce cas ci leur 0 sera singulier.
La bonne façon de faire est d’utiliser la fonction _n()
, tu essaies ?
à‡a fonctionne, en français … car en français notre seul singulier est « 1 », mais dans d’autres langues il commence à « 5 ». Il faut donc toujours utiliser%d
ou %s
.
- 1er paramètre = singulier
- 2ème paramètre = pluriel
- 3ème paramètre = nombre pour la comparaison
- 4ème paramètre = text domain
J’ai préféré utiliser %s
plutôt que %d
alors que le nombre de ticket sera bel et bien un entier MAIS avec une chaà®ne de caractère je permets à ce chiffre de contenir des virgules et espaces pour les séparateurs de milliers.
Haaa voilà ! Enfin !
Chaque langue ou presque a un pluriel personnel, voici la liste de ces règles :
Add New
Passons à un autre exemple, je veux pouvoir traduire « Add New« , je fais donc :
Cela s’utilise donc dans le menu de mon custom post type. Mais comment traduire ça ?
« Ajouter un nouveau » ? « Ajouter une nouvelle » ? « Ajouter des nouveaux » ? « Ajouter des nouvelles » ? Aà¯e, impossible ni de connaitre le genre ni le nombre de cette chaà®ne.
Il faut lui ajouter un contexte afin de savoir quels genre et nombre choisir. Cela se fait avec _x()
:
Je code donc en anglais et j’utilise le 3ème paramètre pour renseigner le contexte. Le dernier paramètre est toujours le text domain.
En français je peux alors traduire par :
Si j’ai besoin de cette même traduction plus tard, il me suffit de modifier le contexte :
En français je peux alors traduire par :
Login
Bon, j’ai compris, et ça c’est bon ?
Oui et non. C’est bon mais WordPress connait déjà cette chaà®ne. Le text domain de WordPress est « default« , ne rien mettre en text domain revient à mettre cette valeur.
Le fait d’ajouter votre propre text domain vous force a créer une traduction.
Vous pouvez, selon moi, utiliser les chaà®nes courtes sans domaine afin de bénéficier des traductions de WordPress, mais si la chaà®ne est longue, vous risquez de voir un jour cette traduction modifiée, au risque que son contexte change pour vous.
Dans ce cas, évitez vraiment.
gisa
Autre exemple venant du core :
Ceci est correct, mais je ne comprends pas forcément comment traduire ça. Il s’agit en fait d’un format de date/time.
Dans votre code PHP, commentez alors cette ligne :
Par contre, dans vos plugins, si vous avez besoin d’un format de date ou d’heure, ne recréez pas vos données, lisez les options :
Point important rappelé par Nicolas Maillard, il faut utiliser la fonction date_i18n()
et non pas date()
pour afficher une date dans la langue du site, sinon c’est la langue du serveur qui sera affichée !!
DOM
Nous avons vu pas mal de chaà®nes assez simples, qu’en est-il du code HTML ?
Prenons un nouvel exemple :
Cela fonctionne, parfait. MAIS vous laissez la possibilité aux autres langues de mettre des balises H1, ou même ne rien mettre ? Pas logique selon moi. Exportez le contenu HTML important :
Maintenant les balises H3 sont forcées ! Même choses pour les styles et class, évitez de laissez ça en traduction. Par contre s’il s’agit de balises plus simple comme I, B, EM, STRONG etc, vous pouvez, selon moi, laisser passer.
Dernier cas : les liens !
Avec ce cas je ne permet pas aux autres langues de modifier mon lien. C’est bien par exemple pour vos crédits ou des URLs qui ne changeront pas.
Par contre s’il s’agit de vidéos tutos youtube, de documentation, ces liens sont susceptibles d’exister dans d’autres langues, laissez alors les liens dans la traduction. Il se pourrait même que le lien soit supprimé car, n’existant qu’en français, la personne ai besoin de le supprimer.
D’un autre côté, selon les cas, vous pouvez aussi forcer les liens en les sortants de la traduction comme on a fait avec les H3.
SCRIPT
Si vous souhaitez afficher du JavaScript dans votre code, il est possible que vous fassiez ça :
Mais pour du contenu plus lourd, je vous recommande de créer un .js
.
Malheureusement un .js ne peut pas être traduit directement via le code PHP.
Néanmoins la fonction wp_localize_script() permet de pallier à ce problème.
Exemple provenant du codex :
Vous pouvez maintenant récupérer dans votre script :
RN
Il existe quelques chaà®nes un peu spéciales que gettext n’aime pas trop :
La tentative de traduction d’un espace sans contexte n’est pas valide, utilisez plutôt _x()
.
Et la tentative de traduction de retour chariot n’est pas non plus appréciée :
GENERATEWP
Petit point spécial pour parler du site generatewp.com qui vous permet entre autre de générer facilement le code des custom posts types.
Le soucis est que le code fourni mets la priorité de ton hook sur 0 :
Et habituellement les plugins et thèmes ajoutent le chargement de la traduction aussi dans init :
La priorité par défaut étant 10, les traductions du CPT sont chargées à vide avant que le fichier de traduction ne le soit, et aucun traduction ne fonctionne pour votre CPT …
Vous avez appris quelque chose ? Tant mieux, c’est le but !
Réagir à cet article