Getting Started Internationalizing (i18n) with Intlayer and React Create App
O que é o Intlayer?
Intlayer é uma biblioteca de internacionalização (i18n) inovadora e de código aberto, projetada para simplificar o suporte multilíngue em aplicações web modernas.
Com o Intlayer, você pode:
- Gerenciar traduções facilmente usando dicionários declarativos no nível do componente.
- Localizar dinamicamente metadados, rotas e conteúdos.
- Garantir suporte ao TypeScript com tipos gerados automaticamente, melhorando a autocompletação e a detecção de erros.
- Aproveitar recursos avançados, como detecção e troca dinâmica de locais.
Passo a Passo para Configurar o Intlayer em uma Aplicação React
Passo 1: Instalar Dependências
Instale os pacotes necessários usando npm:
1npm install intlayer react-intlayer
1yarn add intlayer react-intlayer
1pnpm add intlayer react-intlayer
Passo 2: Configuração do seu projeto
Crie um arquivo de configuração para configurar os idiomas da sua aplicação:
1// intlayer.config.ts
2
3import { Locales, type IntlayerConfig } from "intlayer";
4
5const config: IntlayerConfig = {
6 internationalization: {
7 locales: [
8 Locales.ENGLISH,
9 Locales.FRENCH,
10 Locales.SPANISH,
11 // Seus outros idiomas
12 ],
13 defaultLocale: Locales.ENGLISH,
14 },
15};
16
17export default config;
Para ver todos os parâmetros disponíveis, consulte a documentação de configuração aqui.
Passo 3: Integre o Intlayer na sua Configuração CRA
Altere seus scripts para usar react-intlayer
1 "scripts": {
2 "build": "react-intlayer build",
3 "start": "react-intlayer start",
4 "transpile": "intlayer build"
5 },
Nota: os scripts do react-intlayer são baseados no craco. Você também pode implementar sua própria configuração com base no plugin craco do intlayer. Veja um exemplo aqui.
Passo 4: Declare Seu Conteúdo
Crie e gerencie seus dicionários de conteúdo:
1// src/app.content.tsx
2import { t, type DeclarationContent } from "intlayer";
3import { type ReactNode } from "react";
4
5const appContent = {
6 key: "app",
7 content: {
8 getStarted: t<ReactNode>({
9 en: (
10 <>
11 Edite <code>src/App.tsx</code> e salve para recarregar
12 </>
13 ),
14 fr: (
15 <>
16 Éditez <code>src/App.tsx</code> et enregistrez pour recharger
17 </>
18 ),
19 es: (
20 <>
21 Edita <code>src/App.tsx</code> y guarda para recargar
22 </>
23 ),
24 }),
25 reactLink: {
26 href: "https://reactjs.org",
27 content: t({
28 en: "Learn React",
29 fr: "Apprendre React",
30 es: "Aprender React",
31 }),
32 },
33 },
34} satisfies DeclarationContent;
35
36export default appContent;
Veja como declarar seus arquivos de declaração do Intlayer.
Passo 5: Utilize o Intlayer no seu Código
Acesse seus dicionários de conteúdo em toda a sua aplicação:
1import logo from "./logo.svg";
2import "./App.css";
3import { IntlayerProvider, useIntlayer } from "react-intlayer";
4import { LocaleSwitcher } from "./components/LangSwitcherDropDown";
5
6function AppContent() {
7 const content = useIntlayer("app");
8
9 return (
10 <header className="App-header">
11 <img src={logo} className="App-logo" alt="logo" />
12
13 {content.getStarted}
14 <a
15 className="App-link"
16 href={content.reactLink.href.value}
17 target="_blank"
18 rel="noopener noreferrer"
19 >
20 {content.reactLink.content}
21 </a>
22 </header>
23 );
24}
25
26function App() {
27 return (
28 <IntlayerProvider>
29 <div className="App">
30 {/* Para usar corretamente o hook useIntlayer, você deve acessar seus dados em um componente filho */}
31 <AppContent />
32 </div>
33 <div className="absolute bottom-5 right-5 z-50">
34 <LocaleSwitcher />
35 </div>
36 </IntlayerProvider>
37 );
38}
39
40export default App;
Nota: Se você quiser usar seu conteúdo em um atributo string, como alt, title, href, aria-label, etc., você deve chamar o valor da função, como:
tsx1<img src={content.image.src.value} alt={content.image.value} />
(Opcional) Passo 6: Mudar o idioma do seu conteúdo
Para mudar o idioma do seu conteúdo, você pode usar a função setLocale fornecida pelo hook useLocale. Esta função permite que você defina o idioma da aplicação e atualize o conteúdo de acordo.
1import { Locales } from "intlayer";
2import { useLocale } from "react-intlayer";
3
4const LocaleSwitcher = () => {
5 const { setLocale } = useLocale();
6
7 return (
8 <button onClick={() => setLocale(Locales.English)}>
9 Mudar idioma para inglês
10 </button>
11 );
12};
(Opcional) Passo 7: Adicionar Roteamento Localizado à sua aplicação
O objetivo deste passo é criar rotas exclusivas para cada idioma. Isso é útil para SEO e URLs amigáveis para SEO. Exemplo:
1// /dashboard
2// /es/dashboard
3// /fr/dashboard
Por padrão, as rotas não são prefixadas para o idioma padrão. Se você quiser prefixar o idioma padrão, pode definir a opção middleware.prefixDefault como true na sua configuração. Consulte a documentação de configuração para mais informações.
Para adicionar roteamento localizado à sua aplicação, você pode criar um componente LocaleRouter que envolve as rotas da sua aplicação e lida com o roteamento baseado no idioma. Aqui está um exemplo usando React Router:
1// Importando dependências e funções necessárias
2import { Locales, getConfiguration, getPathWithoutLocale } from "intlayer"; // Funções utilitárias e tipos do 'intlayer'
3import { FC, PropsWithChildren } from "react"; // Tipos do React para componentes funcionais e props
4import { IntlayerProvider } from "react-intlayer"; // Provedor para contexto de internacionalização
5import {
6 BrowserRouter,
7 Routes,
8 Route,
9 useParams,
10 Navigate,
11 useLocation,
12} from "react-router-dom"; // Componentes de roteamento para gerenciar navegação
13
14// Desestruturando a configuração do Intlayer
15const { internationalization, middleware } = getConfiguration();
16const { locales, defaultLocale } = internationalization;
17
18/**
19 * Um componente que lida com a localização e envolve crianças com o contexto apropriado de idioma.
20 * Ele gerencia a detecção e validação de idioma com base na URL.
21 */
22const AppLocalized: FC<PropsWithChildren> = ({ children }) => {
23 const path = useLocation().pathname; // Obter o caminho da URL atual
24 const { locale } = useParams<{ locale: Locales }>(); // Extrair o parâmetro de idioma da URL
25
26 // Determinar o idioma atual, com fallback para o padrão se não fornecido
27 const currentLocale = locale ?? defaultLocale;
28
29 // Remover o prefixo do idioma do caminho para construir um caminho base
30 const pathWithoutLocale = removeLocaleFromUrl(
31 path // Caminho da URL atual
32 );
33
34 /**
35 * Se middleware.prefixDefault for true, o idioma padrão deve sempre ser prefixado.
36 */
37 if (middleware.prefixDefault) {
38 // Validar o idioma
39 if (!locale || !locales.includes(locale)) {
40 // Redirecionar para o idioma padrão com o caminho atualizado
41 return (
42 <Navigate
43 to={`/${defaultLocale}/${pathWithoutLocale}`}
44 replace // Substituir a entrada atual do histórico pela nova
45 />
46 );
47 }
48
49 // Envolver crianças com o IntlayerProvider e definir o idioma atual
50 return (
51 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
52 );
53 } else {
54 /**
55 * Quando middleware.prefixDefault é false, o idioma padrão não é prefixado.
56 * Garantir que o idioma atual seja válido e não o idioma padrão.
57 */
58 if (
59 currentLocale.toString() !== defaultLocale.toString() &&
60 !locales
61 .filter(
62 (locale) => locale.toString() !== defaultLocale.toString() // Excluir o idioma padrão
63 )
64 .includes(currentLocale) // Verificar se o idioma atual está na lista de idiomas válidos
65 ) {
66 // Redirecionar para o caminho sem o prefixo de idioma
67 return <Navigate to={pathWithoutLocale} replace />;
68 }
69
70 // Envolver crianças com o IntlayerProvider e definir o idioma atual
71 return (
72 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
73 );
74 }
75};
76
77/**
78 * Um componente de roteamento que configura rotas específicas para cada idioma.
79 * Usa o React Router para gerenciar a navegação e renderizar componentes localizados.
80 */
81export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (
82 <BrowserRouter>
83 <Routes>
84 <Route
85 // Padrão de rota para capturar o idioma (por exemplo, /en/, /fr/) e corresponder a todos os caminhos subsequentes
86 path="/:locale/*"
87 element={<AppLocalized>{children}</AppLocalized>} // Envolve as crianças com gerenciamento de idioma
88 />
89
90 {
91 // Se a prefixação do idioma padrão estiver desativada, renderize as crianças diretamente no caminho raiz
92 !middleware.prefixDefault && (
93 <Route
94 path="*"
95 element={<AppLocalized>{children}</AppLocalized>} // Envolve as crianças com gerenciamento de idioma
96 />
97 )
98 }
99 </Routes>
100 </BrowserRouter>
101);
(Opcional) Passo 8: Mudar a URL quando o idioma mudar
Para mudar a URL quando o idioma muda, você pode usar a prop onLocaleChange fornecida pelo hook useLocale. Paralelamente, você pode usar os hooks useLocation e useNavigate do react-router-dom para atualizar o caminho da URL.
1import { Locales, getLocalizedUrl } from "intlayer";
2import { useLocale } from "react-intlayer";
3import { useLocation, useNavigate } from "react-router-dom";
4
5const LocaleSwitcher = () => {
6 const location = useLocation(); // Obter o caminho atual da URL. Exemplo: /fr/about
7 const navigate = useNavigate();
8
9 const changeUrl = (locale: Locales) => {
10 // Construir a URL com o idioma atualizado
11 // Exemplo: /es/about com o idioma definido para espanhol
12 const pathWithLocale = getLocalizedUrl(location.pathname, locale);
13
14 // Atualizar o caminho da URL
15 navigate(pathWithLocale);
16 };
17
18 const { setLocale } = useLocale({
19 onLocaleChange: changeUrl,
20 });
21
22 return (
23 <button onClick={() => setLocale(Locales.English)}>
24 Mudar idioma para inglês
25 </button>
26 );
27};
Configurar TypeScript
Intlayer utiliza a extensão de módulo para obter os benefícios do TypeScript e tornar sua base de código mais robusta.
Certifique-se de que sua configuração do TypeScript inclua os tipos gerados automaticamente.
1// tsconfig.json
2
3{
4 // sua configuração personalizada
5 include: [
6 "src",
7 "types", // <- Inclua os tipos gerados automaticamente
8 ],
9}
Configuração do Git
Recomenda-se ignorar os arquivos gerados pelo Intlayer. Isso permite que você evite comitê-los em seu repositório Git.
Para fazer isso, você pode adicionar as seguintes instruções ao seu arquivo .gitignore:
1# Ignorar os arquivos gerados pelo Intlayer
2.intlayer
Se você tiver uma ideia para melhorar esta documentação, sinta-se à vontade para contribuir enviando uma pull request no GitHub.
Link do GitHub para a documentação