Ir para o conteúdo

Internacionalização

O Adaptive Learner é fornecido em 8 idiomas, todos completamente traduzidos desde a v1.13.0 / Fase 26: DE, EN, ES, FR, EL, PT, TR, JA. Segundo a regra do projeto, o conteúdo alemão usa umlauts reais (ä, ö, ü, ß) — o alemão com codificação ASCII é proibido em de.yaml e docs/help/de/**. test_i18n_translation_audit.py fixa tanto a cobertura de umlauts como o limiar de ≥90% de divergência em relação ao EN para os catálogos anteriormente em passagem.

Onde vivem as strings

Backend

Catálogos YAML em backend/config/i18n/{lang}.yaml — um ficheiro por idioma. O catálogo de referência é o EN; todos os outros catálogos devem ter a mesma árvore de chaves.

# backend/config/i18n/en.yaml
common:
  save: Save
  cancel: Cancel
settings:
  title: Settings
  section_language: Language
  ...

O backend expõe GET /api/i18n/{lang} que retorna todo o catálogo como JSON. O hook useI18n do frontend chama-o na primeira renderização e armazena o resultado em cache.

Fallbacks do frontend

frontend/src/i18n/fallbacks.ts transporta um subconjunto inline de strings codificadas no pacote frontend. Estas aparecem na primeira renderização antes de o catálogo do backend ter sido carregado — e como fallback permanente se o endpoint do catálogo retornar 5xx.

A cadeia de resolução de fallback em useI18n:

  1. Catálogo do backend (strings em tempo real de /api/i18n/{lang}). Percorrer o caminho com notação de ponto.
  2. Fallbacks do frontend codificados (resiliência na primeira renderização).
  3. String de fallback fornecida pelo chamador.
  4. A própria chave.

Ajuda in-app / site de documentação

docs/help/_meta.yaml declara a árvore de navegação com títulos DE + EN por entrada. O painel de ajuda in-app lê-o diretamente; scripts/generate_mkdocs_nav.py regenera o bloco nav do mkdocs.yml a partir da mesma fonte.

O Markdown das páginas de ajuda vive em docs/help/{lang}/... — uma pasta por idioma. O modo docs_structure: folder do mkdocs-static-i18n gere a resolução.

Adicionar um novo idioma

  1. Catálogo do backend: copie backend/config/i18n/en.yaml para backend/config/i18n/{novolang}.yaml. Traduza cada valor nativamente (sem passagem EN — o teste de auditoria de tradução falhará com <90% de divergência). Depois execute make sync-i18n para espelhar o catálogo em frontend/src/data/i18n/{novolang}.json (o pacote de modo Dexie que o hotfix v1.16.0 tornou resiliente na primeira renderização).
  2. Constantes do frontend: adicione o código de idioma a SUPPORTED_LANGUAGES em frontend/src/lib/constants.ts.
  3. Fallbacks do frontend: adicione um bloco {novolang}: {...} em frontend/src/i18n/fallbacks.ts com o pequeno subconjunto de strings que o caminho de código da primeira renderização usa.
  4. Perguntas de avaliação: edite plugins/adaptive-learner-plugin-assessment/adaptive_learner_assessment/questions.py — adicione um campo text_{novolang} a cada entrada de QUESTIONS e a cada resposta. Re-exporte o JSON: poetry run python plugins/.../questions.py --export-json frontend/src/data/assessment-questions.json (ainda não existe tal CLI; o script em scripts/ precisaria de uma pequena adição).
  5. Prompts de sessão: edite plugins/adaptive-learner-plugin-session/adaptive_learner_session/prompts.py para adicionar uma terceira chave de idioma a cada célula (método, passo). Re-exporte o JSON da mesma forma.
  6. Site de documentação: atualize o bloco plugins.i18n.languages do mkdocs.yml e adicione o diretório docs/help/{novolang}/ espelhando a estrutura EN.

Testes de paridade

backend/tests/test_i18n_parity.py percorre cada catálogo e asserta que:

  • Cada idioma tem cada chave que a referência (EN) tem.
  • Nenhum idioma tem uma chave extra que a referência não tem.

Isto apanha o bug de deriva mais comum: alguém adiciona uma chave em EN e esquece de a adicionar nos outros 7 ficheiros. Execute make test-backend depois de qualquer alteração de catálogo.

Plurais

Os catálogos atuais não usam sintaxe plural ICU. Os poucos contadores que renderizamos (contagem de sessões, dias de sequência) têm seleção de forma codificada em TS:

const label = count === 1 ? t("session_single") : t("session_plural");

Strings plurais ICU via mkdocs-i18n ou uma biblioteca ICU de tempo de execução está na lista de diferidos.

Idiomas RTL

Árabe, hebraico, persa, etc. precisariam de suporte a layout bidirecional no CSS. O tema atual assume LTR; adicionar RTL está na lista de diferidos.

Quando NÃO adicionar uma string

Se uma string só aparecer em superfícies voltadas para desenvolvedores (mensagens de erro lançadas por AdaptiveLearnerError, linhas de log, dados de fixture de testes), deixe-a em inglês. A maquinaria i18n é apenas para strings visíveis ao utilizador final.

As chamadas console.warn e console.error do frontend também ficam em inglês — são para desenvolvedores que leem a consola do navegador, não para utilizadores finais.