PTC

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

Des traductions sont manquantes 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 de 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 d'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 n'a aucune traduction pour elle. Le plugin en cours d'exécution affiche le repli dans la langue source.

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 manquante dans votre fichier POT

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

Réexécutez 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 réextrayez.

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

Chaque chaîne traduisible de votre code a besoin d'un wrapper. Utilisez __(), esc_html__(), _e(), _n() ou _x() avec le bon text domain :

__( '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 concerné 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 bon chemin :

// 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 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 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, définissez-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 incompatibilité de nom de fichier (voir la section suivante) ou un chemin de répertoire incorrect.

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 des requêtes.

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 a 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 à plusieurs text domains (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 de 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 se replie silencieusement sur l'anglais.

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 se nomme 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 seul ne fonctionne que lorsqu'aucun fichier régional n'existe.
  • Trait d'union contre trait de soulignement. Les codes de locale utilisent le trait de soulignement (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 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, 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 passe un text domain comme dernier argument. Si un seul appel passe le mauvais domaine, cette unique chaîne ne sera pas traduite. Toutes les autres chaînes du plugin fonctionneront parfaitement.

// 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 exécutant grep sur votre base de code :

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

Regardez le dernier argument de chaque correspondance. Ils devraient tous correspondre au 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 passer le domaine correspondant :

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

Détectez les mêmes problèmes avant leur publication avec l'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 les mêmes problèmes avant leur publication. Elle inspecte le plugin rendu dans chaque langue cible après chaque mise à jour de traduction et signale ce qui manque ou ce qui est incorrect.

Pour une chaîne anglaise en dur en dehors de __() (Cause 1 ci-dessus), l'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 sont traduites, et signale l'incohérence.

Si vous n'avez pas encore activé l'AI Visual QA, consultez le tutoriel sur les thèmes et plugins WordPress pour la configuration.

Lorsque les quatre vérifications sont validées 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 de PTC avec :

  • Le text domain de votre plugin.
  • L'un des noms de fichiers .mo (par ex., 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 depuis 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 d'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 fois que vous poussez vers main.