Les traductions de votre extension WordPress ne s’affichent pas ? Corrigez les traductions manquantes
Des traductions manquent après un passage de PTC ? Trois vérifications permettent de trouver presque toutes les causes. Vérifiez que la chaîne a bien atteint PTC, que le nom du fichier .mo correspond à ce que WordPress attend, et que le text domain est cohérent dans tout votre code. Ce guide détaille chaque vérification dans l’ordre où elles doivent être effectuées.
Le même ordre de diagnostic fonctionne que vous ayez traduit avec PTC (Private Translation Cloud), GlotPress ou tout autre outil basé sur gettext. Les modes de défaillance sont inhérents au pipeline i18n de WordPress, et non à un traducteur particulier.
Confirmer que la chaîne a atteint PTC
Il s’agit d’abord de vérifier si la chaîne se trouve dans votre projet PTC. Si une chaîne n’a pas été extraite dans votre fichier .pot, PTC ne l’a jamais vue. Le fichier .po ne contient aucune traduction pour celle-ci. L’extension en cours d’exécution affiche alors le texte de secours en langue source.
Comment vérifier :
- Ouvrez la chaîne concernée dans l’extension en cours d’exécution et copiez son texte exact.
- Allez sur votre tableau de bord PTC, ouvrez l’onglet Translations et recherchez la chaîne.
- Si elle n’y est pas, PTC ne l’a jamais reçue.
Trois causes courantes en découlent.
Cause 1 : la chaîne est absente de votre fichier POT
wp i18n make-pot extrait uniquement les chaînes situées à l’intérieur des fonctions i18n reconnues. Cela signifie __(), _e(), _n(), _x(), ainsi que les variantes échappées, avec le bon text domain. Les chaînes associées au mauvais domaine sont ignorées. Les chaînes codées en dur en dehors d’une fonction i18n sont ignorées.
Relancez l’extraction et vérifiez que la chaîne figure désormais dans le .pot :
wp i18n make-pot . languages/my-plugin.pot --domain=my-plugin
grep "Save Changes" languages/my-plugin.pot
Si grep renvoie la chaîne avec un msgid, l’extraction fonctionne. Téléchargez à nouveau le nouveau .pot sur PTC et retraduisez. Si grep ne renvoie rien, la chaîne est codée en dur et n’est pas enveloppée dans __(). C’est là que se situe votre bug. Enveloppez la chaîne et procédez à une nouvelle extraction.
Cause 2 : le texte n’est pas enveloppé dans une fonction gettext
Chaque chaîne traduisible de votre code a besoin d’une enveloppe. Utilisez __(), esc_html__(), _e(), _n() ou _x() avec le text domain correct :
__( 'Hello, world!', 'your-plugin' );
Cause 3 : les chaînes JavaScript n’ont pas été marquées comme traduisibles
Si votre extension inclut du texte traduisible en JavaScript :
- Dans le tableau de bord PTC, allez dans Settings > Monitored Files.
- Modifiez le fichier de ressources concerné et activez Is this a WordPress project with localizable JavaScript?
Cela indique à PTC de scanner les fichiers JavaScript pour y trouver des chaînes traduisibles. PTC régénère les traductions et ouvre une nouvelle merge request avec les fichiers mis à jour.
Assurez-vous ensuite que WordPress sait où charger les fichiers de traduction .json produits par PTC. Appelez wp_set_script_translations() avec le chemin correct :
// For plugins
wp_set_script_translations(
'script-handle',
'text-domain',
plugin_dir_path( __FILE__ ) . 'languages'
);
// For themes
wp_set_script_translations(
'script-handle',
'text-domain',
get_template_directory() . '/languages'
);
Cela indique à WordPress de charger les fichiers .json depuis le dossier de votre extension ou de votre thème.
Confirmer que WordPress charge votre fichier .mo
Si la chaîne est présente dans PTC et que le fichier .mo existe dans le répertoire languages/ de votre extension, mais que l’extension affiche toujours l’anglais, c’est que WordPress ne parvient pas à charger le .mo.
Diagnostic 1 : la locale du site est-elle correctement définie ? Allez dans Réglages > Général > Langue du site dans wp-admin et confirmez qu’elle correspond à votre langue cible. Par exemple, réglez-la sur « espagnol » pour tester l’espagnol. Si le site est en anglais, votre fichier .mo espagnol ne sera jamais chargé. Ce n’est pas un bug.
Diagnostic 2 : load_plugin_textdomain() est-elle réellement exécutée ? Ajoutez une ligne de débogage temporaire :
add_action( 'init', function() {
$loaded = load_plugin_textdomain(
'my-plugin',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages'
);
error_log( 'my-plugin textdomain loaded: ' . var_export( $loaded, true ) );
} );
Rechargez une page et vérifiez votre journal d’erreurs PHP. loaded: true signifie que WordPress a trouvé et chargé un fichier .mo pour la locale actuelle. loaded: false signifie qu’il ne l’a pas fait. La cause est généralement une discordance de nom de fichier (voir la section suivante) ou un mauvais chemin de répertoire.
Diagnostic 3 : le timing du hook est-il correct ? load_plugin_textdomain() doit s’exécuter sur le hook init. C’est le hook canonique pour que les traductions s’appliquent aux chaînes affichées lors du traitement normal d’une requête.
Diagnostic 4 : les traductions de la communauté remplacent-elles vos fichiers groupés ? Par défaut, WordPress donne la priorité aux fichiers de traduction stockés dans /wp-content/languages/. Si votre extension ou thème dispose de traductions fournies par la communauté sur WordPress.org, ces fichiers peuvent écraser les fichiers .mo inclus dans votre projet. Pour éviter cela, utilisez le filtre load_textdomain_mofile pour forcer le chargement du chemin de votre fichier groupé avant que WordPress ne vérifie le répertoire global. Les projets comportant plusieurs text domains (une extension qui en intègre une autre) nécessitent que chaque domaine soit chargé séparément. Chaque domaine a besoin de son propre appel load_plugin_textdomain() ou load_theme_textdomain().
S’assurer que le nom du fichier MO correspond au modèle de recherche de WordPress
La recherche de fichiers .mo par WordPress suit une convention de nommage stricte. S’il manque un seul caractère, WordPress revient silencieusement à l’anglais.
La convention dépend de l’endroit où vous placez le fichier :
| Emplacement | Modèle | Exemple |
|---|---|---|
/languages/ de l’extension |
{text-domain}-{locale}.mo |
my-plugin-de_DE.mo |
/languages/ du thème |
{locale}.mo |
de_DE.mo |
Répertoire global (/wp-content/languages/...) |
{text-domain}-{locale}.mo |
my-theme-de_DE.mo |
Quelques exemples concrets :
my-plugin-es_ES.mopour l’espagnol (Espagne)my-plugin-fr_FR.mopour le français (France)my-plugin-pt_BR.mopour le portugais (Brésil)my-plugin-zh_CN.mopour le chinois simplifiémy-plugin-ja.mopour le japonais (certaines locales n’ont pas de suffixe de région)
Erreurs courantes :
- Mauvais préfixe de text-domain. Si l’en-tête
Text Domainde votre extension estmy-pluginmais que le.moest nommémyplugin-es_ES.mo(sans trait d’union), WordPress ne le trouvera pas. Le préfixe doit correspondre exactement à la valeurText Domain. - Mauvais code de locale.
es.moau lieu dees_ES.mo. WordPress utilise des codes de locale régionaux.es_ES,es_MXetes_ARsont des fichiers différents. Un code de langue seul ne fonctionne que lorsqu’aucun fichier régional n’existe. - Trait d’union vs underscore. Les codes de locale utilisent l’underscore (
es_ES), jamais le trait d’union (es-ES). Cela piège souvent les développeurs qui copient les codes de locale depuis les en-têtesAccept-Languagedes navigateurs ou les sources BCP 47, où le trait d’union est la norme. - Mauvais répertoire. L’en-tête
Domain Pathdoit pointer vers le répertoire contenant vos fichiers.mo. Si leDomain Pathest/languageset que vos fichiers.mosont dans/lang/, WordPress ne les trouvera pas.
Vérifiez en listant les fichiers produits par PTC par rapport à la locale utilisée par votre site :
ls plugins/my-plugin/languages/
# my-plugin-es_ES.mo
# my-plugin-es_ES.po
# my-plugin-fr_FR.mo
# my-plugin-fr_FR.po
Si les noms semblent corrects mais que les traductions ne se chargent toujours pas, lancez le diagnostic load_plugin_textdomain() ci-dessus pour confirmer que WordPress trouve bien le répertoire.
Vérifier que votre text domain est cohérent dans tout votre code
C’est la cause invisible la plus fréquente. Chaque appel à __(), _e(), _n(), _x() dans votre code passe un text domain comme dernier argument. Si un seul appel passe le mauvais domaine, cette chaîne spécifique ne sera pas traduite. Toutes les autres chaînes de l’extension fonctionneront correctement.
// Correct - matches the plugin's Text Domain
$correct = __( 'Save Changes', 'my-plugin' );
// Wrong - text domain typo; this string is never translated
$wrong = __( 'Save Changes', 'myplugin' ); // missing hyphen
// Wrong - copy-pasted from another plugin
$wrong = __( 'Save Changes', 'other-plugin' );
// Wrong - WordPress core domain; works for core strings but not yours
$wrong = __( 'Save Changes', 'default' );
Trouvez les incohérences en effectuant un grep dans votre base de code :
grep -rE "__\(|_e\(|_n\(|_x\(" --include="*.php" .
Examinez le dernier argument de chaque correspondance. Ils devraient tous correspondre au text domain de votre extension. Si vous trouvez des fautes de frappe ou des erreurs de copier-coller, corrigez-les et relancez wp i18n make-pot pour actualiser le .pot.
Pour le code JavaScript utilisant @wordpress/i18n, la même règle s’applique. wp_set_script_translations() en PHP doit également passer le domaine correspondant :
wp_set_script_translations( 'my-plugin-editor', 'my-plugin', '...' );
// ^^^^^^^^^^^
// Must match the JS calls
Détecter les mêmes problèmes avant leur mise en production avec AI Visual QA
La boucle de diagnostic ci-dessus est réactive. Une traduction manque, vous partez à la recherche de la cause. AI Visual QA détecte ces mêmes problèmes avant qu’ils ne soient mis en production. Il inspecte l’extension rendue dans chaque langue cible après chaque mise à jour de traduction et signale ce qui manque ou ce qui est erroné.
Pour une chaîne anglaise codée en dur en dehors de __() (Cause 1 ci-dessus), l’AI Visual QA voit la chaîne non traduite dans l’extension rendue. PTC génère un prompt prêt à être collé pour Cursor ou Claude Code afin d’envelopper la chaîne dans __(). Pour une discordance de text domain (la vérification de la section précédente), il voit que la chaîne n’est pas traduite alors que d’autres chaînes sur le même écran le sont, et signale l’incohérence.
Si vous n’avez pas encore activé l’AI Visual QA, consultez le tutoriel sur les thèmes et extensions WordPress pour la configuration.
Quand les trois vérifications réussissent mais que les traductions manquent toujours
Si vous avez vérifié les trois causes et que les traductions ne s’affichent toujours pas, envoyez un e-mail au support de PTC avec :
- Le text domain de votre extension.
- L’un des noms de fichiers
.mo(par exemple,my-plugin-es_ES.mo). - Une capture d’écran du tableau de bord PTC montrant la chaîne concernée avec sa traduction.
- Le réglage de la langue du site dans Réglages > Général.
La plupart des cas de « traduction manquante » se résument à l’une des causes ci-dessus. Les cas particuliers (versions spécifiques de WordPress, résolution de locale MultiSite, conflit avec une autre extension i18n) nécessitent parfois un examen plus approfondi.
Maintenir les futures versions synchronisées grâce à la traduction continue
Une fois que vos traductions se chargent correctement, configurez le flux de traduction continue afin que les futures versions restent synchronisées avec vos traductions — automatiquement, à chaque push sur la branche principale.