RGAA Lab

Composants accessibles

La langue de la page

L'attribut lang choisit la voix qui lit la page. Sans lui, un texte français est prononcé avec les règles de l'anglais — et devient inintelligible. Démo, code, critères RGAA.

4 critères RGAA en jeu

Essayez-le

Ce paragraphe est en français, et le conteneur qui le porte le déclare. La phrase qui suit ne l'est pas : A page without a language attribute is read with the wrong voice.

Le reste du paragraphe cite Tim Berners-Lee, parle du week-end, donne une adresse — contact@example.org — et mentionne le livre Inclusive Design Patterns, qui porte, lui, son attribut.

Inspectez d’abord : chaque passage affiche la langue dans laquelle il sera restitué, résolue comme le fait un lecteur d’écran — la sienne, ou celle du premier parent qui en déclare une. Basculez ensuite la citation, réinspectez : le constat change parce que le document a changé, pas parce qu’un texte l’annonce. Et si votre système a une voix anglaise installée, faites lire la citation avant et après la bascule — c’est là que l’attribut s’entend.

Cette démo existe aussi en page autonome.

Ce que la déclaration commande

lang n’a aucun effet visible, et c’est ce qui le rend facile à oublier. Il commande la restitution : une synthèse vocale choisit sa voix et ses règles de prononciation d’après la langue déclarée, et n’a aucun autre moyen de la deviner. « Content » ne se prononce pas pareil des deux côtés de la Manche, et « poisson » lu avec des règles anglaises ne ressemble plus à rien.

Il sert aussi ailleurs, sans qu’on l’ait demandé : la césure automatique (hyphens: auto), les guillemets de <q>, le sélecteur CSS :lang(), la proposition de traduction du navigateur, l’indexation. Un seul attribut, posé une fois, et cinq comportements corrects.

L’erreur courante

Le gabarit d’origine, gardé tel quel : html lang="en" en tête d’un site entièrement français. La page est française, la déclaration ne l’est pas.

C’est le défaut le plus fréquent de ce thème, et le plus silencieux : la page valide, s’affiche bien, passe les contrôles automatiques de balisage — et se lit avec une voix anglaise du premier au dernier mot. Le critère 8.3 est satisfait (la langue est présente), c’est le 8.4 qui échoue, sur la pertinence.

Trois variantes coûtent la même chose :

  • lang="", produit par un gabarit qui interpole une variable de langue non renseignée. Une valeur vide vaut absence, et la préproduction, où la variable est peuplée, ne le montre pas.
  • lang sur body au lieu de html. Le titre de la page, annoncé avant l’entrée dans le corps, reste hors de portée de la déclaration.
  • Une citation entière non signalée. Un paragraphe d’anglais dans une page française est prononcé avec des règles françaises : ce n’est plus de l’anglais approximatif, c’est une suite de sons.

Et l’erreur inverse existe : lang="fr" posé sur un conteneur qui englobe aussi la colonne anglaise d’à côté. Le code est valide, sa portée est fausse — c’est le critère 8.8 qui le relève.

Le code, pas à pas

1. La langue par défaut, sur html

L’attribut se pose sur l’élément racine du document : html lang="fr", juste après le <!doctype html>. Une ligne, et toute la page en hérite — le <title> compris, qui est annoncé avant que le lecteur d’écran entre dans le corps.

Le référentiel admet une seconde voie — la langue indiquée texte par texte, ou par des parents qui les couvrent tous — mais elle demande de vérifier qu’aucun contenu n’y échappe. L’attribut sur html est la seule forme qui se contrôle d’un coup d’œil.

2. Un code valide, et pertinent

Trois valeurs correctes pour une page française : fr, suffisant et souvent le meilleur choix ; fr-FR, le français de France ; fr-CA, le français du Canada — une autre voix, un autre vocabulaire.

Deux conditions distinctes, portées par un seul critère. Le test 8.4.1 les exige ensemble pour la page — « Le code de langue est valide ; Le code de langue est pertinent » — et le test 8.8.1 reprend les deux mots pour chaque changement de langue.

Valide : ce que le glossaire appelle un code de langue — « code de 2 caractères (ISO 639-1) ou 3 caractères (ISO 639-2 et suivants) » —, éventuellement suivi d’une option après un tiret (« code de langue »). français, fr_FR et FR fr n’en sont pas. La même entrée ajoute que « l’indication du code de langue ne concerne que la partie [code] avant le tiret » : ce qui suit le tiret est laissé à votre appréciation, et la casse n’a pas de valeur normative — FR-fr est valide. fr-FR reste la convention d’écriture, sans raison de s’en écarter.

Pertinent : la langue déclarée est celle du contenu majoritaire de la page — c’est ce point, et non le premier, qui manque au site français resté en lang="en".

3. Les changements de langue

<p>
	Le rapport reprend le titre
	<span lang="en">Inclusive Design Patterns</span>, publié en 2016.
</p>

<blockquote lang="en">
	<p>A page without a language attribute is read with the wrong voice.</p>
</blockquote>

L’attribut se pose sur l’élément qui contient le texte étranger, ou sur un de ses parents. Aucun élément particulier n’est requis : un <span> suffit pour un titre, un <blockquote> ou un <q> porte naturellement une citation.

Le piège est la portée. Un lang="en" sur un conteneur qui déborde du passage fait basculer du texte français vers la voix anglaise, et rien à l’écran ne le montre : cherchez [lang] dans l’inspecteur, et vérifiez ce que chaque attribut couvre réellement.

4. Les textes qu’on ne voit pas

<!-- Le changement de langue porte sur l'élément, pas sur la valeur -->
<a href="/en/" lang="en" title="Switch to English">English</a>
<img src="/affiche.png" alt="Nothing about us without us" lang="en" />

Un alt, un title, un aria-label sont du contenu comme le reste, et un lecteur d’écran les prononce. Le glossaire du référentiel le dit sans détour : « il n’est pas possible d’indiquer des changements de langue dans une valeur d’attribut elle-même, dans ce cas le changement de langue est indiqué sur l’élément qui contient l’attribut ». Et il ajoute que lorsque l’attribut mêle plusieurs langues, le critère est non applicable — voir « changement de langue » au glossaire.

Le cas le plus répandu est le sélecteur de langue : ses entrées sont écrites chacune dans sa propre langue, et chacune demande donc son lang.

<ul role="list">
	<li><a href="/en/" lang="en" hreflang="en">English</a></li>
	<li><a href="/de/" lang="de" hreflang="de">Deutsch</a></li>
</ul>

hreflang annonce la langue de la page visée, lang celle du texte du lien. Les deux sont utiles, et l’un ne remplace pas l’autre.

5. Ce qui n’appelle aucun lang

Le critère 8.7 prévoit ses propres exceptions, et les connaître évite de baliser la moitié d’une page. Le critère est non applicable pour un nom propre, pour un nom commun étranger présent dans le dictionnaire officiel de la langue de la page, pour un terme étranger soumis par un formulaire et rappelé dans la page, pour un passage dont la langue ne peut pas être déterminée, et pour une langue morte ou imaginaire sans interprétation vocale.

« Week-end » figure au dictionnaire de l’Académie française : rien à déclarer. « Newsletter » n’y figure pas mais est passé dans le langage commun, et le référentiel tranche par l’oreille — le critère s’applique uniquement lorsque l’absence d’indication de langue peut provoquer une incompréhension pour la restitution. Une adresse électronique, elle, relève du passage dont la langue ne se détermine pas.

Le doute se lève en écoutant : si le mot reste reconnaissable prononcé à la française, laissez-le.

6. Quand la page change de langue sans recharger

// Une navigation côté client ne repasse pas par le serveur :
// c'est au routeur de tenir l'attribut à jour.
document.documentElement.lang = locale;

Une application à navigation côté client rend son html une fois, au premier chargement. Passer du français à l’anglais sans toucher document.documentElement.lang laisse toute l’interface anglaise déclarée en français — un défaut qui n’existe que pendant la session, donc invisible pour qui vérifie le code source servi.

Au clavier

Une déclaration de langue n’est pas interactive : elle n’entre dans aucun ordre de tabulation et ne s’actionne pas. Sa vérification appartient au lecteur d’écran, dont voici les commandes utiles.

ToucheEffet
TabNe s’arrête sur rien ici — sauf sur les liens d’un sélecteur de langue, qui sont des liens comme les autres.
Insert + NVDA et JAWS : lecture continue de la page. C’est le moyen le plus rapide d’entendre un changement de langue manquant.
Ctrl + + AVoiceOver : même lecture continue, à partir du curseur.
Insert + Ctrl + VNVDA : ouvre les paramètres de voix, où se règle le changement automatique de langue. Il doit être actif pour que le contrôle ait un sens.

Ce que le lecteur d’écran restitue

Rien n’est annoncé : la voix change, c’est tout. Sur une page correcte, le texte français est lu par une voix française, et la citation anglaise bascule le temps de la phrase — « A page without a language attribute is read with the wrong voice » prononcé en anglais, puis retour au français. Cette bascule est toute la restitution, et elle n’est pas garantie : elle suppose que le changement automatique de langue soit actif dans le lecteur et que la voix de la langue visée soit installée sur le système. C’est ce que vérifie le diagnostic qui suit.

Si tout est lu avec le même accent, trois causes possibles, à écarter dans cet ordre : le changement automatique de langue est désactivé dans le lecteur, la voix de la langue en question n’est pas installée sur le système, ou le lang manque. Vérifiez les deux premières sur un passage dont vous êtes sûr avant de conclure à un défaut de la page.

Et si toute la page est lue avec une voix étrangère dès le titre, ce n’est pas un changement de langue qui manque : c’est le lang de html.

Checklist

  • lang sur html, jamais sur body, et jamais vide.
  • Un code de langue valide (fr, fr-FR) et pertinent : celui du contenu majoritaire.
  • Chaque passage en langue étrangère porte son lang, et rien de plus que lui.
  • Les alt, title et aria-label étrangers : le lang va sur l’élément.
  • Chaque entrée d’un sélecteur de langue écrite dans sa langue.
  • Noms propres et mots du dictionnaire : rien à déclarer.
  • Une navigation côté client met à jour document.documentElement.lang.

Les critères RGAA en jeu

  • Critère 8.3 — Langue par défaut

    Sans langue déclarée, la synthèse vocale applique les règles de prononciation de sa voix par défaut : un site français lu par une voix anglaise n'est pas seulement pénible, il est incompréhensible.

  • Critère 8.4 — Pertinence du code de langue

    Un code invalide comme « français » ou « fr_FR » ne déclare rien, et un code valide mais faux — l'anglais laissé par le gabarit d'origine — est pire qu'une absence : la voix se trompe avec assurance.

  • Critère 8.7 — Changements de langue indiqués

    Une citation, un titre d'œuvre ou une entrée de sélecteur de langue écrits dans une autre langue doivent porter leur propre indication de langue, sinon ils sont prononcés avec les règles de la langue par défaut.

  • Critère 8.8 — Code des changements de langue

    Un changement de langue signalé avec le mauvais code, ou posé sur un conteneur trop large, fait basculer vers une prononciation qui n'est celle d'aucune des deux langues.

Vérifiez votre composant avec l'extension

Pour aller plus loin

Sources