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:
| Idioma | Nome do idioma | Prefixo de URL | Abreviatura na interface |
|---|---|---|---|
| 简体中文 | Chinês simplificado (predefinido) | sem prefixo | ZH |
| 繁體中文 | Chinês tradicional | /zh-tw/ | TW |
| English | Inglês | /en/ | EN |
| 日本語 | Japonês | /ja/ | JA |
| 한국어 | Coreano | /ko/ | KO |
| Español | Espanhol | /es/ | ES |
| Français | Francês | /fr/ | FR |
| Deutsch | Alemão | /de/ | DE |
| Русский | Russo | /ru/ | RU |
| Português | Portuguê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
- 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); - Clique no botão e o menu pendente lista todos os 10 idiomas;
- Clique no idioma pretendido (por exemplo
Englishou日本語); - 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.

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).
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:
- 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 emsrc/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á emsrc/content/docs/en/canvas/i18n.md; - Geração das páginas de todos os idiomas no build: o
astro buildlê a configuraçãolocalesdeastro.config.mjse gera um conjunto completo de páginas estáticas para cada idioma; - 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; - Localização automática dos links internos do corpo do texto: o plugin
rehypeLocalizeInternalLinksdo pipeline de build adiciona automaticamente o prefixo do idioma atual aos links internos do tipo/canvas/xxxpresentes no corpo traduzido; - 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.
- As imagens do corpo caem por idioma: o plugin
rehypeLocalizeDiagramImagesreescreve/images/canvas/<ficheiro>nas traduções para/images/canvas/<idioma>/<ficheiro>, e cada idioma guarda os seus ficheiros empublic/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; - Avisos e notas de rodapé acompanham o idioma da página:
rehypeLocalizeAsideserehypeLocalizeFootnotesreescrevem 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; - hreflang e a página 404: no fim do build,
hreflangXDefault()acrescenta a cada página umhreflang="x-default"que aponta para a versão em chinês simplificado, esrc/pages/404.astroreutiliza 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):
- Registar a rota do idioma: acrescentar
it: { label: 'Italiano', lang: 'it' }emlocales, noastro.config.mjs; - Completar os textos da barra lateral: no mesmo ficheiro, acrescentar em
SIDEBAR_I18Nas traduçõesitpara todos os grupos e entradas; - Completar os termos da interface: registar o idioma em
SUPPORTED_LANGUAGES, emsrc/utils/i18n.ts(código, nome, abreviatura, prefixo de URL) e completar os termos da interface desse idioma emUI_TRANSLATIONS; - 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, criepublic/images/canvas/it/com ficheiros do mesmo nome: as páginas usam-nos automaticamente. - Reconstruir: executar
pnpm run builde as páginas do novo idioma, bem como o índice de pesquisa, passam a estar gerados. Depois do build, corranode scripts/audit-i18n.mjsenode scripts/check-localized-images.mjspara 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:
// O dicionário está organizado em dois níveis「idioma → chave do termo」, na mesma ordem de leitura do getTranslationexport 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.