Getting Started internacionalizando (i18n) con Intlayer y Next.js 14 con App Router
¿Qué es Intlayer?
Intlayer es una biblioteca de internacionalización (i18n) innovadora y de código abierto diseñada para simplificar el soporte multilingüe en aplicaciones web modernas. Intlayer se integra sin problemas con el último marco de Next.js 14, incluida su poderosa App Router. Está optimizado para trabajar con Server Components para una representación eficiente y es completamente compatible con Turbopack (a partir de Next.js >= 15).
Con Intlayer, puedes:
- Gestionar traducciones fácilmente utilizando diccionarios declarativos a nivel de componente.
- Localizar dinámicamente metadatos, rutas y contenido.
- Acceder a traducciones tanto en componentes del lado del cliente como del servidor.
- Asegurar soporte para TypeScript con tipos autogenerados, mejorando la autocompletación y la detección de errores.
- Beneficiarte de características avanzadas, como la detección y cambio dinámico de locales.
Nota: Intlayer es compatible con Next.js 12, 13, 14 y 15. Si estás utilizando Next.js Page Router, puedes consultar esta guía. Para Next.js 15 con o sin turbopack, consulta esta guía.
Guía Paso a Paso para Configurar Intlayer en una Aplicación Next.js
Paso 1: Instalar Dependencias
Instala los paquetes necesarios usando npm:
1npm install intlayer next-intlayer
1yarn add intlayer next-intlayer
1pnpm add intlayer next-intlayer
Paso 2: Configura Tu Proyecto
Crea un archivo de configuración para configurar los idiomas de tu aplicación:
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 // Tus otros locales
12 ],
13 defaultLocale: Locales.ENGLISH,
14 },
15};
16
17export default config;
Para ver todos los parámetros disponibles, consulta la documentación de configuración aquí.
Paso 3: Integra Intlayer en Tu Configuración de Next.js
Configura tu configuración de Next.js para usar Intlayer:
1// next.config.mjs
2import { withIntlayer } from "next-intlayer/server";
3
4/** @type {import('next').NextConfig} */
5const nextConfig = {};
6
7export default withIntlayer(nextConfig);
Paso 4: Configura Middleware para Detección de Locale
Configura middleware para detectar el idioma preferido del usuario:
1// src/middleware.ts
2export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
3
4export const config = {
5 matcher: "/((?!api|static|.*\\..*|_next).*)",
6};
Paso 5: Define Rutas Locales Dinámicas
Implementa enrutamiento dinámico para contenido localizado:
Cambia src/app/page.ts a src/app/[locale]/page.ts
Luego, implementa la función generateStaticParams en el Layout de tu aplicación.
1// src/app/layout.tsx
2
3import type { ReactNode } from "react";
4import "./globals.css";
5
6export { generateStaticParams } from "next-intlayer"; // Línea a insertar
7
8const RootLayout = ({
9 children,
10}: Readonly<{
11 children: ReactNode;
12}>) => children;
13
14export default RootLayout;
Luego agrega un nuevo layout en tu directorio [locale]:
1// src/app/[locale]/layout.tsx
2
3import { type Next14LayoutIntlayer } from "next-intlayer";
4import { Inter } from "next/font/google";
5import { getHTMLTextDir } from "intlayer";
6
7const inter = Inter({ subsets: ["latin"] });
8
9const LocaleLayout: Next14LayoutIntlayer = ({
10 children,
11 params: { locale },
12}) => (
13 <html lang={locale} dir={getHTMLTextDir(locale)}>
14 <body className={inter.className}>{children}</body>
15 </html>
16);
17
18export default LocaleLayout;
Paso 6: Declara Tu Contenido
Crea y gestiona tus diccionarios de contenido:
1// src/app/[locale]/page.content.ts
2import { t, type DeclarationContent } from "intlayer";
3
4const pageContent = {
5 key: "page",
6 content: {
7 getStarted: {
8 main: t({
9 en: "Get started by editing",
10 fr: "Commencez par éditer",
11 es: "Comience por editar",
12 }),
13 pageLink: "src/app/page.tsx",
14 },
15 },
16} satisfies DeclarationContent;
17
18export default pageContent;
Consulta cómo declarar tus archivos de declaración de Intlayer.
Paso 7: Utiliza Contenido en Tu Código
Accede a tus diccionarios de contenido a lo largo de tu aplicación:
1// src/app/[locale]/page.ts
2
3import { ClientComponentExample } from "@component/ClientComponentExample";
4import { LocaleSwitcher } from "@component/LangSwitcherDropDown";
5import { NestedServerComponentExample } from "@component/NestedServerComponentExample";
6import { ServerComponentExample } from "@component/ServerComponentExample";
7import { type Next14PageIntlayer, IntlayerClientProvider } from "next-intlayer";
8import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
9
10const Page: Next14PageIntlayer = ({ params: { locale } }) => {
11 const content = useIntlayer("page", locale);
12
13 return (
14 <>
15 <p>
16 {content.getStarted.main}
17 <code>{content.getStarted.pageLink}</code>
18 </p>
19 {/**
20 * IntlayerServerProvider se usa para proporcionar el locale a los hijos del servidor
21 * No funciona si se establece en el layout
22 */}
23 <IntlayerServerProvider locale={locale}>
24 <ServerComponentExample />
25 </IntlayerServerProvider>
26 {/**
27 * IntlayerClientProvider se usa para proporcionar el locale a los hijos del cliente
28 * Puede configurarse en cualquier componente padre, incluido el layout
29 */}
30 <IntlayerClientProvider locale={locale}>
31 <ClientComponentExample />
32 </IntlayerClientProvider>
33 </>
34 );
35};
36
37export default Page;
1// src/components/ClientComponentExample.tsx
2
3"use client";
4
5import { useIntlayer } from "next-intlayer";
6
7export const ClientComponentExample = () => {
8 const content = useIntlayer("client-component-example"); // Crea la declaración de contenido relacionada
9
10 return (
11 <div>
12 <h2>{content.title} </h2>
13 <p>{content.content}</p>
14 </div>
15 );
16};
1// src/components/ServerComponentExample.tsx
2
3import { useIntlayer } from "next-intlayer/server";
4
5export const ServerComponentExample = () => {
6 const content = useIntlayer("server-component-example"); // Crea la declaración de contenido relacionada
7
8 return (
9 <div>
10 <h2>{content.title} </h2>
11 <p>{content.content}</p>
12 </div>
13 );
14};
Nota: Si deseas usar tu contenido en un atributo string, como alt, title, href, aria-label, etc., debes llamar al valor de la función, así:
tsx1<img src={content.image.src.value} alt={content.image.value} />
Para un uso más detallado de Intlayer en componentes Client o Server, consulta el ejemplo de Next.js aquí.
(Opcional) Paso 8: Internacionalización de tus metadatos
En caso de que desees internacionalizar tus metadatos, como el título de tu página, puedes utilizar la función generateMetadata proporcionada por Next.js. Dentro de la función, utiliza la función getTranslationContent para traducir tus metadatos.
1// src/app/[locale]/layout.tsx o src/app/[locale]/page.tsx
2
3import {
4 type IConfigLocales,
5 getTranslationContent,
6 getMultilingualUrls,
7} from "intlayer";
8import type { Metadata } from "next";
9import type { LocalParams } from "next-intlayer";
10
11export const generateMetadata = ({
12 params: { locale },
13}: LocalParams): Metadata => {
14 const t = <T>(content: IConfigLocales<T>) =>
15 getTranslationContent(content, locale);
16
17 /**
18 * Genera un objeto que contiene todas las URL para cada locale.
19 *
20 * Ejemplo:
21 * ```ts
22 * getMultilingualUrls('/about');
23 *
24 * // Devuelve
25 * // {
26 * // en: '/about',
27 * // fr: '/fr/about',
28 * // es: '/es/about',
29 * // }
30 * ```
31 */
32 const multilingualUrls = getMultilingualUrls("/");
33
34 return {
35 title: t<string>({
36 en: "My title",
37 fr: "Mon titre",
38 es: "Mi título",
39 }),
40 description: t({
41 en: "My description",
42 fr: "Ma description",
43 es: "Mi descripción",
44 }),
45 alternates: {
46 canonical: url,
47 languages: { ...multilingualUrls, "x-default": "/" },
48 },
49 openGraph: {
50 url: multilingualUrls[locale],
51 },
52 };
53};
54
55// ... Resto del código
Aprende más sobre la optimización de metadatos en la documentación oficial de Next.js.
(Opcional) Paso 9: Internacionalización de tu sitemap.xml y robots.txt
Para internacionalizar tu sitemap.xml y robots.txt, puedes utilizar la función getMultilingualUrls proporcionada por Intlayer. Esta función te permite generar URL multilingües para tu sitemap.
1// src/app/sitemap.ts
2
3import { getMultilingualUrls } from "intlayer";
4import type { MetadataRoute } from "next";
5
6const sitemap = (): MetadataRoute.Sitemap => [
7 {
8 url: "https://example.com",
9 alternates: {
10 languages: getMultilingualUrls("https://example.com"),
11 },
12 },
13 {
14 url: "https://example.com/login",
15 alternates: {
16 languages: getMultilingualUrls("https://example.com/login"),
17 },
18 },
19 {
20 url: "https://example.com/register",
21 alternates: {
22 languages: getMultilingualUrls("https://example.com/register"),
23 },
24 },
25];
26
27export default sitemap;
1// src/app/robots.ts
2import type { MetadataRoute } from "next";
3import { getMultilingualUrls } from "intlayer";
4
5const getAllMultilingualUrls = (urls: string[]) =>
6 urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
7
8const robots = (): MetadataRoute.Robots => ({
9 rules: {
10 userAgent: "*",
11 allow: ["/"],
12 disallow: getAllMultilingualUrls(["/login", "/register"]),
13 },
14 host: "https://example.com",
15 sitemap: `https://example.com/sitemap.xml`,
16});
17
18export default robots;
Aprende más sobre la optimización del sitemap en la documentación oficial de Next.js. Aprende más sobre la optimización de robots.txt en la documentación oficial de Next.js.
(Opcional) Paso 10: Cambia el idioma de tu contenido
Para cambiar el idioma de tu contenido, puedes utilizar la función setLocale proporcionada por el hook useLocale. Esta función te permite establecer el locale de la aplicación y actualizar el contenido en consecuencia.
1import { Locales } from "intlayer";
2import { useLocale } from "next-intlayer";
3
4const MyComponent = () => {
5 const { setLocale } = useLocale();
6
7 return (
8 <button onClick={() => setLocale(Locales.English)}>Cambiar Idioma</button>
9 );
10};
Configura TypeScript
Intlayer usa la ampliación de módulos para obtener los beneficios de TypeScript y hacer que tu código sea más robusto.
Asegúrate de que tu configuración de TypeScript incluya los tipos autogenerados.
1// tsconfig.json
2
3{
4 // tu configuración personalizada
5 include: [
6 "src",
7 "types", // <- Incluye los tipos autogenerados
8 ],
9}
Configuración de Git
Se recomienda ignorar los archivos generados por Intlayer. Esto te permite evitar comprometerlos en tu repositorio Git.
Para hacer esto, puedes agregar las siguientes instrucciones a tu archivo .gitignore:
1# Ignorar los archivos generados por Intlayer
2.intlayer
Si tienes una idea para mejorar esta documentación, no dudes en contribuir enviando una pull request en GitHub.
Enlace de GitHub a la documentación