Adicione funcionalidades de i18n
Astro não tem suporte integrado a internacionalização (i18n), mas você pode construir a sua própria solução. Nesta receita, você vai aprender como usar as coleções de conteúdo e roteamento dinâmico para fornecer conteúdo em diferentes línguas.
Esse exemplo utiliza cada língua como seu próprio subcaminho, e.x. example.com/en/blog para Inglês e example.com/fr/blog para Francês.
Se você prefere que a língua padrão não seja visível na URL ao contrário de outras línguas, abaixo tem instruções para ocultar a língua padrão.
Receita
Configure páginas para cada língua
- 
Crie um diretório para cada língua que você quer oferecer suporte. Por exemplo, en/efr/se você estiver oferecendo suporte para inglês e francês:- Diretóriosrc/- Diretóriopages/- Diretórioen/- about.astro
- index.astro
 
- Diretóriofr/- about.astro
- index.astro
 
- index.astro
 
 
 
- 
Configure src/pages/index.astropara redirecionar para a língua padrão.src/pages/index.astro <meta http-equiv="refresh" content="0;url=/en/" />Esta abordagem utiliza meta refresh e funcionará independentemente de como você fizer deploy do seu site. No entanto, alguns hosts estáticos também permitem que você configure redirecionamentos pelo servidor com um arquivo de configuração personalizado. Verifique a documentação da sua plataforma de deploy para mais detalhes. Se você está utilizando um adaptador SSR, você pode usar Astro.redirectpara redirecionar para a linguagem padrão no servidor.src/pages/index.astro ---return Astro.redirect('/en/');---
Use coleções para conteúdo traduzido
- 
Crie um diretório em src/content/para cada tipo de conteúdo que você quer incluir e adicione subdiretórios para cada língua suportada. Por exemplo, para oferecer suporte a postagens de blog em inglês e francês:- Diretóriosrc/- Diretóriocontent/- Diretórioblog/- Diretórioen/ Postagens de blog em inglês- post-1.md
- post-2.md
 
- Diretóriofr/ Postagens de blog em francês- post-1.md
- post-2.md
 
 
 
 
 
- 
Crie um arquivo src/content/config.tse exporte uma coleção para cada tipo de conteúdo.src/content/config.ts import { defineCollection, z } from 'astro:content';const blogCollection = defineCollection({schema: z.object({title: z.string(),author: z.string(),date: z.date()})});export const collections = {'blog': blogCollection};📚 Leia mais sobre Coleções de Conteúdo. 
- 
Use rotas dinâmicas para buscar e renderizar conteúdo baseado em parâmetros langeslug.Em modo de renderização estático, use getStaticPathspara mapear cada entrada de conteúdo para uma página:src/pages/[lang]/blog/[...slug].astro ---import { getCollection } from 'astro:content'export async function getStaticPaths() {const paginas = await getCollection('blog')const caminhos = paginas.map(pagina => {const [lang, ...slug] = pagina.slug.split('/');return { params: { lang, slug: slug.join('/') || undefined }, props: pagina }})return caminhos;}const { lang, slug } = Astro.params;const pagina = Astro.props;const dataFormatada = pagina.data.data.toLocaleString(lang);const { Content } = await page.render();---<h1>{page.data.titulo}</h1><p>by {page.data.autor} • {dataFormatada}</p><Content/>Em modo SSR, busque a entrada solicitada diretamente: src/pages/[lang]/blog/[...slug].astro ---import { getEntryBySlug } from 'astro:content';const { lang, slug } = Astro.params;const pagina = await getEntryBySlug('blog', `${lang}/${slug}`);if (!pagina) {return Astro.redirect('/404');}const dataFormatada = page.data.data.toLocaleString(lang);const { Content, headings } = await page.render();---<h1>{page.data.titulo}</h1><p>by {page.data.autor} • {dataFormatada}</p><Content/>📚 Leia mais sobre roteamento dinâmico. O exemplo acima utiliza o método de formatação de data toLocaleString()para criar uma string legível a partir da data da página. Isso garante que a data e a hora sejam formatadas de acordo com a língua do usuário.
Traduza strings da UI
Criar dicionários de termos para traduzir as labels dos elementos de UI em todo o seu site. Isso permite que seus visitantes experimentem seu site completamente na língua deles.
- 
Crie um arquivo src/i18n/ui.tspara armazenar suas strings de tradução:src/i18n/ui.ts export const linguas = {en: 'English',fr: 'Français',};export const linguaPadrao = 'en';export const ui = {en: {'nav.home': 'Home','nav.about': 'About','nav.twitter': 'Twitter',},fr: {'nav.home': 'Accueil','nav.about': 'À propos',},} as const;
- 
Crie duas funções: uma para detectar a língua da página baseado na URL atual, e outra para obter as strings de tradução para diferentes partes da UI em src/i18n/utils.ts:src/i18n/utils.ts import { ui, linguaPadrao } from './ui';export function pegarLangDeURL(url: URL) {const [, lang] = url.pathname.split('/');if (lang in ui) return lang as keyof typeof ui;return linguaPadrao;}export function usarTraducoes(lang: keyof typeof ui) {return function t(key: keyof typeof ui[typeof linguaPadrao]) {return ui[lang][key] || ui[linguaPadrao][key];}}No passo 1, a string nav.twitternão foi traduzida para o francês. Você pode não querer traduzir todos os termos, como nomes próprios ou termos comuns da indústria. A funçãouseTranslationsirá retornar o valor da língua padrão se uma chave não for traduzida. Neste exemplo, os usuários franceses também verão “Twitter” na barra de navegação.
- 
Importe as funções onde necessário e use-as para escolher a string de UI que corresponde a língua atual. Por exemplo, um componente de navegação pode ser assim: src/components/Nav.astro ---import { pegarLangDeURL, usarTraducoes } from '../i18n/utils';const lang = pegarLangDeURL(Astro.url);const t = usarTraducoes(lang);---<ul><li><a href={`/${lang}/home/`}>{t('nav.home')}</a></li><li><a href={`/${lang}/about/`}>{t('nav.about')}</a></li><li><a href="https://twitter.com/astrodotbuild">{t('nav.twitter')}</a></li></ul>
- 
Cada página deve ter um atributo langno elemento<html>que corresponda a língua da página. Neste exemplo, um layout reutilizável extrai a língua da rota atual:src/layouts/Base.astro ---import { pegarLangDeURL } from '../i18n/utils';const lang = pegarLangDeURL(Astro.url);---<html lang={lang}><head><meta charset="utf-8" /><link rel="icon" type="image/svg+xml" href="/favicon.svg" /><meta name="viewport" content="width=device-width" /><title>Astro</title></head><body><slot /></body></html>Assim, você pode usar este layout base para garantir que as páginas usem o atributo langcorreto automaticamente.src/pages/en/about.astro ---import Base from "../../layouts/Base.astro"---<Base><h1>About me</h1>...</Base>
Permitir que os usuários alternem entre línguas
Criar links para as diferentes línguas que você oferece suporte para que os usuários possam escolher a língua que eles querem ler seu site.
- 
Crie um componente para mostrar um link para cada língua: src/components/SeletorLinguas.astro ---import { linguas } from '../i18n/ui';---<ul>{Object.entries(linguas).map(([lang, label]) => (<li><a href={`/${lang}/`}>{label}</a></li>))}</ul>
- 
Adicione <SeletorLinguas />ao seu site para que ele seja mostrado em todas as páginas. O exemplo abaixo adiciona ele ao rodapé do site em um layout base:src/layouts/Base.astro ---import SeletorLinguas from '../components/SeletorLinguas.astro';import { pegarLangDeURL } from '../i18n/utils';const lang = pegarLangDeURL(Astro.url);---<html lang={lang}><head><meta charset="utf-8" /><link rel="icon" type="image/svg+xml" href="/favicon.svg" /><meta name="viewport" content="width=device-width" /><title>Astro</title></head><body><slot /><footer><SeletorLinguas /></footer></body></html>
Ocultar a língua padrão na URL
- 
Crie um diretório para cada língua, exceto a língua padrão. Por exemplo, armazene suas páginas da língua padrão diretamente em pages/, e suas páginas traduzidas emfr/:- Diretóriosrc/- Diretóriopages/- about.astro
- index.astro
- Diretóriofr/- about.astro
- index.astro
 
 
 
 
- 
Adicione outra linha ao arquivo src/i18n/ui.tspara ativar o recurso:src/i18n/ui.ts export const mostrarLinguaPadrao = false;
- 
Adicione uma função ao arquivo src/i18n/utils.ts, para traduzir caminhos baseado na língua atual:src/i18n/utils.ts import { ui, linguaPadrao, mostrarLinguaPadrao } from './ui';export function usarCaminhoTraduzido(lang: keyof typeof ui) {return function traduzirCaminho(caminho: string, l: string = lang) {return !mostrarLinguaPadrao && l === linguaPadrao ? caminho : `/${l}${caminho}`}}
- 
Importe a função onde for necessário. Por exemplo, um componente navpode ficar assim:src/components/Nav.astro ---import { pegarLangDeURL, usarTraducoes, usarCaminhoTraduzido } from '../i18n/utils';const lang = pegarLangDeURL(Astro.url);const t = usarTraducoes(lang);const traduzirCaminho = usarCaminhoTraduzido(lang);---<ul><li><a href={traduzirCaminho('/home/')}>{t('nav.home')}</a></li><li><a href={traduzirCaminho('/about/')}>{t('nav.about')}</a></li><li><a href="https://twitter.com/astrodotbuild">{t('nav.twitter')}</a></li></ul>
- 
A função também pode ser usada para traduzir caminhos para uma língua específica. Por exemplo, quando os usuários alternam entre línguas: src/components/SeletorLinguas.astro ---import { linguas } from '../i18n/ui';---<ul>{Object.entries(linguas).map(([lang, label]) => (<li><a href={traduzirCaminho('/', lang)}>{label}</a></li>))}</ul>
Traduzir rotas
Traduzir as rotas das suas páginas para cada língua.
- Adicione mapeamento de rotas no arquivo src/i18n/ui.ts:
export const rotas = {  de: {   'services': 'leistungen',  },  fr: {   'services': 'prestations-de-service',  }, }- Atualize a função usarCaminhoTraduzidono arquivosrc/i18n/utils.tspara adicionar a lógica de tradução de roteamento.
import { ui, linguaPadrao, mostrarLinguaPadrao, rotas } from './ui';
export function usarCaminhoTraduzido(lang: keyof typeof ui) {  return function traduzirCaminho(caminho: string, l: string = lang) {    const nomeCaminho = caminho.replaceAll('/', '')    const temTraducao = linguaPadrao !== l && rotas[l] !== undefined && rotas[l][nomeCaminho] !== undefined    const caminhoTraduzido = temTraducao ? '/' + rotas[l][nomeCaminho] : path
    return !mostrarCaminhoTraduzido && l === linguaPadrao ? caminhoTraduzido : `/${l}${caminhoTraduzido}`  }}- Crie uma função auxiliar para obter a rota, se ela existir baseada na URL atual, em src/i18n/utils.ts:
import { ui, linguaPadrao, mostrarLinguaPadrao, rotas } from './ui';
export function pegarRotaDeUrl(url: URL): string | undefined {  const nomeCaminho = new URL(url).pathname  const partes = nomeCaminho?.split('/')  const caminho = partes.pop() || partes.pop()
  if (caminho === undefined) {    return undefined  }
  const linguaAtual = pegarLangDeURL(url);
  if (linguaPadrao === linguaAtual) {    const rota = Object.values(rotas)[0];    return rota[caminho] !== undefined ? rota[caminho] : undefined  }
  const pegarChavePeloValor = (obj: Record<string, string>, valor: string): string | undefined  => {      return Object.keys(obj).find((chave) => obj[chave] === valor)  }
  const chaveRevertida = pegarChavePeloValor(rotas[linguaAtual], caminho)
  if (chaveRevertida !== undefined) {    return chaveRevertida  }
  return undefined}- A função auxiliar pode ser usada para obter uma rota traduzida. Por exemplo, quando nenhuma rota traduzida é definida, o usuário será redirecionado para sua página inicial:
   ---   import { languages } from '../i18n/ui';   const rota = pegarRotaDeUrl(Astro.url);   ---
   <ul>     {Object.entries(linguas).map(([lang, label]) => (       <li>         <a href={traduzirCaminho(`/${rota ? rota : ''}`, lang)}>{label}</a>       </li>     ))}   </ul>Recursos
Bibliotecas da comunidade
- astro-i18next — Uma integração Astro para i18next incluindo alguns componentes utilitários.
- astro-i18n — Uma biblioteca de internacionalização focada em TypeScript para Astro.
- astro-i18n-aut — Uma integração Astro para i18n que suporta defaultLocalesem geração de páginas. A integração é agnóstica a adaptadores e frameworks de UI.