« 1 articles trouvés. » Ce message, affiché en haut d’une page d’archive de thème, saute aux yeux de n’importe quel visiteur un peu attentif. Le développeur qui hérite du thème jure pourtant n’avoir rien codé de bizarre : la chaîne vient d’un fichier de traduction .po correctement chargé, avec une entrée française qui semble correcte. Le bug est ailleurs, dans la façon dont le compteur a été assemblé en amont.
Ce genre de coquille traîne souvent plusieurs mois sur un site avant d’être signalé, parce qu’elle ne casse rien visuellement : elle choque seulement l’œil, pas le navigateur. Elle révèle presque toujours la même cause profonde, une confusion entre gérer un pluriel et simplement traduire un mot.
Symptôme : un nombre suivi d’un mot toujours au pluriel
Dans le thème en cause, la fonction de comptage ressemblait à ceci avant correction :
$nombre = count( $articles );
echo sprintf(
__( '%d articles trouvés.', 'mon-theme' ),
$nombre
);
Avec un seul article, le message affiché est donc littéralement « 1 articles trouvés. », puisque la chaîne source ne contient qu’une seule forme, invariable, du mot « articles ». Le traducteur qui a rempli le fichier .po n’avait aucune marge de manœuvre : la chaîne anglaise d’origine ne proposait qu’une seule variante à traduire, déjà figée au pluriel.
Diagnostic : une seule chaîne là où il en faut deux
Le cœur du problème n’est pas la traduction, mais l’appel à __() plutôt qu’à la fonction dédiée aux pluriels, _n(). Cette fonction attend quatre arguments : la forme singulière source, la forme plurielle source, le nombre à évaluer, et le domaine de texte. Elle choisit ensuite la bonne forme en fonction des règles de pluriel définies pour la langue active, via le fichier de traduction chargé.
Pour le français, les règles de pluriel de gettext ne distinguent que deux formes : singulier pour zéro et un, pluriel au-delà. D’autres langues, notamment slaves ou arabes, définissent bien plus de catégories, mais ce n’est pas le sujet ici : dans un projet en français, il suffit de fournir ces deux formes pour que l’affichage soit correct dans tous les cas.
Correctif : remplacer __() par _n()

La correction consiste à fournir les deux formes explicitement, en laissant WordPress choisir :
$nombre = count( $articles );
echo sprintf(
_n(
'%d article trouvé.',
'%d articles trouvés.',
$nombre,
'mon-theme'
),
$nombre
);
Avec cette version, le fichier .po généré par un outil comme Poedit propose bien deux zones de traduction distinctes pour la même chaîne source, une pour le singulier et une pour le pluriel. Le traducteur peut alors écrire « 1 article trouvé. » et « 3 articles trouvés. » séparément, et la fonction choisit la bonne au moment de l’affichage selon la valeur de $nombre.
- Le troisième argument de
_n()doit toujours être un nombre, jamais une chaîne déjà formatée. - Les deux premiers arguments restent en anglais dans le code source, comme toute chaîne WordPress destinée à la traduction.
- Le domaine de texte doit correspondre exactement à celui déclaré lors du chargement des traductions du thème.
Prévention : repérer le motif au moment de la revue de code
Ce bug se repère facilement en relecture, une fois qu’on sait quoi chercher : toute chaîne contenant un mot au pluriel juste après un espace réservé à un nombre, du type '%d éléments', mérite une vérification. Si le mot ne change jamais de forme entre 0, 1 et 2, c’est probablement une occasion manquée d’utiliser _n().
Un test rapide et fiable consiste à forcer temporairement la valeur du compteur à 1 sur un environnement de développement, pour toutes les listes affichées sur le site : articles, commentaires, résultats de recherche, produits en stock. Si un seul message reste incorrect au singulier, il indique précisément l’endroit où __() a été utilisée à la place de _n().
En résumé
Une chaîne de caractères qui contient un nombre variable mérite presque toujours une fonction de pluriel plutôt qu’une simple traduction. Le symptôme est visuellement mineur, mais il trahit un thème mal préparé pour la traduction, ce qui devient vite gênant sur un site consulté par un public exigeant. Corriger ce genre de détail tôt évite d’avoir à repasser sur des dizaines de chaînes similaires une fois le thème déployé en production.