# Ajouter un hreflang technique fiable avec Polylang sur un WordPress multilingue

> Polylang génère le hreflang automatiquement, mais des erreurs de configuration le rendent silencieusement inutile. Voici comment le vérifier et le fiabiliser.

- Auteur : Clément Hadrot
- Publié le : 2023-11-23
- Mis à jour le : 2023-11-23
- Catégorie : SEO &amp; GEO
- URL : https://wpmoderne.dev.wordpress-developpement.fr/seo/hreflang-technique-polylang-wordpress/

## L’essentiel

- Vérifier la génération réelle des balises hreflang
- Corriger les langues non associées entre traductions
- Éviter les doublons causés par le cache

Un client gérait un site vitrine en français, anglais, espagnol et allemand avec Polylang. Sur le papier, tout semblait en ordre : le sélecteur de langue fonctionnait, chaque page avait sa traduction. Pourtant, la Search Console signalait des erreurs hreflang sur près d'un tiers des pages, avec des retours croisés incomplets entre l'allemand et l'espagnol.

Polylang gère l'essentiel du hreflang sans configuration supplémentaire, mais son automatisme repose entièrement sur la qualité des associations de traduction que l'équipe éditoriale a saisies à la main. Voici la procédure que nous suivons pour fiabiliser ce point sur chaque projet multilingue.

## Étape 1 : vérifier que Polylang génère bien les balises

Avant de corriger quoi que ce soit, il faut confirmer ce qui est réellement envoyé au navigateur. Sur une page publiée, on inspecte le code source et on cherche les balises `<link rel="alternate" hreflang="...">` dans le `<head>`.

```
<link rel="alternate" hreflang="fr" href="https://exemple.fr/produit/" />
<link rel="alternate" hreflang="en" href="https://exemple.fr/en/product/" />
<link rel="alternate" hreflang="es" href="https://exemple.fr/es/producto/" />
<link rel="alternate" hreflang="x-default" href="https://exemple.fr/product/" />
```

Si ces balises sont absentes, le problème vient presque toujours d'un thème qui appelle `wp_head()` trop tard, ou d'un plugin de cache qui sert une version figée de la page sans purge après modification des traductions.

## Étape 2 : contrôler les associations de traduction une par une

Le hreflang de Polylang se construit à partir des associations définies dans le module Langues de chaque contenu. Une page en anglais non reliée explicitement à sa version allemande ne recevra jamais la balise correspondante, même si les deux existent et sont publiées.

> L'essentiel à retenir : Vérifier la génération réelle des balises hreflang ; Corriger les langues non associées entre traductions ; Éviter les doublons causés par le cache

Pour auditer rapidement l'ensemble d'un site, on peut interroger directement le modèle de données de Polylang depuis un script exécuté en contexte WordPress :

```
$languages = pll_languages_list();
foreach ( get_posts( array( 'post_type' => 'page', 'numberposts' => -1 ) ) as $page ) {
    $current_lang = pll_get_post_language( $page->ID );
    foreach ( $languages as $lang ) {
        if ( $lang === $current_lang ) {
            continue;
        }
        $translation_id = pll_get_post( $page->ID, $lang );
        if ( ! $translation_id ) {
            echo "Page {$page->ID} ({$current_lang}) n'a pas de traduction en {$lang}\n";
        }
    }
}
```

Ce script liste toutes les pages orphelines de traduction dans au moins une langue. C'est là que se cachent la majorité des retours croisés incomplets signalés par Google.

## Étape 3 : gérer le cas particulier de la page d'accueil

La page d'accueil pose un piège classique : quand elle est définie comme page statique dans les réglages de lecture, Polylang doit recevoir une page d'accueil distincte par langue, associée dans son propre module de traduction. Oublier cette association produit un hreflang qui ne couvre que la langue par défaut, laissant les autres versions linguistiques sans URL alternative sur la page la plus visitée du site.

## Étape 4 : neutraliser les doublons créés par le cache

Sur ce projet, un plugin de cache de page conservait une version HTML statique générée avant l'ajout de la traduction allemande. Résultat : les visiteurs français voyaient un hreflang à trois langues quand les nouveaux visiteurs anglais, arrivant sur une page fraîchement mise en cache, en voyaient quatre. Google, qui explore à des moments différents, a fini par indexer les deux versions et signaler une incohérence.

- Vider systématiquement le cache de page après toute modification de traduction, pas seulement après une modification de contenu.
- Exclure les URL du sélecteur de langue de la variation de cache basée sur des cookies, pour éviter les doublons de fragment.
- Ajouter une purge automatique déclenchée par le hook `pll_save_post`, qui se déclenche à chaque sauvegarde de traduction.

## Étape 5 : valider avec un outil externe

Une fois les corrections appliquées, on croise toujours les résultats avec un validateur indépendant de Polylang, pour écarter tout biais de configuration interne. Le rapport « Ciblage international » de la Search Console reste la référence, complété par un contrôle manuel sur un échantillon de dix pages représentatives dans chaque langue.

> Un hreflang à moitié fiable est pire qu'une absence de hreflang : Google prend les signaux au sérieux et les retours croisés incomplets créent de la confusion sur la version canonique à afficher par pays.

## Pour aller plus loin

Polylang fait bien son travail tant que les associations de traduction sont complètes et que le cache ne triche pas. La vraie fiabilité ne vient pas du plugin, elle vient de la discipline éditoriale : chaque nouvelle page doit être immédiatement reliée à ses équivalents dans les autres langues, sinon le hreflang généré automatiquement restera, silencieusement, incomplet.
