# Attribut lang HTML : ce que WordPress ne fait pas automatiquement en multilingue

> Un audit d'accessibilité a pointé un attribut lang incohérent sur un site traduit. Voici ce que le cœur de WordPress gère seul, et ce qu'il faut ajouter.

- Auteur : Clément Hadrot
- Publié le : 2020-01-24
- Mis à jour le : 2020-01-24
- Catégorie : Multilingue
- URL : https://wpmoderne.dev.wordpress-developpement.fr/multilingue/attribut-lang-html-multilingue-wordpress/

## L’essentiel

- L'attribut lang du <html> suit la langue du site, pas celle de la page affichée
- Un plugin multilingue doit réécrire cet attribut par requête
- Sans correction, les lecteurs d'écran appliquent la mauvaise prononciation

Un client m'a transféré un rapport d'audit d'accessibilité la semaine dernière : parmi la dizaine de points bloquants, un seul concernait directement WordPress. La balise `<html lang="fr-FR">` restait affichée telle quelle sur les pages traduites en anglais et en néerlandais. Un lecteur d'écran configuré en anglais prononçait donc chaque mot avec une phonétique française, rendant le contenu incompréhensible pour l'utilisateur malvoyant qui avait signalé le problème.

Ce cas illustre une confusion fréquente chez les développeurs qui découvrent le multilingue : WordPress gère très bien la langue de l'interface d'administration et la locale de certaines chaînes système, mais il ne sait absolument rien faire tout seul concernant la langue affichée à un visiteur sur une page traduite. C'est entièrement la responsabilité de l'extension multilingue installée, et toutes ne le font pas avec le même soin.

## Ce que le cœur de WordPress gère réellement

WordPress détermine la valeur de l'attribut `lang` à partir d'un seul réglage : la langue générale du site, définie dans **Réglages > Général** et stockée dans l'option `WPLANG` (ou `siteurl` pour la locale par défaut). Cette valeur est injectée par la fonction `get_bloginfo( 'language' )`, elle-même appelée dans le fichier `header.php` du thème actif, généralement ainsi :

```
<html language_attributes() >
```

La fonction `language_attributes()` lit la locale globale active au moment du rendu de la page. Si aucune extension ne modifie cette locale en cours de requête, elle reste figée à la valeur définie dans les réglages généraux, quelle que soit la langue du contenu réellement affiché. C'est exactement le comportement qui a fait échouer l'audit RGAA de mon client : le site avait été configuré en français par défaut, et rien ne changeait cette valeur sur les URL `/en/` ou `/nl/`.

## Pourquoi les plugins multilingues doivent intervenir

Un plugin multilingue sérieux doit accrocher un filtre ou une action très tôt dans le cycle de requête pour changer la locale WordPress avant que le thème ne génère le `<head>`. Polylang, par exemple, détermine la langue de la page à partir de l'URL ou du contenu demandé, puis appelle `switch_to_locale()` pour que toutes les fonctions qui dépendent de la locale, dont `get_locale()` et donc indirectement `language_attributes()`, reflètent la bonne langue.

> L'essentiel à retenir : L'attribut lang du <html> suit la langue du site, pas celle de la page affichée ; Un plugin multilingue doit réécrire cet attribut par requête ; Sans correction, les lecteurs d'écran appliquent la mauvaise prononciation

WPML procède différemment en interne, mais le résultat visible doit être identique : la balise `<html>` doit porter le code de langue exact de la page consultée, avec si possible la variante régionale (`en-US` plutôt qu'un simple `en` quand cela a du sens pour le site).

### Le format attendu par les standards

La spécification HTML autorise deux formes : un code de langue simple (`fr`, `en`, `ar`) ou une combinaison langue-région (`fr-FR`, `fr-CA`, `en-GB`). Les recommandations d'accessibilité, dont le RGAA français et les WCAG, exigent que cette valeur corresponde exactement à la langue principale du contenu de la page, sans quoi les technologies d'assistance ne peuvent pas choisir le bon moteur de synthèse vocale ni la bonne base de règles de césure.

- Le code doit suivre la norme [BCP 47](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/lang), documentée par la MDN.
- Une page multilingue avec des passages dans une autre langue doit aussi utiliser `lang` sur les éléments concernés, pas seulement sur `<html>`.
- Un attribut `lang` vide ou absent est pire qu'une valeur incorrecte : il empêche toute inférence par le navigateur.

## Vérifier concrètement sur un site en production

Le diagnostic ne demande aucun outil compliqué. Il suffit d'afficher le code source de chaque version linguistique et de comparer la valeur de l'attribut `lang` avec la langue réellement affichée à l'écran. Sur un site utilisant Polylang, j'ajoute systématiquement ce test manuel à ma recette de mise en production, juste après avoir vérifié les redirections 301 :

```
curl -s https://exemple.fr/en/ | grep -o '<html[^>]*>'
```

Si la sortie affiche autre chose que `lang="en-US"` ou une variante cohérente, le thème actif contourne probablement `language_attributes()` avec une balise `<html>` statique codée en dur, ou bien un plugin de cache sert une page mise en cache avant que la locale n'ait été appliquée. J'ai déjà rencontré ce second cas avec un cache de page trop agressif qui servait la version anglaise avec l'attribut `lang` français resté figé depuis la première génération du cache.

## Les pièges les plus fréquents en pratique

Trois situations reviennent régulièrement lors de mes audits chez des clients multilingues. La première concerne les thèmes premium achetés sur des marketplaces qui codent en dur `<html lang="en-US">` dans leur fichier `header.php`, en écrasant purement et simplement l'appel à la fonction native. La seconde touche les pages générées par des constructeurs de pages qui insèrent leur propre balise de démarrage sans passer par les hooks WordPress. La troisième, plus insidieuse, vient d'un cache statique généré côté serveur qui fige la première version rendue de la page sans distinguer les variantes de langue dans sa clé de cache.

> Sur chaque nouveau projet multilingue, je place la vérification de l'attribut `lang` tout en haut de ma checklist de recette, avant même de tester les liens hreflang : c'est un correctif de trente secondes qui évite un rapport d'audit entier à refaire.

## En résumé

WordPress ne fait rien de spécial pour l'attribut `lang` au-delà de refléter la locale globale du site au moment du rendu. Sur un site monolingue, cela suffit largement. Sur un site multilingue, c'est entièrement à l'extension de traduction, à la configuration du cache et parfois au thème de garantir que cette valeur change réellement d'une version linguistique à l'autre. Un test `curl` de trente secondes par langue publiée suffit à repérer le problème avant qu'un audit externe ne le fasse à votre place.
