Skip to content

Add Brazilian Portuguese (pt) translation- #729 - #736

Open
natalieac03 wants to merge 43 commits into
daisy:mainfrom
natalieac03:main
Open

Add Brazilian Portuguese (pt) translation- #729#736
natalieac03 wants to merge 43 commits into
daisy:mainfrom
natalieac03:main

Conversation

@natalieac03

Copy link
Copy Markdown

This PR adds a Brazilian Portuguese translation of the speech rules.

What's included

  • Complete translation of all 12 rule files (unicode.yaml, unicode-full.yaml,
    definitions.yaml, SimpleSpeak_Rules.yaml, ClearSpeak_Rules.yaml, the five
    SharedRules/ files, navigate.yaml, overview.yaml)
  • 142 tests in tests/Languages/pt/, all passing; full suite green (7307 passed)
  • Unicode coverage: 3557 codepoints

Method

The translation was originally seeded from Spanish, but every entry was
subsequently checked against the English reference rather than Spanish.
This turned out to matter: I found several entries in es/unicode.yaml that are
incorrect and marked T: (human-verified), e.g. " reads as barra inversa
(backslash) and ℂℕℚℝℤ reads as prima inversa, which is the value belonging
to U+2035. These read as correct Spanish, so a careful translator would carry
them over intact. I'm happy to open a separate issue for the Spanish file if
that's useful.

I also ported rules present in en/ but missing from es/ (and therefore from
pt/): repeating-decimal, zero/identity/diagonal matrix, laplacian,
coordinate, currency, exponential, covariance, dimension-by,
unit-terse, power-indexed-by, nofix-intent, and pause in SimpleSpeak.

Deliberate divergences from en/

These are marked with # audit-ignore and documented in
Rules/Languages/pt/ACHADOS.md:

  • 1x1-matrix and 1x1-determinant kept separate. English merges them; in
    Portuguese the articles differ in gender ("a matriz" / "o determinante"), which
    a merged rule can't express.
  • Style adjective is postposed. "maiúscula a vazado", not "vazado maiúscula a" — Portuguese places the qualifier after the noun.
  • Cardinal instead of ordinal for exponents and root indices. ToOrdinal()
    reads from a single masculine list, but the exponent context requires feminine
    agreement in Portuguese ("a quarta potência"). Using the cardinal form
    ("a potência 4") is gender-neutral and works in both contexts. Note this means
    ClearSpeak_Exponents = 'Ordinal' currently degrades to the same output as
    the default; a NumbersOrdinalOnesFeminine list would fix this properly, if
    you'd accept one.
  • Negations omit the copula. ≢ ≇ ∦ ⊈ ⊉ — in Portuguese "não é congruente a"
    is already a complete predicate, so the $Verbosity!='Terse'"is" branch
    would produce "é não é congruente a".

One upstream fix worth taking on its own

The interval rule in en/SharedRules/general.yaml builds its phrase by reading
the internal tag name and replacing hyphens with spaces, so
open-closed-interval becomes "open closed interval". This only works because
the tag names are English — every other language hears the English term. The
Portuguese version tests the interval type explicitly instead. I can split this
into a separate PR against en/ if you'd prefer.

Known limitations

  • unicode-full.yaml is complete but 19 entries remain t: (lowercase): the
    fraktur/script naming choice needs validation with a native speaker using a
    screen reader.
  • navigate.yaml predates commit 0107c89 and hasn't been migrated to the
    NavNodeOffset generation; the character-navigation rules are absent.
  • No listening validation with blind users yet. All verification so far is
    textual and structural.

natalieac03 and others added 30 commits August 7, 2026 17:57
cargo test Languages::pt saía de 33 falhas em 91 testes. Agora passa 92/92,
e a suíte inteira do repositório continua verde. Nada em src/ foi tocado.

Bugs de regra:

- SharedRules/general.yaml: a distinção Verbose/Medium tinha desabado na
  química. 14 pares de ramos diziam "subscrito"/"sobrescrito" nos dois
  níveis, onde o inglês tem subscript/sub. Um deles (ramo $Prescripts[4])
  dizia "subscrito" onde o inglês diz superscript.
- SharedRules/general.yaml: ligação dupla escrita "::" não era reconhecida.
  A regra testava .='::', mas o canonicalizador converte para ∷ (U+2237)
  antes de as regras rodarem, então H₂C::CH₂ saía "maiúsculo c, como
  maiúsculo c".
- unicode.yaml: a regra de "|" era uma simplificação da inglesa e perdia
  três casos — P(A|B) ("dado"), a|b entre números ("divide") e o intent
  literal. Portada a estrutura inglesa inteira.
- SharedRules/general.yaml: <none/> fora da química caía no default-text,
  que fala o nome da tag, e saía a palavra inglesa "none". Agora "nenhum".
- SharedRules/general.yaml: faltava o Log maiúsculo (valor principal), que
  saía "Log de x". Marcado t: — a tradução precisa de conferência.
- definitions.yaml: "segundo de arco" estava duplicado em PluralForms. O
  leitor de YAML do Rust aceita, mas audit-translations recusava o arquivo
  inteiro, ou seja, definitions.yaml não estava sendo auditado de verdade.
- definitions.yaml: plurais das formas prefixadas de "segundo de arco", que
  a regra genérica produzia como "yoctossegundo de arcos".

Testes desatualizados: pausas geradas pelo motor (ver ACHADOS.md seção 1),
o artigo em "o log de x", "1 meio" em vez de "um meio", "l n x" no modo
conciso, e a vírgula do grego (que o teste inglês também tem).

Decisão: menos unário fica "menos", não "negativo". Os testes estavam
divididos; a regra já dizia "menos" e os três discordantes foram alinhados.

Resolve duas pendências do ACHADOS.md: a contradição aparente entre
tensor_mmultiscripts e mhchem_so4_2mais (caminhos de código diferentes — só
o da química estava quebrado) e a divergência de inverse_trig entre
SimpleSpeak e ClearSpeak (as regras já estavam alinhadas; era o teste).

ACHADOS.md ganha a seção 6. Corrigidas duas afirmações das seções
anteriores: compute_auto_pause conta bytes, não letras; e as regras de
química não eram idênticas às inglesas (só as diretivas de pausa eram).
Registrado também que trocar bytes por caracteres foi testado e não
resolve — piora de 15 para 36 falhas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e colidir com ⊄

Duas correções de fala, com varredura e não caso a caso (ACHADOS 7.8/7.9):

1. Dentro de um conjunto ({x ∈ ℤ : x > 5}) a expressão modifica "todos os x"
   e não pode ter verbo finito nem singular: o verbo grudava em "conjunto"
   ("o conjunto de todos os x pertence a inteiros"). Seis dos oito ramos
   estavam errados, não só o Belongs. Agora: em / membros de / elementos de /
   pertencentes a, e as negações nominais. "fora de" foi rejeitado por trocar
   pertinência por localização; "não em" por ser truncado. O ramo SimpleSpeak
   usava uma string só para dentro e fora e passou a bifurcar.

2. ∉ com ClearSpeak_SetMemberSymbol=In fora de conjunto falava "não está
   contido em", exatamente a fala do ⊄. Passa a "não está em", espelhando o ∈.

Também nesta rodada, já em varredura: termo único por família de estilo
(fraktur, caligráfico) e adjetivo posposto nos dois arquivos; ∈ ∊ com Auto
separado de Member como o ∉; ! volta a distinguir literal/fatorial; ≇ ≚ ≞ ⋕
com termo matemático em vez do nome Unicode; cópula dupla em ∦ ⊈ ⊉.

Novo: tests/Languages/pt/ClearSpeak/sets.rs (pt vai de 102 para 142 testes,
∈ e ∊ travados iguais nas cinco preferências e nos dois estilos),
PythonScripts/conferir_vocabulario.py (consistência de vocabulário entre
unicode.yaml e unicode-full.yaml: 8 -> 4 grupos, restantes benignos) e
Rules/Languages/pt/TERMINOLOGIA_PT_BR.md (registro único das leituras).

Suíte inteira: 7307 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134dJm6wzqbquvZrNhPD3Ea
…o; pacote de escuta

Diagnóstico antes de escolher (ACHADOS 9): o MathML do ACESSÍLIA vem do
latex2mathml nos dois caminhos (inclusive Docling) e nunca traz intent=, então
os 186 IntentMappings ausentes não são prioridade. O que importa é o que o
motor infere sozinho e o que sai cru para o sintetizador.

Correções, pelo dano ao estudante:
- caracteres crus no corpus real: negrito latino e grego (\mathbf, \boldsymbol),
  ⟨ ⟩, ¯ de \bar{x} (o motor canonicaliza U+0304/U+203E para U+00AF, então a
  entrada "com mácron" nunca era alcançada), setas longas, µ Ω ℧ Å soltos
- "1 terceiro" -> "1 terço": listas fracionárias paravam em "meio"
- "o integral" -> "a integral": artigo concorda com o operador grande
- "magnitude de x" -> "a norma de x": intent inferido sem mapping pt
- "cross product"/"dot product" literais -> "produto vetorial/escalar": o
  intent inferido vem sem filhos e nenhuma regra casava com count(*)=0
- recuo controlado só em regra (gerar_recuo_en.py): 2091 entradas do en para
  codepoints sem cobertura, estilo já definido traduzido, resto em t: minúsculo.
  Antes o caractere saía cru; agora sai em inglês, contado como pendente.

Pacote da sessão de escuta (gerar_pacote_escuta.py -> SESSAO_ESCUTA.md): 30
expressões em 6 áreas, fala real nos dois estilos e três verbosidades, roteiro
e tabela das decisões que dependem do ouvinte.

cargo test: 7307 passed, 0 failed (pt: 142). conferir_vocabulario.py: 4 grupos,
todos benignos, antes e depois.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134dJm6wzqbquvZrNhPD3Ea
…o en

O latex2mathml emite \mid como U+2223, não "|": P(A ∣ B) saía "A divide B".
A entrada "∣" ganha a mesma condição de contexto da regra do "|" (dentro de
P( · ∣ · ) é "dado"; fora continua "divide"). Em conjunto por compreensão
{x ∣ ...} o problema persiste e não é regra: o canonicalizador só trata "|"
como cerca (registrado como item de src/ em ACHADOS 9.6).

Varredura: as 593 expressões dos testes do inglês faladas em português, à
procura de palavras inglesas. Fora dos <mtext> em inglês dos próprios testes
e das letras decoradas, nenhum vazamento em material real. As decorações
(circulado, entre parênteses, com ponto, invertido) entraram no mapa de
estilo do recuo controlado.

cargo test: 7307 passed, 0 failed (pt: 142). conferir_vocabulario.py: 4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134dJm6wzqbquvZrNhPD3Ea
…ão do recuo = 0

As entradas do recuo controlado usavam t: minúsculo, a mesma marca de
"traduzido mas não conferido" — 2 mil delas contra 20 pendências reais, que
sumiam no meio. Cada entrada do bloco leva agora # RECUO-EN na linha da chave
e o conferir_vocabulario.py ganhou a seção 5, que reporta os dois números em
separado: 2091 entradas de recuo (1980 strings em inglês) contra 20 strings
pendentes de conferência (fraktur x10, caligráfico x10).

Verificação de regressão: as 593 expressões dos testes do en faladas em pt
sem e com o bloco. 526 iguais; 67 mudaram, todas com caractere cru antes.
Nenhuma expressão 100% português mudou de fala.

cargo test: 7307 passed, 0 failed (pt: 142). conferir_vocabulario.py: 4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134dJm6wzqbquvZrNhPD3Ea
Removed comments regarding translation corrections and pluralization issues.
Removed comments regarding corrections in Portuguese grammar and terminology for mathematical expressions.
Removed comments regarding corrections related to gendered ordinal numbers and unnecessary English suffixes.
Removed translation notes and comments from definitions.yaml.
Corrected the tag for 'overview-default' to include 'fraction' for better intent matching.
Removed comments and documentation from escuta.rs.
Removed cautionary comments regarding the Spanish equivalent tests and their historical inaccuracies.
natalieac03 and others added 3 commits August 31, 2026 08:03
Reverte o .gitignore à versão do upstream; arquivos locais (venv, saídas
de teste, scripts auxiliares e documentos .md) ficam fora do controle de
versão via .git/info/exclude.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJN43HMwJHeagwCporXvF3
@github-project-automation github-project-automation Bot moved this from Triage to Done in MathCAT Project Board Aug 31, 2026
@natalieac03 natalieac03 reopened this Aug 31, 2026
@github-project-automation github-project-automation Bot moved this from Done to Ready in MathCAT Project Board Aug 31, 2026
@natalieac03

natalieac03 commented Aug 31, 2026

Copy link
Copy Markdown
Author

Sorry for the noise, the venv was tracked by mistake. It's removed now, and
the PR is restricted to Rules/Languages/pt and tests/Languages/pt (24 files).
Ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

1 participant