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.

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, documentée par la MDN.
- Une page multilingue avec des passages dans une autre langue doit aussi utiliser
langsur les éléments concernés, pas seulement sur<html>. - Un attribut
langvide 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
langtout 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.