vendredi 25 septembre 2026

À propos

Contact

Tests

Détecter les chaînes non traduites et les textdomains erronés en CI

Vérifier automatiquement l'internationalisation de votre extension à chaque pull request, avec les sniffs WordPress dédiés et un contrôle du fichier .pot.

Par Clément Hadrot • 15 janvier 2025 • 5 min de lecture • Aucun commentaire
Détecter les chaînes non traduites et les textdomains erronés en CI

Un client distribuant son extension sur plusieurs marchés européens nous a signalé que la version allemande n’affichait presque aucune chaîne traduite, alors que le fichier de traduction existait bel et bien et semblait complet. Le coupable : plusieurs appels à __() dans le code utilisaient le textdomain de l’extension écrit en dur sous forme de variable concaténée, une pratique qui empêche les outils d’extraction de chaînes de les repérer, et qui empêche tout simplement WordPress de les charger correctement au moment de l’exécution.

Ce genre d’erreur ne casse rien de visible pour un développeur qui teste en français ou dans la langue par défaut du site : elle ne se révèle qu’au moment où un utilisateur change réellement de langue, souvent bien après la mise en production. C’est un candidat idéal pour un contrôle automatisé en CI plutôt qu’une vérification manuelle.

Les erreurs de textdomain les plus fréquentes

Le textdomain doit être une chaîne littérale, identique au slug déclaré dans l’en-tête du plugin, passée telle quelle à chaque appel de fonction de traduction. Trois erreurs reviennent régulièrement dans les audits :

// Erreur : textdomain construit dynamiquement, illisible par les outils d'extraction
__( 'Enregistrer les modifications', $this->textdomain );

// Erreur : textdomain qui ne correspond pas au slug déclaré dans l'en-tête du plugin
__( 'Enregistrer les modifications', 'mon-extension-ancien-nom' );

// Correct : chaîne littérale identique au slug du plugin
__( 'Enregistrer les modifications', 'mon-extension' );

La première erreur est la plus insidieuse : le code fonctionne parfaitement en local puisque la variable contient bien la bonne valeur à l’exécution, mais aucun outil d’extraction statique de chaînes ne peut résoudre une variable, ce qui vide le fichier .pot généré de ces chaînes.

Activer les sniffs i18n de WordPress Coding Standards

Le jeu de règles WordPress-Extra de PHPCS inclut des sniffs dédiés à l’internationalisation, regroupés sous WordPress.WP.I18n, qui détectent justement ce type de problème de façon statique, sans avoir besoin d’exécuter le code :

<?xml version="1.0"?>
<ruleset name="Mon Extension">
    <rule ref="WordPress-Extra">
        <exclude name="WordPress.Files.FileName" />
    </rule>
    <rule ref="WordPress.WP.I18n">
        <properties>
            <property name="text_domain" type="array">
                <element value="mon-extension" />
            </property>
        </properties>
    </rule>
</ruleset>

La propriété text_domain renseignée explicitement permet à PHPCS de signaler toute chaîne de traduction qui utiliserait un textdomain différent de celui déclaré, y compris un textdomain codé en dur mais simplement mal orthographié, l’erreur la plus fréquente sur les projets qui renomment leur extension en cours de vie.

L'essentiel à retenir : Un textdomain codé en dur casse silencieusement la traduction sur certains outils ; Les sniffs i18n de WPCS détectent la majorité des erreurs courantes ; Un .pot désynchronisé du code se détecte en comparant sa génération à chaque PR

Vérifier la cohérence du fichier .pot à chaque pull request

Un fichier .pot qui n’a pas été régénéré depuis plusieurs mois de développement actif devient rapidement obsolète : de nouvelles chaînes ajoutées au code n’y figurent pas, ce qui empêche les traducteurs de les traduire tant qu’ils ne s’appuient que sur ce fichier. La vérification consiste à régénérer le .pot dans le job de CI avec WP-CLI, puis à comparer son contenu à la version versionnée dans le dépôt :

wp i18n make-pot . languages/mon-extension.pot --exclude=vendor,node_modules
git diff --exit-code languages/mon-extension.pot

Si la commande git diff --exit-code détecte une différence, le job échoue et signale explicitement que le fichier .pot versionné n’est plus synchronisé avec le code, ce qui invite le contributeur à le régénérer et à l’inclure dans sa pull request avant la fusion.

Attention aux chaînes concaténées, invisibles pour les outils

Un autre piège classique, moins lié au textdomain qu’à la structure même de la chaîne : découper une phrase en plusieurs appels à __() concaténés rend la traduction impossible dans les langues dont l’ordre des mots diffère du français ou de l’anglais.

// À éviter : structure de phrase figée, intraduisible correctement
echo __( 'Vous avez', 'mon-extension' ) . ' ' . $nombre . ' ' . __( 'articles en attente', 'mon-extension' );

// Préférable : une seule chaîne avec espace réservé
printf(
    /* translators: %d: nombre d'articles en attente */
    esc_html__( 'Vous avez %d articles en attente', 'mon-extension' ),
    $nombre
);

Le sniff WordPress.WP.I18n signale également l’absence de commentaire translators: devant un espace réservé, un commentaire pourtant essentiel pour qu’un traducteur comprenne ce que représente chaque %d ou %s sans avoir à lire le code source environnant.

Intégrer le contrôle complet dans le pipeline

  • Exécuter PHPCS avec le jeu de règles i18n configuré sur chaque pull request touchant au code PHP
  • Régénérer le .pot et comparer son contenu à la version versionnée, en échec bloquant si différence
  • Ajouter, en documentation interne courte, la liste des fonctions de traduction autorisées (__(), _e(), _n(), esc_html__()) pour éviter que de nouveaux contributeurs réinventent un mécanisme maison

Une extension qui se targue d’être traduite en douze langues, mais dont un tiers des chaînes récentes n’apparaît même pas dans le fichier de traduction, ne tient pas vraiment cette promesse : le contrôle automatisé est ce qui la rend vraie dans la durée.

En résumé

L’internationalisation d’une extension WordPress se dégrade silencieusement si personne ne la contrôle activement : un textdomain mal écrit ou un .pot qui prend du retard ne cassent rien de visible pour l’équipe de développement elle-même. Les sniffs i18n de WordPress Coding Standards, couplés à une comparaison automatisée du fichier .pot à chaque pull request, transforment ce risque diffus en un contrôle explicite et bloquant, pour un coût de mise en place de quelques lignes de configuration.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi