PTC

Les traductions du plugin WordPress ne s'affichent pas ? Corrigez les traductions manquantes

Des traductions manquent après une exécution de PTC ? Quatre vérifications permettent de trouver presque toutes les causes. Vérifiez que la chaîne a 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ù les exécuter.

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.

Confirmez que la chaîne a atteint PTC

La première question est de savoir 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. Le plugin en cours d'exécution affiche la langue source de repli.

Comment vérifier :

  1. Ouvrez la chaîne concernée dans le plugin en cours d'exécution et copiez son texte exact.
  2. Allez dans votre tableau de bord PTC, ouvrez l'onglet Translations, et recherchez la chaîne.
  3. Si elle ne s'y trouve pas, PTC ne l'a jamais reçue.

Voici trois causes courantes.

Cause 1 : la chaîne est absente de votre fichier POT

wp i18n make-pot n'extrait que les chaînes situées à l'intérieur des fonctions i18n reconnues. Cela signifie __(), _e(), _n(), _x(), et les variantes échappées, avec le bon text domain. Les chaînes situées dans le mauvais domaine sont ignorées. Les chaînes en dur en dehors d'une fonction i18n sont ignorées.

Exécutez à nouveau l'extraction et vérifiez que la chaîne se trouve maintenant 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éversez à nouveau le nouveau .pot sur PTC et retraduisez. Si grep ne renvoie rien, la chaîne est en dur et n'est pas encapsulée dans __(). C'est votre bug. Encapsulez la chaîne et extrayez-la à nouveau.

Cause 2 : le texte n'est pas encapsulé dans une fonction gettext

Chaque chaîne traduisible dans votre code nécessite un wrapper. 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 plugin inclut du texte traduisible en JavaScript :

  1. Dans le tableau de bord PTC, allez dans Settings > Monitored Files.
  2. Modifiez le fichier de ressources correspondant et activez « Is this a WordPress project with localizable JavaScript? »

Cela indique à PTC d'analyser les fichiers JavaScript à la recherche de 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 plugin ou de votre thème.

Confirmez que WordPress charge votre fichier .mo

Si la chaîne se trouve dans PTC et que le fichier .mo existe dans le répertoire languages/ de votre plugin, mais que le plugin rendu affiche toujours de l'anglais, WordPress ne parvient pas à charger le .mo.

Diagnostic 1 : la locale du site est-elle définie correctement ? 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 « Español » pour tester l'espagnol. Si le site est en anglais, votre .mo espagnol ne se chargera jamais. Ce n'est pas un bug.

Diagnostic 2 : load_plugin_textdomain() s'exécute-t-il réellement ? 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 incohérence du nom de fichier (voir la section suivante) ou un chemin de répertoire erroné.

Diagnostic 3 : le moment 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 pendant le traitement normal de la requête.

Diagnostic 4 : les traductions communautaires remplacent-elles vos fichiers inclus ? Par défaut, WordPress donne la priorité aux fichiers de traduction stockés dans /wp-content/languages/. Si votre plugin ou thème possède des traductions communautaires sur WordPress.org, ces fichiers peuvent remplacer 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 inclus avant que WordPress ne vérifie le répertoire global. Les projets à text domains multiples (un plugin qui intègre un autre plugin) 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().

Assurez-vous que le nom du fichier MO correspond au modèle de recherche de WordPress

La recherche de fichiers .mo de WordPress suit une convention de nommage stricte. À un caractère près, WordPress utilise silencieusement l'anglais comme langue de repli.

La convention dépend de l'endroit où vous placez le fichier :

Emplacement Modèle Exemple
/languages/ du plugin {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.mo pour l'espagnol (Espagne)
  • my-plugin-fr_FR.mo pour le français (France)
  • my-plugin-pt_BR.mo pour le portugais (Brésil)
  • my-plugin-zh_CN.mo pour le chinois simplifié
  • my-plugin-ja.mo pour 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 Domain de votre plugin est my-plugin mais que le .mo est nommé myplugin-es_ES.mo (sans trait d'union), WordPress ne le trouvera pas. Le préfixe doit correspondre exactement à la valeur Text Domain.
  • Mauvais code de locale. es.mo au lieu de es_ES.mo. WordPress utilise des codes de locale régionaux. es_ES, es_MX et es_AR sont des fichiers différents. Un code de langue simple ne fonctionne que lorsqu'aucun fichier régional n'existe.
  • Trait d'union vs tiret du bas. Les codes de locale utilisent le tiret du bas (es_ES), jamais le trait d'union (es-ES). Cela piège les développeurs qui copient les codes de locale depuis les en-têtes Accept-Language du navigateur ou des sources BCP 47, où le trait d'union est la norme.
  • Mauvais répertoire. L'en-tête Domain Path doit pointer vers le répertoire contenant vos fichiers .mo. Si Domain Path est /languages et que vos fichiers .mo sont dans /lang/, WordPress ne les trouvera pas.

Vérifiez en listant les fichiers produits par PTC par rapport à la locale que votre site utilise :

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, exécutez le diagnostic load_plugin_textdomain() ci-dessus pour confirmer que WordPress trouve le répertoire.

Vérifiez que votre text domain est cohérent dans tout votre code

C'est le tueur silencieux. Chaque appel __(), _e(), _n(), _x() dans votre code transmet un text domain comme dernier argument. Si ne serait-ce qu'un seul appel transmet le mauvais domaine, cette chaîne spécifique ne sera pas traduite. Toutes les autres chaînes du plugin 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 utilisant grep sur votre base de code :

grep -rE "__\(|_e\(|_n\(|_x\(" --include="*.php" .

Regardez le dernier argument de chaque correspondance. Ils devraient tous être le text domain de votre plugin. Si vous trouvez des fautes de frappe ou des erreurs de copier-coller, corrigez-les et réexécutez 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 transmettre le domaine correspondant :

wp_set_script_translations( 'my-plugin-editor', 'my-plugin', '...' );
//                                                ^^^^^^^^^^^
//                                                Must match the JS calls

Détectez ces mêmes problèmes avant de publier avec la AI Visual QA

La boucle de diagnostic ci-dessus est réactive. Une traduction manque, vous partez à la recherche de la cause. L'AI Visual QA de PTC détecte ces mêmes problèmes avant la publication. Elle inspecte le plugin rendu dans chaque langue cible après chaque mise à jour de traduction et signale ce qui manque ou est incorrect.

Pour une chaîne en anglais en dur en dehors de __() (Cause 1 ci-dessus), la AI Visual QA voit la chaîne non traduite dans le plugin rendu. PTC génère un prompt prêt à coller pour Cursor ou Claude Code afin d'encapsuler la chaîne dans __(). Pour une incohérence de text domain (la vérification de la section précédente), elle voit la chaîne non 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é la AI Visual QA, consultez le tutoriel sur les thèmes et plugins WordPress pour la configuration.

Lorsque les quatre vérifications réussissent mais que les traductions manquent toujours

Si vous avez effectué les quatre vérifications et que les traductions ne s'affichent toujours pas, envoyez un e-mail au support PTC avec :

  • Le text domain de votre plugin.
  • 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 limites (versions spécifiques de WordPress, résolution de locale MultiSite, conflit avec un autre plugin i18n) nécessitent parfois un examen plus approfondi.

Gardez les futures versions synchronisées grâce à la localisation continue

Une fois que vos traductions se chargent correctement, configurez le flux de travail de localisation continue pour que les futures versions restent synchronisées avec vos traductions - automatiquement, à chaque push vers main.