O que o 3.1.2 exige
O idioma de cada passagem ou frase no conteúdo pode ser determinado programaticamente, exceto para nomes próprios, termos técnicos, palavras de idioma indeterminado e palavras ou frases que se tornaram parte do vernáculo do texto que as envolve.
Texto original, em inglês (WCAG 2.1)
The human language of each passage or phrase in the content can be programmatically determined except for proper names, technical terms, words of indeterminate language, and words or phrases that have become part of the vernacular of the immediately surrounding text.
Uma citação, uma avaliação ou o nome de um idioma escrito em outra língua precisa do próprio lang, para que sintetizadores de voz pronunciem com as regras certas e softwares de braille traduzam corretamente. Uma única palavra pode contar quando a troca de idioma é intencional.
As exceções mantêm isso prático: nomes próprios, termos técnicos, palavras de idioma indeterminado e palavras que viraram parte do idioma ao redor. O Understanding 3.1.2 (em inglês) dá como exemplos “rendezvous” em inglês e “podcast” em francês.
Um lang errado é um problema à parte: o leitor de tela troca para uma voz que lê o trecho com as regras de outro idioma.
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.
Um trecho marcado com o idioma errado
Uma avaliação em alemão foi marcada como francês. O leitor de tela troca para o francês e lê palavras alemãs com regras francesas. A tag é válida, então as regras passam.
Antes, reprova no 3.1.2
<blockquote lang="fr">
<p>Die Lieferung kam einen Tag früher
als angekündigt.</p>
</blockquote>Depois, aprova
<blockquote lang="de">
…
</blockquote>- axe-core
Aprova: a
valid-langencontra uma tag válida.- Rampa
✗ html > body > main > blockquote Marcado como lang="fr", mas o texto está em alemão (de). Evidência: "Die Lieferung kam einen Tag früher als angekündigt." Patch: - <blockquote lang="fr"> + <blockquote lang="de"> confiança alta · 1/1 rodadas · evidência verificada · id d0eb6daacd91
Uma frase em outro idioma sem lang
O lema está em inglês numa página em português, sem lang, então é lido com as regras do português. Nenhuma das ferramentas percebe: o axe-core não tem tag para verificar, e o Rampa só julga elementos que declaram um idioma.
Antes, reprova no 3.1.2
<p>O lema da nossa fundadora:
<q>Made by hand, slowly and with care.</q></p>Depois, aprova
<p>O lema da nossa fundadora:
<q lang="en">Made by hand, slowly and with care.</q></p>- axe-core
Aprova: não há
langpara verificar.- Rampa
O Rampa não relatou nada aqui. Achar trechos que não têm
langainda não foi feito.
Uma tag com o separador errado
Tags de idioma usam hífen: en-US, não en_US. O axe-core reprova a tag inválida, e o Rampa relata isso sem perguntar a um modelo.
Antes, reprova no 3.1.2
<p lang="en_US">We ship worldwide.</p>Depois, aprova
<p lang="en-US">We ship worldwide.</p>- axe-core
Reprova:
valid-lang.- Rampa
✗ html > body > main > p:nth-of-type(2) O atributo 'lang' deve ter um valor válido alta · regra valid-lang
O que o axe-core verifica
O axe-core 4.14.0 mapeia uma regra para o 3.1.2: a valid-lang, que reprova valor de lang que não é uma tag de idioma válida. O Rampa relata as falhas dela como estão, e um elemento reprovado por ela nunca vai para o modelo.
| Regra | O que verifica | Mapeada para | Numa execução do Rampa |
|---|---|---|---|
valid-lang, página da regra na Deque University, em inglês | O atributo 'lang' deve ter um valor válido | 3.1.2 | roda |
A regra não lê o texto. Uma avaliação em alemão marcada com lang="fr" passa, e um trecho sem lang nenhum também.
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
Todo elemento, fora a raiz, que declara um lang válido, não está oculto, não foi reprovado pela valid-lang e tem pelo menos quatro letras de texto que herdam esse idioma.
O que o modelo vê
- O idioma declarado e o idioma herdado do que está em volta do elemento.
- A marcação do elemento, até 800 caracteres.
- O texto que herda o idioma declarado, na ordem de leitura, até 1.200 caracteres, com os nomes das imagens vindos de
alte dearia-labelledby.
O que ele precisa responder
Um veredito, o idioma do texto como tag principal BCP 47, um trecho curto copiado como evidência, qual exceção do 3.1.2 se aplica (nome próprio, termo técnico, palavras de idioma indeterminado, vernáculo do texto ao redor ou nenhuma) e um grau de confiança.
O que derruba uma alegação
- O trecho não está no texto do elemento, 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 alega que uma exceção se aplica.
- Uma aprovação detecta outro idioma sem alegar exceção.
O patch
O lang do elemento passa a ser a tag principal detectada, como de.
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.2, lang válido em trechos (ACT de46e4) | sintaxe | 19 | 1,00 / 1,00 | 1,00 / 1,00 / 1,00 |
| 3.1.2, lang confere com o texto (ACT off6ek) | significado | 13 | não definida, nada apontado / 0,00 | 0,80 / 1,00 / 0,89 |
Pares corrompidos: o Rampa separou 4 de 5 (lang em trechos), 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
- A primeira rodada, em 07/10/2026, teve recall 0,75 no off6ek. Os erros nunca chegaram a um modelo, porque o Rampa não contava como texto os nomes de imagem vindos de
aria-labelledby; com isso corrigido, o recall é 1,00. - O único par que o Rampa não separou é uma página intacta que ele também reprova: “Paul put dire comment on tape”, uma frase que é inglês e francês ao mesmo tempo. Em 1.1.1 e 3.1.2, os erros de modelo tanto do Gemma quanto do
openai:gpt-6-lunacaíram nessa frase. - Em 1.1.1 e 3.1.2, o
openai:gpt-6-lunateve os mesmos números do Gemma em duas rodadas com chamadas novas, por cerca de US$ 0,005 cada.
Limitações
- Só elementos que declaram
langsão julgados. Um trecho em outro idioma semlangnenhum não é encontrado, nem pelo Rampa nem pelo axe-core. - Texto com menos de quatro letras fica de fora, assim como elementos ocultos.
- Uma frase que mistura dois idiomas é difícil para um modelo, como mostram as ressalvas acima.
- O patch propõe só a tag principal, como
de. - Só páginas web: snapshots de apps não são julgados no 3.1.2.
Perguntas sobre o 3.1.2
Nomes próprios e estrangeirismos precisam de lang?
Não. O 3.1.2 exclui nomes próprios, termos técnicos, palavras de idioma indeterminado e palavras que viraram parte do idioma ao redor, como “rendezvous” em inglês. O Rampa pergunta ao modelo qual exceção se aplica, e uma aprovação apoiada numa exceção é aceita.
O Rampa acha trechos estrangeiros sem lang?
Ainda não. Ele só julga elementos que declaram um idioma, então uma citação em outra língua sem o atributo lang passa despercebida, como no axe-core.
O axe-core verifica o idioma das partes?
Verifica se cada valor de lang é uma tag válida (valid-lang). Uma tag válida num texto em outro idioma passa.
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.2 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.2Conferido com o rampa-cli (commit 0459809) e as fontes do W3C em 9 de outubro de 2026.