# WordPress headless multilingue : Polylang et WPML avec WPGraphQL

> Exposer un site multilingue à un front découplé pose des questions que le multilingue classique ne pose pas : langues, traductions liées, menus par langue.

- Auteur : Clément Hadrot
- Publié le : 2022-04-04
- Mis à jour le : 2022-04-04
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/wordpress-headless-multilingue-polylang-wpml-wpgraphql/

## L’essentiel

- WPGraphQL for Polylang ajoute les champs de langue au schéma
- Récupérer les traductions liées d'un même contenu
- Construire le routage localisé côté front, pas côté WordPress

Un projet headless multilingue diffère d'un site WordPress classique multilingue sur un point essentiel : le routage par langue (préfixe d'URL, sous-domaine, ou domaine dédié) n'est plus géré par WordPress et l'extension de traduction, mais par le front lui-même. WordPress reste la source de vérité pour le contenu traduit, mais c'est au front de décider comment structurer les URL et de récupérer la bonne langue au bon moment.

Cet article couvre l'exposition des langues et traductions via WPGraphQL avec Polylang ou WPML, et la construction du routage localisé côté front. Il ne traite pas la configuration d'un site WordPress multilingue classique avec thème PHP, dont les mécanismes de routage intégrés (sous-répertoires générés automatiquement) ne s'appliquent pas de la même façon en headless.

## Polylang avec WPGraphQL for Polylang

L'extension WPGraphQL for Polylang ajoute au schéma GraphQL les champs nécessaires pour connaître la langue de chaque contenu et accéder à ses traductions liées :

```
query ArticleAvecTraductions($slug: ID!) {
  post(id: $slug, idType: SLUG) {
    title
    content
    language {
      code
      locale
    }
    translations {
      language {
        code
      }
      slug
    }
  }
}
```

Le champ `translations` renvoie la liste des versions traduites du même contenu, avec leur code de langue et leur slug propre — indispensable pour construire un sélecteur de langue qui pointe vers la bonne URL plutôt que de rediriger vers la page d'accueil traduite par défaut, une erreur fréquente sur les premiers projets multilingues headless que j'ai vus passer.

## WPML avec WPGraphQL for WPML

WPML suit un principe équivalent avec sa propre extension, WPGraphQL for WPML, dont le schéma diffère légèrement dans les noms de champs :

```
query ArticleWPML($id: ID!) {
  post(id: $id, idType: DATABASE_ID) {
    title
    language {
      code
      name
    }
    translations {
      code
      href
    }
  }
}
```

Une différence pratique entre les deux extensions : WPML expose directement un champ `href` dans `translations`, correspondant à l'URL WordPress native de la traduction, alors que Polylang expose plutôt un `slug` à recomposer soi-même. Cette différence influence directement la façon dont le front doit reconstruire ses propres routes.

## Construire le routage localisé côté front

> L'essentiel à retenir : WPGraphQL for Polylang ajoute les champs de langue au schéma ; Récupérer les traductions liées d'un même contenu ; Construire le routage localisé côté front, pas côté WordPress

Avec Next.js, l'internationalisation intégrée au routeur (préfixes de langue automatiques comme `/fr/...` et `/en/...`) se combine avec les données de langue récupérées via WPGraphQL, mais les deux restent des mécanismes distincts à synchroniser explicitement :

```
// next.config.js
module.exports = {
  i18n: {
    locales: ['fr', 'en'],
    defaultLocale: 'fr',
  },
};
```

```
// pages/[locale]/article/[slug].js
export async function getStaticProps({ params }) {
  const { post } = await requeteGraphQL(REQUETE_ARTICLE, {
    slug: params.slug,
    language: params.locale.toUpperCase(),
  });

  return { props: { post } };
}
```

Le préfixe de langue de l'URL Next.js et le code de langue transmis à la requête GraphQL doivent rester strictement synchronisés : une désynchronisation (par exemple un slug français demandé avec un code de langue anglais) renvoie généralement une réponse vide plutôt qu'une erreur explicite, ce qui complique le débogage si ce point n'est pas testé tôt.

## Exposer les menus par langue

Les menus de navigation suivent la même logique que le contenu : chaque langue dispose de son propre menu, enregistré séparément dans Polylang ou WPML. Côté WPGraphQL, le champ `language` s'applique aussi aux menus si l'extension de langue est bien compatible avec le type `Menu` du schéma :

```
query MenuParLangue($emplacement: MenuLocationEnum!, $langue: LanguageCodeFilterEnum!) {
  menus(where: { location: $emplacement, language: $langue }) {
    nodes {
      menuItems {
        nodes {
          label
          url
          path
        }
      }
    }
  }
}
```

## Gérer les contenus non traduits

Un contenu peut exister dans une langue sans avoir d'équivalent traduit dans une autre — un article de blog publié uniquement en français, par exemple. Le front doit gérer ce cas explicitement : soit en masquant le sélecteur de langue vers une traduction inexistante, soit en proposant un repli vers l'accueil de la langue cible plutôt qu'une erreur 404 brute.

| Situation | Comportement recommandé |
| --- | --- |
| Traduction existante | Lien direct vers le slug traduit |
| Pas de traduction pour ce contenu précis | Masquer l'option de langue, ou proposer l'accueil localisée avec un message explicite |

- Vérifier systématiquement que le champ `translations` n'est pas vide avant d'afficher un sélecteur de langue actif.
- Prévoir une page 404 localisée par langue, pas une 404 générique dans une seule langue par défaut.
- Tester le comportement du sitemap et des balises `hreflang` générées, un point souvent oublié dans les premiers déploiements multilingues headless.

> Sur un projet multilingue, je considère la synchronisation entre le préfixe d'URL du front et le code de langue transmis à l'API comme le point de fragilité numéro un : une bonne partie des bugs multilingues que j'ai corrigés venaient d'un décalage silencieux entre les deux, jamais signalé par une erreur explicite.

## En résumé

WPGraphQL for Polylang et WPGraphQL for WPML exposent tous deux les langues et traductions liées au schéma GraphQL, avec des noms de champs légèrement différents selon l'extension utilisée. Le routage localisé reste entièrement à la charge du front, qui doit maintenir une synchronisation stricte entre son propre système de préfixes de langue et les codes de langue transmis à chaque requête.
