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

What’s on your mind?

Create GitHub Issue

Quickest way to alert our team of a problem.

Community