O que o 3.1.1 exige

O idioma padrão de cada página web pode ser determinado programaticamente.

Critério de sucesso 3.1.1 Idioma da Página (Nível A), citado da tradução autorizada para o português do Brasil das Diretrizes de Acessibilidade para Conteúdo Web (WCAG) 2.2, publicada em 27 de março de 2025 pelo Ceweb.br. Copyright © 2020-2023 World Wide Web Consortium. Usado sob a Licença de Documentos do W3C. A WCAG 2.1 não tem tradução autorizada, e este critério tem o mesmo texto na 2.1 e na 2.2. Em caso de divergência, vale o original em inglês.
Texto original, em inglês (WCAG 2.1)

The default human language of each web page can be programmatically determined.

Web Content Accessibility Guidelines (WCAG) 2.1, Recomendação do W3C de 6 de maio de 2025. Copyright © 2020-2025 World Wide Web Consortium.

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.

Regras ACT do 3.1.1

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-lang e a html-lang-valid encontram 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 1e93156072a4

O patch propõe pt, a tag principal; pt-BR acrescenta 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.

Regras do axe-core 4.14.0 para o 3.1.1
RegraO que verificaMapeada paraNuma execução do Rampa
html-has-lang, página da regra na Deque University, em inglêsO elemento <html> deve ter um atributo 'lang'3.1.1roda
html-lang-valid, página da regra na Deque University, em inglêsO elemento <html> deve ter um valor válido para o atributo 'lang'3.1.1roda
html-xml-lang-mismatch, página da regra na Deque University, em inglêsElementos HTML com 'lang' e 'xml:lang' devem ter o mesmo idioma base3.1.1roda

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 lang ficam 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 --verbose lista todos.
  • Alegações derrubadas pela verificação são contadas em todo relatório, nunca mostradas como achados.

Como o Rampa foi medido nele

Casos de teste ACT do W3C para o 3.1.1: precisão, recall e F1, com o Gemma 4 12B numa GPU local
ConjuntoTestaCasosaxe-core, precisão / recallRampa, precisão / recall / F1
3.1.1, página tem lang válido (ACT b5c3f8, bf051a)sintaxe111,00 / 1,001,00 / 1,00 / 1,00
3.1.1, lang confere com a página (ACT ucwvc8)significado140,00 / 0,000,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 lang ausente ou inválido.

Método e análise de erros no README (em inglês)

Limitações

  • Só um lang vá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.1

Conferido com o rampa-cli (commit 0459809) e as fontes do W3C em 9 de outubro de 2026.