Le WordPress d'aujourd'hui, décodé pour les développeurs

Multilingue

Un slug traduit entre en collision avec sa version dans une autre langue

Sur un site de recrutement bilingue, la version française d'une offre d'emploi s'affiche sous l'URL anglaise. Diagnostic d'une collision de slug et correctif durable.

Par WordPress Développement • 11 décembre 2023 • 4 min de lecture • Aucun commentaire
Un slug traduit entre en collision avec sa version dans une autre langue

wp_unique_post_slug : c’est cette fonction cœur qui décide, pour chaque article publié, si un slug est déjà pris. Sur un site de recrutement traduit en anglais et en français avec Polylang, une conseillère RH signale un comportement étrange : l’offre /offre-consultant-senior/ affiche systématiquement le texte anglais, même quand le sélecteur de langue indique le français.

Le symptôme est net une fois qu’on regarde les deux fiches dans l’administration : la version française porte en réalité le slug offre-consultant-senior-2, mais le lien partagé sur les réseaux pointait vers le slug sans suffixe, donc vers la traduction anglaise. Une collision de slug entre deux langues, silencieuse, qui a fini par tromper tout le monde.

Symptôme : deux traductions, un seul slug propre

Dans WordPress, l’unicité d’un slug se calcule par type de contenu et par parent, indépendamment de toute notion de langue : le cœur ne connaît pas Polylang. Sans intervention, créer une traduction avec le même titre générerait donc automatiquement un slug numéroté (-2, -3…), ce qui casserait l’intérêt même d’une URL localisée.

Polylang corrige ce point depuis longtemps en accrochant un filtre sur wp_unique_post_slug qui autorise un slug identique entre deux posts si leurs langues respectives diffèrent. En temps normal, /en/consultant-senior/ et /consultant-senior/ coexistent sans souci.

Où le filtre casse

Le cas décrit ici vient d’un thème maison qui ajoutait, lui aussi, un filtre sur wp_unique_post_slug pour gérer un ancien système de sous-marques, avec une priorité plus basse que celle de Polylang. Résultat : le filtre du thème renvoyait un slug déjà « nettoyé » avant que Polylang ait pu appliquer sa propre exception linguistique, et WordPress retombait sur son comportement par défaut : suffixer la deuxième publication rencontrée.

L'essentiel à retenir : wp_unique_post_slug ignore les langues par défaut ; Polylang filtre ce comportement, un conflit de priorité le casse ; Un slug -2 signale presque toujours ce problème

Diagnostic : remonter la chaîne de filtres

Trois vérifications suffisent à confirmer l’hypothèse :

  • Lister les fonctions accrochées à wp_unique_post_slug avec wp eval 'var_dump($GLOBALS["wp_filter"]["wp_unique_post_slug"]);' en WP-CLI, pour voir l’ordre des priorités.
  • Vérifier dans la table wp_posts que le champ post_name de la traduction française contient bien un suffixe numérique inattendu.
  • Contrôler la table wp_term_relationships associée à la taxonomie de langue Polylang (language) pour confirmer que les deux articles sont correctement rattachés chacun à leur langue.

Une fois la liste des filtres obtenue, la priorité du filtre maison apparaît clairement inférieure à celle de Polylang, qui s’exécute par défaut avec une priorité de 20 sur ce hook précis dans les versions récentes du plugin.

Correctif : réordonner puis régénérer les slugs propres

La correction se fait en deux temps. D’abord, on relève la priorité du filtre maison au-delà de celle de Polylang, ou mieux, on fusionne sa logique dans le filtre existant plutôt que d’en ajouter un concurrent :

add_filter( 'wp_unique_post_slug', function ( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
    // Logique maison de sous-marques, appliquée après Polylang.
    return apply_sous_marque_slug( $slug, $post_ID, $original_slug );
}, 25, 6 );

Ensuite, il faut régénérer manuellement le slug de chaque article touché : renommer temporairement le champ post_name avec une valeur neutre, puis relancer l’enregistrement de l’article pour que la chaîne de filtres, désormais correcte, recalcule un slug propre sans suffixe.

Vérifier les redirections existantes

Comme l’ancien slug numéroté a probablement été indexé, une redirection 301 de offre-consultant-senior-2 vers offre-consultant-senior (dans la bonne langue) évite de perdre le référencement acquis pendant la période où le bug est passé inaperçu.

Prévention : ne jamais empiler des filtres de slug sans les auditer

Avant d’ajouter un nouveau filtre sur wp_unique_post_slug, pre_wp_unique_post_slug ou un hook équivalent, il vaut mieux systématiquement vérifier ce qu’un plugin de traduction y a déjà déposé. Un audit rapide en WP-CLI, ajouté à la checklist de mise en production, évite ce genre de surprise silencieuse.

Un slug qui se termine par -2, -3 ou davantage mérite toujours une vérification : dans un contexte multilingue, ce n’est presque jamais un hasard de nommage, mais souvent un conflit de filtres.

En résumé

La collision de slug entre langues n’est pas un défaut de Polylang, mais la conséquence d’un filtre concurrent mal priorisé. Le réflexe à garder : chaque fois qu’un plugin ou un thème touche à wp_unique_post_slug, s’assurer que sa priorité respecte celle du plugin multilingue en place, et documenter ce choix pour l’équipe qui reprendra le projet plus tard.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

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

Voir tous ses articles

Dans la même veine

À lire aussi