Pular para o conteúdo

Adicione funcionalidades de i18n

Nesta receita, você aprenderá como usar coleções de conteúdo e roteamento dinâmico para construir suas própria solução de internacionalização (i18n) e servir seu conteúdo em diferentes línguas.

Esse exemplo serve cada língua em seu próprio subcaminho, como 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, aqui estão instruções para ocultar a língua padrão.

Veja a seção de recursos para links externos sobre assuntos relacionados como estilização right-to-left (RTL) e escolher tags de idioma.
  1. Crie um diretório para cada língua que você quer oferecer suporte. Por exemplo, en/ e fr/ se você estiver oferecendo suporte para inglês e francês:

    • Directorysrc/
      • Directorypages/
        • Directoryen/
          • about.astro
          • index.astro
        • Directoryfr/
          • about.astro
          • index.astro
        • index.astro
  2. Configure src/pages/index.astro para 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.

Use coleções para conteúdo traduzido

Seção intitulada Use coleções para conteúdo traduzido
  1. 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:

    • Directorysrc/
      • Directorycontent/
        • Directoryblog/
          • Directoryen/ Postagens de blog em inglês
            • post-1.md
            • post-2.md
          • Directoryfr/ Postagens de blog em francês
            • post-1.md
            • post-2.md
  2. Crie um arquivo src/content/config.ts e 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({
    titulo: z.string(),
    autor: z.string(),
    dia: z.date()
    })
    });
    export const collections = {
    'blog': blogCollection
    };
    Leia mais sobre Coleções de Conteúdo.
  3. Use rotas dinâmicas para buscar e renderizar conteúdo baseado em parâmetros lang e slug.

    Em modo de renderização estático, use getStaticPaths para 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.dia.toLocaleString(lang);
    const { Content } = await page.render();
    ---
    <h1>{pagina.data.titulo}</h1>
    <p>por {pagina.data.autor}{dataFormatada}</p>
    <Content/>
    Leia mais sobre roteamento dinâmico.

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.

  1. Crie um arquivo src/i18n/ui.ts para 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;
  2. Crie duas funções auxiliares: uma para detectar a língua da página baseado na URL atual, e outra para obter as strings traduzidas 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];
    }
    }
  3. Importe os auxiliadores onde necessário e use-os 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>
  4. Cada página deve ter um atributo lang no 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 lang correto automaticamente.

    src/pages/en/about.astro
    ---
    import Base from "../../layouts/Base.astro"
    ---
    <Base>
    <h1>About me</h1>
    ...
    </Base>

Permitir que usuários alternem línguas

Seção intitulada Permitir que usuários alternem línguas

Crie 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.

  1. 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>
  2. 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>
  1. 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 em fr/:

    • Directorysrc/
      • Directorypages/
        • about.astro
        • index.astro
        • Directoryfr/
          • about.astro
          • index.astro
  2. Adicione outra linha ao arquivo src/i18n/ui.ts para ativar o recurso:

    src/i18n/ui.ts
    export const mostrarLinguaPadrao = false;
  3. Adicione uma função auxiliar 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}`
    }
    }
  4. Importe o auxiliador onde for necessário. Por exemplo, um componente nav pode 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>
  5. A função auxiliar 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';
    import { getLangFromUrl, useTranslatedPath } from '../i18n/utils';
    const lang = getLangFromUrl(Astro.url);
    const translatePath = useTranslatedPath(lang);
    ---
    <ul>
    {Object.entries(linguas).map(([lang, label]) => (
    <li>
    <a href={traduzirCaminho('/', lang)}>{label}</a>
    </li>
    ))}
    </ul>

Traduza as rotas das suas páginas para cada língua.

  1. Adicione mapeamento de rotas no arquivo src/i18n/ui.ts:

    src/i18n/ui.ts
    export const rotas = {
    de: {
    'services': 'leistungen',
    },
    fr: {
    'services': 'prestations-de-service',
    },
    }
  2. Atualize a função auxiliar usarCaminhoTraduzido no arquivo src/i18n/utils.ts para adicionar a lógica de tradução de roteamento.

    src/i18n/utils.ts
    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}`
    }
    }
  3. Crie uma função auxiliar para obter a rota, se ela existir baseada na URL atual, em src/i18n/utils.ts:

    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
    }
  4. 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:

    src/components/SeletorLinguas.astro
    ---
    import { languages } from '../i18n/ui';
    import { pegarRotaDeUrl } from '../i18n/utils';
    const rota = pegarRotaDeUrl(Astro.url);
    ---
    <ul>
    {Object.entries(linguas).map(([lang, label]) => (
    <li>
    <a href={traduzirCaminho(`/${rota ? rota : ''}`, lang)}>{label}</a>
    </li>
    ))}
    </ul>
  • 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 defaultLocale sem geração de páginas. A integração é agnóstica a adaptadores e frameworks de UI.
  • paraglide — Uma biblioteca i18n com completa segurança de tipagem projetada especificamente para padrões de hidratação parcial como ilhas Astro.
Contribua

O que passa em sua cabeça?

Comunidade