Internacionalização
Sirva sua documentação em vários idiomas com roteamento sensível ao locale, navegação por idioma, interface traduzida e SEO — tudo baseado em convenções.
O Blume serve um projeto em muitos idiomas. Coloque os arquivos traduzidos no lugar certo e o Blume cuida do roteamento, do seletor de idiomas, da navegação por locale e do SEO para você — não há uma camada de roteamento separada para manter. É opcional: sem um bloco i18n, seu site continua em um único idioma exatamente como antes.
Ative o recurso
Adicione um bloco i18n listando seus locales e qual deles é o padrão:
i18n: {
defaultLocale: "en",
locales: [
{ code: "en", label: "English" },
{ code: "fr", label: "Français" },
{ code: "ar", label: "العربية", dir: "rtl" },
],
}
Cada locale tem um code (usado nas URLs), um label (exibido no seletor de idiomas) e um dir opcional para escritas da direita para a esquerda ("ltr" por padrão). Um style opcional dá ao blume translate orientações livres para o locale — registro, dialeto, terminologia, por exemplo "Brazilian Portuguese, informal você" — de modo que a escolha fica fixada desde a primeira tradução, em vez de ser decidida pelo agente.
Organize o conteúdo traduzido
O locale padrão fica na raiz do seu conteúdo. Todos os outros locales são pastas de nível superior nomeadas pelo respectivo code, espelhando a estrutura padrão:
docs/
index.mdx -> /
guides/quickstart.mdx -> /guides/quickstart
fr/
index.mdx -> /fr
guides/quickstart.mdx -> /fr/guides/quickstart
ar/
index.mdx -> /ar
| Arquivo | Rota |
|---|---|
docs/index.mdx |
/ |
docs/guides/quickstart.mdx |
/guides/quickstart |
docs/fr/guides/quickstart.mdx |
/fr/guides/quickstart |
Você traduz apenas os arquivos que quiser — todo o resto recorre automaticamente ao fallback (veja Fallbacks).
Sufixos de nome de arquivo
Prefere manter as traduções ao lado do original? Defina parser: "dot" e nomeie os arquivos com um sufixo de locale em vez de usar pastas:
docs/
guides/quickstart.mdx -> /guides/quickstart (default)
guides/quickstart.fr.mdx -> /fr/guides/quickstart (French)
Bom para traduções esparsas — coloque as poucas páginas que você traduziu junto às originais sem espelhar a árvore inteira.
Arquivos compartilhados
Para conteúdo que é igual em todos os idiomas — um changelog, uma página de status — adicione um marcador $ para que um único arquivo sirva a todos os locales sem duplicação:
docs/changelog.$.mdx -> /changelog and /fr/changelog (same content)
docs/guides/meta.$.ts (folder meta applied to every locale)
Um meta.ts específico de um locale ainda substitui o compartilhado para aquele idioma.
URLs do locale padrão
Por padrão, o locale padrão não tem prefixo de URL (/, /guides/quickstart), enquanto os outros locales são prefixados (/fr/…). Isso mantém limpas as URLs do seu idioma principal. Para prefixar todos os locales, incluindo o padrão:
i18n: {
// …
hideDefaultLocalePrefix: false, // /en/…, /fr/…
}
Navegação por locale
Cada idioma ganha sua própria barra lateral, construída a partir dos arquivos daquele locale — então as traduções podem divergir em estrutura, ordenação ou rótulos. Os arquivos meta.ts de pasta também são resolvidos por locale: com o parser dir padrão, coloque um meta.ts em fr/guides/ para ordenar o grupo em francês de forma independente. Com o parser dot, as traduções ficam ao lado das originais, portanto o meta.ts de uma pasta se aplica a todos os locales. Todo o resto da navegação funciona da mesma forma, por idioma.
As abas do cabeçalho são configuradas, e não derivadas do conteúdo, então seus rótulos são localizados em blume.config.ts: o label de uma aba aceita um mapa por locale ({ en: "Docs", fr: "Documentation" }) além da forma de string simples, recorrendo à entrada do locale padrão para os locales que você não preencheu. Veja Abas.
Fallbacks
Quando uma página ainda não foi traduzida, o Blume renderiza o conteúdo do locale de fallback na URL localizada — assim o link funciona, a página é totalmente pré-renderizada e os motores de busca não são levados a um beco sem saída. O fallback usa por padrão o seu defaultLocale:
i18n: {
// …
fallbackLocale: "en", // default; set to null to 404 instead
}
Páginas de fallback são excluídas do índice de busca e não são anunciadas como traduções reais no hreflang, de modo que conteúdo não traduzido não concorre por posicionamento. Elas ainda aparecem na barra lateral daquele locale, então a navegação permanece completa — um leitor consegue chegar a qualquer página em qualquer idioma.
Traduzindo com um agente
Você não precisa preencher os locales manualmente. O blume translate encontra todas as páginas que estão faltando ou desatualizadas em cada locale e as traduz com uma CLI de agente local (Claude Code ou Codex):
blume translate --claude
O Blume valida a estrutura de cada resultado — frontmatter, blocos de código, links — e escreve os arquivos ele mesmo; o agente apenas traduz o texto. Um registro versionado (blume.translations.json) rastreia de qual revisão de origem cada tradução veio, então as reexecuções tocam apenas o que mudou, e as traduções que você escreveu à mão são adotadas como estão, nunca sobrescritas. Em CI, blume translate --check falha quando uma página de origem avançou além de suas traduções.
O seletor de idiomas
Quando a i18n está ativada, um seletor de idiomas aparece automaticamente no cabeçalho, gerado a partir dos seus locales. Para cada página, ele aponta para a tradução correspondente em todos os idiomas; onde falta uma tradução, ele aponta para a página de fallback e a marca como não traduzida. Não há nada para configurar.
Interface traduzida
O Blume inclui traduções nativas para os elementos da própria interface — “Nesta página”, “Buscar”, “Editar no GitHub” e o restante — de modo que um locale com um pacote nativo já vem com a interface traduzida. Você traduz apenas o seu conteúdo.
Há pacotes para mais de 30 idiomas — árabe, bengali, búlgaro, catalão, chinês (simplificado e tradicional), croata, tcheco, dinamarquês, holandês, finlandês, francês, alemão, grego, hebraico, híndi, húngaro, indonésio, italiano, japonês, coreano, norueguês, persa, polonês, português (e português brasileiro), romeno, russo, sérvio, eslovaco, espanhol, sueco, tailandês, turco, ucraniano e vietnamita. Eles são mantidos pela comunidade — abra um PR para adicionar um locale ou aprimorar uma tradução.
Strings ausentes ou não incluídas recorrem ao locale padrão e, depois, ao inglês. Para substituir uma string ou fornecer seu próprio idioma, defina i18n.ui, com chaves por locale:
i18n: {
// …
ui: {
fr: {
search: { button: "Rechercher", placeholder: "Rechercher…" },
page: { previous: "Précédent", next: "Suivant" },
},
},
}
SEO
O SEO localizado é cuidado para você — não há metadados por página para escrever:
<html lang>edirsão definidos a partir do locale ativo.- As alternativas
hreflangapontam para todas as traduções reais de uma página, mais umx-defaultapontando para o locale padrão. - As URLs canônicas são corretas por locale, e o JSON-LD carrega
inLanguage.
Defina deployment.site para que isso possa ser emitido como URLs absolutas.
Busca
A busca é limitada ao idioma ativo: em uma página /fr/…, o diálogo retorna resultados em francês, com uma opção Todos os idiomas para buscar em todos os locales de uma vez. Os índices padrão (Orama) e FlexSearch filtram no navegador; provedores hospedados carregam uma faceta locale em cada registro.
Da direita para a esquerda
Defina dir: "rtl" em um locale e o Blume espelha toda a interface — a barra lateral, o cabeçalho, o índice da página, a paginação, a busca e os menus — e define <html dir> de acordo. Duas coisas permanecem deliberadamente da esquerda para a direita: blocos de código (código se lê da esquerda para a direita em qualquer idioma) e conteúdo de fallback — uma página não traduzida mantém a direção do idioma em que ela realmente está escrita, então o inglês exibido sob um locale RTL continua legível enquanto os elementos ao redor são espelhados.