Roadmap de internacionalização (i18n)¶
Diátaxis: explanation. Para o como traduzir, veja
locale/README.md.
CLAUDE.md §1 e §5 fixam português brasileiro como idioma fonte
do Anotae. i18n para outros idiomas é planejada de forma incremental.
Por que i18n vem depois¶
Anotae nasce focado no SUS brasileiro. Internationalizar antes de estabilizar a UX em PT-BR seria:
- Caro: cada string que muda invalida traduções pendentes.
- Distraído: tira foco do problema clínico real (atrito de digitação na APS/DF).
- Prematuro: a primeira release internacional (
v4.0, ~M36) espera demanda comprovada — uma UBS de Cabo Verde ou Moçambique pedindo o app, não suposição.
Fases planejadas¶
| Fase | Versão | Idiomas | Justificativa |
|---|---|---|---|
| Hoje | v0.9.x – v3.x | apenas PT-BR | foco no piloto APS/DF |
| i18n base | v0.9.0-beta4+ | infra gettext pronta, _() em strings novas |
esta PR (#34) |
| Tradução parcial | v3.x | PT-PT (cobertura UI principal) | dar conta de profissionais portugueses |
| i18n full | v4.0 (M36+) | PT-BR + PT-PT + ES + EN | PALOPs + LATAM |
| Hub regional | v5.0+ | + FR, IT | se houver demanda |
Decisão técnica: Python gettext stdlib¶
Sem dependência nova. Suportado em todas as plataformas. Workflow
padrão da comunidade Python (xgettext → .po → .mo).
Alternativas consideradas:
| Opção | Vantagem | Desvantagem |
|---|---|---|
gettext stdlib ✅ |
Zero deps; padrão | API verbosa |
| Babel | Pluralização melhor | Dep extra |
| Fluent (Mozilla) | Sintaxe rica | Dep + curva |
| Crowdin/Weblate SaaS | Workflow tradutor | Vendor lock + custo |
Convenção de msgid¶
Msgid = string PT-BR. Em outros projetos (Django, GNOME) o msgid é em inglês para máxima portabilidade. Anotae inverte porque:
- PT-BR é o idioma fonte, não destino.
- Sem
.mocarregado,_("Salvar")devolve "Salvar" — UX fica intacta para a base de usuários atual. - Tradutores de outros idiomas trabalham a partir de PT-BR (idioma que dominam, pelo menos no caso PALOP/LATAM).
A convenção pode mudar em v4.0+ se uma comunidade de tradutores
não-lusófonos preferir msgid em inglês — então fazemos uma rodada
de migração com tradução automatizada via msgmerge.
Workflow CI¶
.github/workflows/ci.yml deve (ainda não implementado neste PR)
ganhar um step:
Sem isso, strings novas com _() ficam "presas" — tradutor não vê
até a próxima execução manual do script. Adicionar em PR de
follow-up junto com a primeira tradução real.
Política sobre PII em strings traduzíveis¶
Strings de UI nunca devem conter PII de paciente em runtime.
Quando uma string usa placeholder (_("Encounter %s salvo") % handle),
o tradutor vê apenas "Encounter %s salvo" — sem dados reais.
Reforço:
- O
.poté gerado por análise estática do código — só pega strings literais. Dados em runtime nunca entram no catálogo. - Tradutores recebem apenas o
.pot— nunca o vault de qualquer usuário. - Inspecionar o
.potantes de mandar para tradução:grep -i 'cns\|cpf\|paciente' locale/anotae.potdeve retornar 0 linhas.
Quando reabrir esta decisão¶
- Demanda comprovada de UBS lusófona não-brasileira → acelerar PT-PT
para
v1.xem vez de aguardarv3.x. - Patrocínio para tradução profissional → priorizar EN (alcance máximo) sobre PT-PT.
- Comunidade tradutora aparece spontaneously e prefere msgid em EN → migrar via msgmerge.