Next.js Internacionalización (i18n) con next-intl e Intlayer
Tanto next-intl como Intlayer son frameworks de internacionalización (i18n) de código abierto diseñados para aplicaciones Next.js. Se utilizan ampliamente para gestionar traducciones, localización y cambio de idioma en proyectos de software.
Comparten tres nociones principales:
Declaración de Contenido: El método para definir el contenido traducible de tu aplicación.
- Nombrada content declaration file en Intlayer, que puede ser un archivo JSON, JS o TS que exporta datos estructurados. Consulta la documentación de Intlayer para más información.
- Nombrada messages o locale messages en next-intl, usualmente en archivos JSON. Consulta la documentación de next-intl para más información.
Utilidades: Herramientas para construir e interpretar declaraciones de contenido en la aplicación, como useIntlayer() o useLocale() para Intlayer, y useTranslations() para next-intl.
Plugins y Middleware: Funciones para gestionar la redirección de URL, optimización de paquetes, y más—por ejemplo, intlayerMiddleware para Intlayer o createMiddleware para next-intl.
Intlayer vs. next-intl: Diferencias Clave
Para un análisis más profundo de cómo Intlayer se compara con otras bibliotecas de i18n para Next.js (como next-intl), consulta el post del blog next-i18next vs. next-intl vs. Intlayer.
Cómo Generar Mensajes de next-intl con Intlayer
¿Por Qué Usar Intlayer con next-intl?
Los archivos de declaración de contenido de Intlayer generalmente ofrecen una mejor experiencia para los desarrolladores. Son más flexibles y mantenibles debido a dos principales ventajas:
Colocación Flexible: Puedes colocar un archivo de declaración de contenido de Intlayer en cualquier parte del árbol de archivos de tu aplicación. Esto facilita renombrar o eliminar componentes sin dejar archivos de mensajes no utilizados o colgantes.
Estructuras de archivos de ejemplo:
bash.└── src └── components └── MyComponent ├── index.content.ts # Archivo de declaración de contenido └── index.tsx
Traducciones Centralizadas: Intlayer almacena todas las traducciones en una única declaración de contenido, asegurando que no falta ninguna traducción. En proyectos de TypeScript, las traducciones faltantes se marcan automáticamente como errores de tipo, proporcionando una retroalimentación inmediata a los desarrolladores.
Instalación
Para usar Intlayer y next-intl juntos, instala ambas bibliotecas:
npm install intlayer next-intl
Configuración de Intlayer para Exportar Mensajes de next-intl
Nota: Exportar mensajes de Intlayer para next-intl puede introducir ligeras diferencias en la estructura. Si es posible, mantén un flujo solo de Intlayer o solo de next-intl para simplificar la integración. Si necesitas generar mensajes de next-intl desde Intlayer, sigue los pasos a continuación.
Crea o actualiza un archivo intlayer.config.ts (o .mjs / .cjs) en la raíz de tu proyecto:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, content: { dictionaryOutput: ["next-intl"], // Usa la salida de next-intl nextIntlMessagesDir: "./intl/messages", // Dónde guardar los mensajes de next-intl },};export default config;
Declaración de Contenido
A continuación se presentan ejemplos de archivos de declaración de contenido en múltiples formatos. Intlayer compilará estos en archivos de mensajes que next-intl puede consumir.
import { t, type DeclarationContent } from "intlayer";const content = { key: "my-component", content: { helloWorld: t({ en: "Hello World", fr: "Bonjour le monde", es: "Hola Mundo", }), },} satisfies DeclarationContent;export default content;
Construir los Mensajes de next-intl
Para construir los archivos de mensajes para next-intl, ejecuta:
npx intlayer build
Esto generará recursos en el directorio ./intl/messages (según lo configurado en intlayer.config.*). La salida esperada:
.└── intl └── messages └── es └── my-content.json └── fr └── my-content.json └── en └── my-content.json
Cada archivo incluye mensajes compilados de todas las declaraciones de contenido de Intlayer. Las claves de nivel superior generalmente coinciden con tus campos content.key.
Usando next-intl en Tu Aplicación Next.js
Para más detalles, consulta la documentación oficial de uso de next-intl.
Crear un Middleware (opcional):
Si deseas gestionar la detección automática de idiomas o redirección, utiliza el createMiddleware de next-intl.middleware.tsimport createMiddleware from "next-intl/middleware";import { NextResponse } from "next/server";export default createMiddleware({ locales: ["en", "fr", "es"], defaultLocale: "en",});export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"],};
Crear un layout.tsx o _app.tsx para Cargar Mensajes:
Si estás utilizando el App Router (Next.js 13+), crea un layout:app/[locale]/layout.tsximport { NextIntlClientProvider } from 'next-intl';import { notFound } from 'next/navigation';import React, { ReactNode } from 'react';export const dynamic = 'force-dynamic';export default async function RootLayout({ children, params}: { children: ReactNode; params: { locale: string };}) { let messages; try { messages = (await import(`../../intl/messages/${params.locale}.json`)).default; } catch (error) { notFound(); } return ( <html lang={params.locale}> <body> <NextIntlClientProvider locale={params.locale} messages={messages}> {children} </NextIntlClientProvider> </body> </html> );}
Si estás utilizando el Pages Router (Next.js 12 o anterior), carga los mensajes en _app.tsx:
pages/_app.tsximport type { AppProps } from 'next/app';import { NextIntlProvider } from 'next-intl';function MyApp({ Component, pageProps }: AppProps) { return ( <NextIntlProvider locale={pageProps.locale} messages={pageProps.messages}> <Component {...pageProps} /> </NextIntlProvider> );}export default MyApp;
Obtener Mensajes del Lado del Servidor (ejemplo de Pages Router):
pages/index.tsximport { GetServerSideProps } from "next";import HomePage from "../components/HomePage";export default HomePage;export const getServerSideProps: GetServerSideProps = async ({ locale }) => { const messages = (await import(`../intl/messages/${locale}.json`)).default; return { props: { locale, messages, }, };};
Usando Contenido en Componentes de Next.js
Una vez que los mensajes se han cargado en next-intl, puedes usarlos en tus componentes a través del hook useTranslations():
import type { FC } from "react";import { useTranslations } from 'next-intl';const MyComponent: FC = () => { const t = useTranslations('my-component'); // 'my-component' corresponde a la clave de contenido en Intlayer return ( <div> <h1>{t('helloWorld')}</h1> </div> );};export default MyComponent;
¡Eso es todo! Siempre que actualices o agregues nuevos archivos de declaración de contenido de Intlayer, vuelve a ejecutar el comando intlayer build para regenerar tus mensajes JSON de next-intl. next-intl recogerá el contenido actualizado automáticamente.
Si tienes una idea para mejorar esta blogumentación, no dudes en contribuir enviando una pull request en GitHub.
Enlace de GitHub al blog