O que o 3.1.1 exige
O idioma padrão de cada página web pode ser determinado programaticamente.
Texto original, em inglês (WCAG 2.1)
The default human language of each web page can be programmatically determined.
Com o lang certo no elemento html, leitores de tela carregam as regras de pronúncia certas, navegadores mostram caracteres e escritas corretamente e players exibem legendas direito. Com o errado, um leitor de tela lê uma página em português com as regras do inglês.
O idioma padrão é o mais usado. O Understanding 3.1.1 (em inglês) acrescenta que, quando vários idiomas aparecem na mesma medida, o padrão é o primeiro a aparecer. Trechos em outros idiomas são o 3.1.2.
O valor é uma tag de idioma BCP 47, como pt-BR, en ou es. Um jeito comum de errar é traduzir uma página a partir de um template e ficar com o lang do template.
Falhas comuns
Abaixo de cada exemplo: o que o axe-core e o Rampa relataram sobre a marcação de antes da correção, numa execução com o Gemma 4 12B em 8 de outubro de 2026.
Sem lang nenhum
Sem lang, o leitor de tela lê a página com a voz em que o aparelho estiver configurado, seja qual for o idioma do texto. Aqui as regras decidem: o axe-core reprova, e o Rampa relata isso sem perguntar a um modelo.
Antes, reprova no 3.1.1
<html>Depois, aprova
<html lang="pt-BR">- axe-core
Reprova:
html-has-lang.- Rampa
✗ html O elemento <html> deve ter um atributo 'lang' alta · regra html-has-lang
Um valor que não é tag de idioma
O lang recebe uma tag como pt-BR, não o nome do idioma. O axe-core também reprova isso.
Antes, reprova no 3.1.1
<html lang="portugues">Depois, aprova
<html lang="pt-BR">- axe-core
Reprova:
html-lang-valid.- Rampa
✗ html O elemento <html> deve ter um valor válido para o atributo 'lang' alta · regra html-lang-valid
Uma tag válida para o idioma errado
A página em português nasceu do template em inglês e ficou com lang="en". A tag é válida, então todas as regras passam, e o leitor de tela lê português com a pronúncia do inglês.
Antes, reprova no 3.1.1
<html lang="en">
…
<h1>Horário de funcionamento</h1>
<p>De segunda a sexta, das 7h às 18h.
Sábado, das 8h às 13h.</p>Depois, aprova
<html lang="pt-BR">- axe-core
Aprova: a
html-has-lange ahtml-lang-validencontram uma tag válida.- Rampa
✗ html A página está marcada como lang="en", mas a maior parte do texto está em português (pt). Evidência: "Horário de funcionamento De segunda a sexta, das 7h às 18h. Sábado, das 8h às 13h." Patch: - <html lang="en"> + <html lang="pt"> confiança alta · 1/1 rodadas · evidência verificada · id 1e93156072a4O patch propõe
pt, a tag principal;pt-BRacrescenta a região.
O que o axe-core verifica
O axe-core 4.14.0 mapeia três regras para o 3.1.1: a html-has-lang reprova página sem lang, a html-lang-valid, página cujo lang não é uma tag válida, e a html-xml-lang-mismatch, página em que lang e xml:lang discordam. O Rampa relata as falhas delas como estão, e uma página reprovada por qualquer uma nunca vai para o modelo.
| Regra | O que verifica | Mapeada para | Numa execução do Rampa |
|---|---|---|---|
html-has-lang, página da regra na Deque University, em inglês | O elemento <html> deve ter um atributo 'lang' | 3.1.1 | roda |
html-lang-valid, página da regra na Deque University, em inglês | O elemento <html> deve ter um valor válido para o atributo 'lang' | 3.1.1 | roda |
html-xml-lang-mismatch, página da regra na Deque University, em inglês | Elementos HTML com 'lang' e 'xml:lang' devem ter o mesmo idioma base | 3.1.1 | roda |
Nenhuma delas lê o texto. lang="en" numa página escrita em português passa nas três.
Cada regra leva à página dela na Deque University, a empresa que mantém o axe-core (em inglês).
O que o Rampa julga, e como
O que vai para o modelo
A página, uma vez: quando o elemento raiz declara um lang válido, nenhuma das três regras reprovou e pelo menos 12 letras de texto herdam esse idioma.
O que o modelo vê
- O idioma declarado.
- O texto que herda esse idioma, na ordem de leitura, até 1.500 caracteres. Trechos que declaram o próprio
langficam de fora, porque são o 3.1.2.
O que ele precisa responder
Um veredito, o idioma da maior parte do texto como tag principal BCP 47, um trecho curto copiado do texto como evidência e um grau de confiança.
O que derruba uma alegação
- O trecho não está no texto da página, tem menos de duas letras ou passa de 400 caracteres.
- O idioma detectado não é uma tag BCP 47 válida.
- Uma reprovação detecta o idioma declarado, ou uma aprovação detecta outro.
O patch
O lang do elemento raiz passa a ser a tag principal detectada, como es.
Em todo critério
- O conteúdo da página chega ao modelo marcado como dado, e o prompt manda ignorar qualquer instrução que esteja nele.
- As respostas ficam em cache por um hash do prompt, da imagem, do modelo e das configurações, então a mesma entrada nunca chama um modelo duas vezes.
- Com
--runs 3, o Rampa pergunta três vezes e fica com a maioria; quando as rodadas discordam, a confiança cai. Achados abaixo de--min-confidence(média por padrão) ficam ocultos, e o--verboselista todos. - Alegações derrubadas pela verificação são contadas em todo relatório, nunca mostradas como achados.
Como o Rampa foi medido nele
| Conjunto | Testa | Casos | axe-core, precisão / recall | Rampa, precisão / recall / F1 |
|---|---|---|---|---|
| 3.1.1, página tem lang válido (ACT b5c3f8, bf051a) | sintaxe | 11 | 1,00 / 1,00 | 1,00 / 1,00 / 1,00 |
| 3.1.1, lang confere com a página (ACT ucwvc8) | significado | 14 | 0,00 / 0,00 | 0,50 / 1,00 / 0,67 |
Pares corrompidos: o Rampa separou 4 de 4 (lang da página), o axe-core 0. Um par é uma página de teste que passa e uma cópia quebrada de propósito; quem dá o mesmo veredito às duas não está julgando.
Rodada em 9 de outubro de 2026: axe-core 4.14.0, Gemma 4 12B numa GPU local, raciocínio desligado, uma rodada, casos de teste ACT a9a1483e. Amostras pequenas e uma rodada só: leia os números como um pipeline que funciona, não como resultado.
Leia com estas ressalvas
- O julgamento do 3.1.1 chegou junto com o 2.4.2, o 2.4.4 e o 2.4.6 em 08/10/2026, e os prompts deles foram ajustados depois de ler os erros nestes casos, então os números são otimistas até páginas novas confirmarem.
- A precisão baixa no ucwvc8 é da contagem, não do julgamento. Todos os exemplos que passam e que reprovam estão certos; os falsos positivos são páginas que a regra chama de não aplicáveis, quatro delas reprovadas pelo axe-core por
langausente ou inválido.
Limitações
- Só um
langválido é julgado. Um ausente ou inválido é achado do axe-core. - O modelo lê até 1.500 caracteres do texto que herda o idioma da página, então uma página cujo começo difere do resto pode ser mal julgada.
- Páginas com menos de 12 letras de texto ficam de fora.
- Quando dois idiomas aparecem na mesma medida, a WCAG faz do primeiro o padrão; o modelo pode responder que não dá para dizer.
- O patch propõe só a tag principal, como
pt; acrescente a região se quiser. - Só páginas web: snapshots de apps não são julgados no 3.1.1.
Perguntas sobre o 3.1.1
Qual idioma o lang deve nomear numa página com dois idiomas?
O mais usado. O Understanding 3.1.1 diz que, quando os dois aparecem na mesma medida, o padrão é o primeiro a aparecer. Trechos no outro idioma ganham o próprio lang, que é o 3.1.2.
lang="pt" basta, ou precisa ser pt-BR?
O 3.1.1 pede que o idioma possa ser determinado por software, e uma tag principal como pt faz isso. Uma subtag de região como pt-BR acrescenta informação. O patch do Rampa propõe só a tag principal.
O axe-core verifica se o lang confere com o conteúdo?
Não. A html-has-lang verifica se o atributo existe, e a html-lang-valid, se o valor é uma tag válida. lang="en" numa página em português passa nas duas.
Verifique suas páginas
O Rampa ainda não está no npm. Clone e rode a partir do código, com Node.js 22.12 ou mais novo e Chrome ou Edge. O --criteria 3.1.1 julga só este critério; sem ele, rodam os oito que rodam por padrão.
Com o Ollama rodando, o Rampa escolhe um modelo local sozinho; o node dist/cli.mjs doctor diz o que falta.
git clone https://github.com/guilhermebsantiago/rampa-cli.git
cd rampa-cli
pnpm install && pnpm build
node dist/cli.mjs check https://example.com --criteria 3.1.1Conferido com o rampa-cli (commit 0459809) e as fontes do W3C em 9 de outubro de 2026.