Getting Started internationalizing (i18n) with Intlayer and Next.js 14 with App Router
What is Intlayer?
Intlayer é uma biblioteca inovadora e de código aberto de internacionalização (i18n) projetada para simplificar o suporte multilíngue em aplicações web modernas. Intlayer se integra perfeitamente com o mais recente framework Next.js 14, incluindo seu poderoso App Router. É otimizado para trabalhar com Server Components para renderização eficiente e é totalmente compatível com Turbopack (a partir do Next.js >= 15).
Com o Intlayer, você pode:
- Gerenciar traduções facilmente usando dicionários declarativos no nível do componente.
- Localizar dinamicamente metadados, rotas e conteúdo.
- Acessar traduções em componentes do lado do cliente e do lado do servidor.
- Garantir suporte TypeScript com tipos autogerados, melhorando a autocompletação e a detecção de erros.
- Beneficiar-se de recursos avançados, como detecção e troca dinâmica de locais.
Nota: O Intlayer é compatível com Next.js 12, 13, 14 e 15. Se você estiver usando Next.js Page Router, pode consultar este guia. Para Next.js 15 com ou sem turbopack, consulte este guia.
Step-by-Step Guide to Set Up Intlayer in a Next.js Application
Step 1: Install Dependencies
Instale os pacotes necessários usando npm:
npm install intlayer next-intlayer
yarn add intlayer next-intlayer
pnpm add intlayer next-intlayer
Step 2: Configure Your Project
Crie um arquivo de configuração para configurar os idiomas da sua aplicação:
// intlayer.config.ts
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Seus outros locais
],
defaultLocale: Locales.ENGLISH,
},
};
export default config;
Para ver todos os parâmetros disponíveis, consulte a documentação de configuração aqui.
Step 3: Integrate Intlayer in Your Next.js Configuration
Configure sua configuração do Next.js para usar o Intlayer:
// next.config.mjs
import { withIntlayer } from "next-intlayer/server";
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default withIntlayer(nextConfig);
Step 4: Configure Middleware for Locale Detection
Configure um middleware para detectar o idioma preferido do usuário:
// src/middleware.ts
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
export const config = {
matcher: "/((?!api|static|.*\\..*|_next).*)",
};
Step 5: Define Dynamic Locale Routes
Implemente o roteamento dinâmico para conteúdo localizado:
Mude src/app/page.ts para src/app/[locale]/page.ts
Em seguida, implemente a função generateStaticParams em seu Layout da aplicação.
// src/app/layout.tsx
import type { ReactNode } from "react";
import "./globals.css";
export { generateStaticParams } from "next-intlayer"; // Linha a ser inserida
const RootLayout = ({
children,
}: Readonly<{
children: ReactNode;
}>) => children;
export default RootLayout;
Em seguida, adicione um novo layout em seu diretório [locale]:
// src/app/[locale]/layout.tsx
import { type Next14LayoutIntlayer } from "next-intlayer";
import { Inter } from "next/font/google";
import { getHTMLTextDir } from "intlayer";
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout: Next14LayoutIntlayer = ({
children,
params: { locale },
}) => (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>{children}</body>
</html>
);
export default LocaleLayout;
Step 6: Declare Your Content
Crie e gerencie seus dicionários de conteúdo:
// src/app/[locale]/page.content.ts
import { t, type DeclarationContent } from "intlayer";
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
en: "Get started by editing",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
} satisfies DeclarationContent;
export default pageContent;
Veja como declarar seus arquivos de declaração Intlayer.
Step 7: Utilize Content in Your Code
Acesse seus dicionários de conteúdo em toda a sua aplicação:
// src/app/[locale]/page.ts
import { ClientComponentExample } from "@component/ClientComponentExample";
import { LocaleSwitcher } from "@component/LangSwitcherDropDown";
import { NestedServerComponentExample } from "@component/NestedServerComponentExample";
import { ServerComponentExample } from "@component/ServerComponentExample";
import { type Next14PageIntlayer, IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const Page: Next14PageIntlayer = ({ params: { locale } }) => {
const content = useIntlayer("page", locale);
return (
<>
<p>
{content.getStarted.main}
<code>{content.getStarted.pageLink}</code>
</p>
{/**
* IntlayerServerProvider é usado para fornecer o idioma para os filhos do servidor
* Não funciona se definido no layout
*/}
<IntlayerServerProvider locale={locale}>
<ServerComponentExample />
</IntlayerServerProvider>
{/**
* IntlayerClientProvider é usado para fornecer o idioma para os filhos do cliente
* Pode ser definido em qualquer componente pai, incluindo o layout
*/}
<IntlayerClientProvider locale={locale}>
<ClientComponentExample />
</IntlayerClientProvider>
</>
);
};
export default Page;
// src/components/ClientComponentExample.tsx
"use client";
import { useIntlayer } from "next-intlayer";
export const ClientComponentExample = () => {
const content = useIntlayer("client-component-example"); // Crie a declaração de conteúdo relacionada
return (
<div>
<h2>{content.title} </h2>
<p>{content.content}</p>
</div>
);
};
// src/components/ServerComponentExample.tsx
import { useIntlayer } from "next-intlayer/server";
export const ServerComponentExample = () => {
const content = useIntlayer("server-component-example"); // Crie a declaração de conteúdo relacionada
return (
<div>
<h2>{content.title} </h2>
<p>{content.content}</p>
</div>
);
};
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:
tsx<img src={content.image.src.value} alt={content.image.value} />
Para um uso mais detalhado do intlayer em componente Cliente ou Servidor, veja o exemplo do Next.js aqui.
(Optional) Step 8: Internationalization of your metadata
No caso de você querer internacionalizar seus metadados, como o título da sua página, você pode usar a função generateMetadata fornecida pelo Next.js. Dentro da função, use a função getTranslationContent para traduzir seus metadados.
// src/app/[locale]/layout.tsx ou src/app/[locale]/page.tsx
import {
type IConfigLocales,
getTranslationContent,
getMultilingualUrls,
} from "intlayer";
import type { Metadata } from "next";
import type { LocalParams } from "next-intlayer";
export const generateMetadata = ({
params: { locale },
}: LocalParams): Metadata => {
const t = <T>(content: IConfigLocales<T>) =>
getTranslationContent(content, locale);
/**
* Gera um objeto contendo todas as urls para cada localidade.
*
* Exemplo:
* ```ts
* getMultilingualUrls('/about');
*
* // Retorna
* // {
* // en: '/about',
* // fr: '/fr/about',
* // es: '/es/about',
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
return {
title: t<string>({
en: "My title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: "My description",
fr: "Ma description",
es: "Mi descripción",
}),
alternates: {
canonical: url,
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: multilingualUrls[locale],
},
};
};
// ... Restante do código
Aprenda mais sobre a otimização de metadados na documentação oficial do Next.js.
(Optional) Step 9: Internationalization of your sitemap.xml and robots.txt
Para internacionalizar seu sitemap.xml e robots.txt, você pode usar a função getMultilingualUrls fornecida pelo Intlayer. Essa função permite que você gere URLs multilíngues para seu sitemap.
// src/app/sitemap.ts
import { getMultilingualUrls } from "intlayer";
import type { MetadataRoute } from "next";
const sitemap = (): MetadataRoute.Sitemap => [
{
url: "https://example.com",
alternates: {
languages: getMultilingualUrls("https://example.com"),
},
},
{
url: "https://example.com/login",
alternates: {
languages: getMultilingualUrls("https://example.com/login"),
},
},
{
url: "https://example.com/register",
alternates: {
languages: getMultilingualUrls("https://example.com/register"),
},
},
];
export default sitemap;
// src/app/robots.ts
import type { MetadataRoute } from "next";
import { getMultilingualUrls } from "intlayer";
const getAllMultilingualUrls = (urls: string[]) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
const robots = (): MetadataRoute.Robots => ({
rules: {
userAgent: "*",
allow: ["/"],
disallow: getAllMultilingualUrls(["/login", "/register"]),
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
export default robots;
Aprenda mais sobre a otimização do sitemap na documentação oficial do Next.js. Aprenda mais sobre a otimização do robots.txt na documentação oficial do Next.js.
(Optional) Step 10: Change the language of your content
Para mudar o idioma do seu conteúdo, você pode usar a função setLocale fornecida pelo hook useLocale. Essa função permite que você defina o idioma da aplicação e atualize o conteúdo de acordo.
import { Locales } from "intlayer";
import { useLocale } from "next-intlayer";
const MyComponent = () => {
const { setLocale } = useLocale();
return (
<button onClick={() => setLocale(Locales.English)}>Mudar Idioma</button>
);
};
Configure TypeScript
Intlayer usa augmentação de módulo para obter benefícios do TypeScript e tornar seu código mais robusto.
Certifique-se de que sua configuração TypeScript inclua os tipos autogerados.
// tsconfig.json
{
// sua configuração personalizada
include: [
"src",
"types", // <- Inclua os tipos auto gerados
],
}
Git Configuration
É recomendado ignorar os arquivos gerados pelo Intlayer. Isso permite que você evite se comprometer com eles em seu repositório Git.
Para fazer isso, você pode adicionar as seguintes instruções ao seu arquivo .gitignore:
# Ignore os arquivos gerados pelo Intlayer
.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