Pular para o conteúdo

Suporte a vários idiomas e troca de idioma

O EpoCanvas Docs inclui de origem um sistema multilingue ao nível do conteúdo: os textos da interface, como a barra de navegação, a barra lateral e as mensagens de pesquisa, bem como o corpo do texto de cada documento, têm versões independentes em 10 idiomas. Quando o leitor escolhe o idioma no canto superior direito da página, é encaminhado para a versão do mesmo artigo nesse idioma, com o corpo do texto e a interface a mudarem em conjunto.


Lista de idiomas suportados

O site disponibiliza atualmente 10 idiomas, sendo o chinês simplificado o idioma predefinido:

IdiomaNome do idiomaPrefixo de URLAbreviatura na interface
简体中文Chinês simplificado (predefinido)sem prefixoZH
繁體中文Chinês tradicional/zh-tw/TW
EnglishInglês/en/EN
日本語Japonês/ja/JA
한국어Coreano/ko/KO
EspañolEspanhol/es/ES
FrançaisFrancês/fr/FR
DeutschAlemão/de/DE
РусскийRusso/ru/RU
PortuguêsPortuguês/pt/PT

A lista de idiomas está definida em SUPPORTED_LANGUAGES, em src/utils/i18n.ts, e o registo das rotas de idioma está na configuração locales de astro.config.mjs; ambos os locais devem manter-se consistentes.


Como trocar de idioma

  1. Encontre o botão de idioma à direita da barra de navegação no topo da página (mostra a abreviatura do idioma atual, por exemplo ZH);
  2. Clique no botão e o menu pendente lista todos os 10 idiomas;
  3. Clique no idioma pretendido (por exemplo English ou 日本語);
  4. O browser salta para a versão do artigo atual nesse idioma; a navegação, a barra lateral, o índice e o corpo do texto passam todos para o idioma escolhido.

Efeito real anotado com o menu pendente de troca de idioma aberto: ① botão de idioma ② lista de idiomas ③ idioma atual

Figura: efeito real anotado após clicar no botão de idioma na página “Suporte a vários idiomas e troca de idioma”. ① botão de troca de idioma à direita da barra superior; ② menu pendente aberto, listando todos os 10 idiomas (a lista pode ser deslocada); ③ idioma atualmente ativo (marcado com um visto).

Diagrama do mecanismo de funcionamento da troca de idioma

Figura: fluxo de execução da troca de idioma. No build é gerado um conjunto de páginas estáticas para cada idioma; clicar no botão de idioma salta para o mesmo artigo no idioma correspondente; quando falta a tradução de alguma página, é automaticamente apresentada em chinês como fallback.


Regras de URL

As páginas de cada idioma têm um prefixo de URL próprio; o mesmo artigo diferencia-se entre idiomas apenas pelo prefixo:

/canvas/i18n/ → Chinês simplificado (idioma predefinido, sem prefixo)
/en/canvas/i18n/ → Inglês
/ja/canvas/i18n/ → Japonês
/zh-tw/canvas/i18n/ → Chinês tradicional
  • A informação de idioma está diretamente codificada no URL; a página após a troca pode ser guardada nos favoritos e partilhada diretamente, e os motores de pesquisa conseguem indexar cada idioma separadamente;
  • Os links internos do site que aparecem na página (navegação, barra lateral, links de recomendação no corpo do texto) recebem automaticamente o prefixo do idioma atual, pelo que o leitor, ao ler continuamente dentro de um idioma, não salta de volta para páginas em chinês;
  • Cada versão linguística é uma página estática independente gerada no build; o atributo <html lang> da página corresponde ao idioma, permitindo que leitores de ecrã e ferramentas de tradução o identifiquem corretamente.

O que acontece quando falta uma tradução

O sistema trata as traduções em falta segundo a estratégia de “fallback para o idioma predefinido”: quando um documento ainda não tem tradução num determinado idioma, aceder à página desse idioma mostra o conteúdo em chinês simplificado predefinido, mantendo o resto da página (navegação, barra lateral, textos da interface) no idioma escolhido, sem erros 404 nem páginas em branco.

A vantagem desta estratégia é que, ao adicionar um documento, não é preciso esperar que as traduções de todos os idiomas estejam prontas: publica-se primeiro a versão chinesa e, quando as traduções estiverem completas, basta reconstruir o site.


Princípios de implementação

A capacidade multilingue assenta no mecanismo de internacionalização do Astro e do Starlight. O fluxo de build é o seguinte:

  1. Diretórios de conteúdo divididos por idioma: os documentos do idioma predefinido ficam em src/content/docs/ (chinês simplificado) e os dos outros idiomas em src/content/docs/<idioma>/, com uma estrutura de diretórios exatamente correspondente à chinesa; por exemplo, a versão inglesa de “Suporte a vários idiomas e troca de idioma” está em src/content/docs/en/canvas/i18n.md;
  2. Geração das páginas de todos os idiomas no build: o astro build lê a configuração locales de astro.config.mjs e gera um conjunto completo de páginas estáticas para cada idioma;
  3. Renderização dos termos da interface por idioma: os textos da interface, como a navegação da barra superior, as mensagens de pesquisa e o título do índice, são produzidos no build por cada componente através de getTranslation(key, lang) diretamente no idioma correspondente; não há scripts de substituição em tempo de execução na página;
  4. Localização automática dos links internos do corpo do texto: o plugin rehypeLocalizeInternalLinks do pipeline de build adiciona automaticamente o prefixo do idioma atual aos links internos do tipo /canvas/xxx presentes no corpo traduzido;
  5. Pesquisa de texto completo isolada por idioma: o Pagefind cria um índice independente para cada idioma; pesquisar numa página em inglês devolve apenas resultados em inglês.
  6. As imagens do corpo caem por idioma: o plugin rehypeLocalizeDiagramImages reescreve /images/canvas/<ficheiro> nas traduções para /images/canvas/<idioma>/<ficheiro>, e cada idioma guarda os seus ficheiros em public/images/canvas/<idioma>/; sem um ficheiro com o mesmo nome mantém-se o original, por isso uma imagem nova não precisa de existir logo nos 10 idiomas;
  7. Avisos e notas de rodapé acompanham o idioma da página: rehypeLocalizeAsides e rehypeLocalizeFootnotes reescrevem os títulos dos avisos e as notas a partir da pasta de idioma do ficheiro de origem — o Starlight deduz o idioma na fase remark pelo caminho absoluto, mas o build local passa um caminho relativo e, sem isto, tudo cairia para chinês;
  8. hreflang e a página 404: no fim do build, hreflangXDefault() acrescenta a cada página um hreflang="x-default" que aponta para a versão em chinês simplificado, e src/pages/404.astro reutiliza o mesmo dicionário para apresentar a mensagem no idioma do browser, com o menu de idiomas a levar à página inicial de cada idioma.

Para programadores: como adicionar um novo idioma?

Tendo como exemplo a adição do italiano (Italiano, código it):

  1. Registar a rota do idioma: acrescentar it: { label: 'Italiano', lang: 'it' } em locales, no astro.config.mjs;
  2. Completar os textos da barra lateral: no mesmo ficheiro, acrescentar em SIDEBAR_I18N as traduções it para todos os grupos e entradas;
  3. Completar os termos da interface: registar o idioma em SUPPORTED_LANGUAGES, em src/utils/i18n.ts (código, nome, abreviatura, prefixo de URL) e completar os termos da interface desse idioma em UI_TRANSLATIONS;
  4. Traduzir o conteúdo dos documentos: criar o diretório src/content/docs/it/ e colocar as traduções seguindo a estrutura de diretórios da versão chinesa. As páginas por traduzir mostram primeiro o chinês como fallback e podem ser completadas gradualmente; Para traduzir também capturas e diagramas, crie public/images/canvas/it/ com ficheiros do mesmo nome: as páginas usam-nos automaticamente.
  5. Reconstruir: executar pnpm run build e as páginas do novo idioma, bem como o índice de pesquisa, passam a estar gerados. Depois do build, corra node scripts/audit-i18n.mjs e node scripts/check-localized-images.mjs para rever a estrutura da tradução e as referências de imagens; ambos são verificações obrigatórias na CI.

Para programadores: como adicionar ou modificar termos da interface?

Ao acrescentar novos elementos à interface, complete os termos em UI_TRANSLATIONS, em src/utils/i18n.ts:

src/utils/i18n.ts
// O dicionário está organizado em dois níveis「idioma → chave do termo」, na mesma ordem de leitura do getTranslation
export const UI_TRANSLATIONS: Record<string, Record<string, string>> = {
// Passo 1: adicionar o termo no idioma predefinido zh-CN (se faltar, a interface mostra o nome da chave como fallback)
'zh-CN': {
'nav.plugins': '插件生态',
// ...restantes termos já existentes
},
// Passo 2: acrescentar nos outros idiomas a tradução da mesma chave; os idiomas sem tradução recaem automaticamente para o chinês
en: {
'nav.plugins': 'Plugins',
},
ja: {
'nav.plugins': 'プラグイン',
},
};

De seguida, chame getTranslation no componente e passe-lhe o idioma atual:

---
import { getLangFromLocale, getTranslation } from '../../utils/i18n';
const lang = getLangFromLocale(Astro.currentLocale);
---
<a href={localizedHref('/plugins/', lang)}>{getTranslation('nav.plugins', lang)}</a>

Os termos são renderizados no build como texto estático no idioma correspondente, sem custos em tempo de execução.