Skip to main content

Guía completa de internacionalización en Next.js

Configure next-intl con App Router, prepare el enrutamiento regional y automatice las traducciones con IA.

1

Instalar next-intl

next-intl es un único paquete que gestiona el enrutamiento regional, la carga de mensajes y los hooks de traducción para App Router de Next.js.

Terminal
npm install next-intl
¿Por qué next-intl en vez de next-i18next? next-intl está diseñado para App Router y los componentes de servidor. next-i18next se creó para Pages Router y su compatibilidad con App Router es limitada.
2

Crear la configuración de solicitudes de i18n

Cree dos archivos: src/i18n/request.ts para cargar los mensajes y src/i18n/routing.ts para definir las configuraciones regionales. Determinan cómo resuelve next-intl los mensajes y las rutas.

src/i18n/routing.ts
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';

export const routing = defineRouting({
  locales: ['en', 'de', 'ja', 'es'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',  // /about for en, /de/about for de
});

export const { Link, redirect, usePathname, useRouter } =
  createNavigation(routing);
Turbopack —el empaquetador predeterminado de Next.js 15— requiere experimental.turbo.resolveAlias en next.config.js. Sin él, verá errores «Couldn't find next-intl config file».
3

Configurar el middleware

Añada middleware.ts para gestionar la detección regional, la reescritura de URL y las redirecciones. El middleware intercepta cada solicitud y garantiza que se aplique la configuración correcta.

middleware.ts
// middleware.ts  <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)'],
};
middleware.ts DEBE estar en el directorio raíz de su proyecto, no dentro de src/. Este es el error de configuración más habitual con next-intl.
4

Configurar la estructura de carpetas [locale]

Mueva las rutas de la aplicación dentro de app/[locale]/. Añada generateStaticParams para generar páginas de cada configuración regional durante la compilación. Así se crea la estructura de URL /en/about, /de/about, etc.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
DEBE llamar a setRequestLocale(locale) en cada page.tsx y layout.tsx que utilice traducciones. Sin ello, Next.js recurre al renderizado dinámico y el rendimiento de la compilación empeora considerablemente.
5

Actualizar el diseño raíz

Cargue los mensajes con getMessages() y páselos a NextIntlClientProvider en el diseño regional raíz. Defina el atributo lang de html a partir del parámetro regional.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  const { locale } = await params;
  if (!routing.locales.includes(locale as any)) notFound();

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
NextIntlClientProvider requiere una prop locale explícita. Omitirla provoca errores sutiles en los componentes de cliente que resultan difíciles de depurar.
6

Utilizar traducciones en los componentes

Los componentes de servidor utilizan getTranslations —asíncrono, con await—. Los componentes de cliente utilizan useTranslations —un hook—. Elija según dónde se renderice el componente; los de servidor mantienen las traducciones completamente fuera del paquete JavaScript del cliente.

app/[locale]/page.tsx
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function AboutPage({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  setRequestLocale(locale);
  const t = await getTranslations('AboutPage');

  return <h1>{t('title')}</h1>;
}

// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';

export default function SearchBar() {
  const t = useTranslations('SearchBar');
  return <input placeholder={t('placeholder')} />;
}
Prefiera componentes de servidor para el contenido traducido. Mantienen las cadenas fuera del paquete JavaScript del cliente y reducen el tiempo de carga para los usuarios.
7

Añadir SEO: metadatos y hreflang

Utilice generateMetadata para producir títulos y descripciones de página específicos de cada configuración regional. Añada alternates.languages para las etiquetas hreflang y permita que los motores de búsqueda descubran todas las versiones lingüísticas de cada página.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';

export async function generateMetadata({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Metadata' });

  return {
    title: t('title'),
    description: t('description'),
    alternates: {
      languages: Object.fromEntries(
        routing.locales.map((l) => [l, `/${l}`])
      ),
    },
  };
}
En Vercel, las compilaciones pueden generar localhost como URL canónica si metadataBase no está definido. Defina siempre metadataBase en el diseño raíz con su dominio de producción.
8

Gestionar páginas de error y no encontrado

error.tsx y not-found.tsx necesitan un tratamiento especial porque pueden renderizarse fuera del diseño regional normal. not-found.tsx en la raíz requiere su propia configuración del proveedor de i18n para mostrar mensajes de error localizados.

app/[locale]/error.tsx
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';

export default function Error() {
  const t = useTranslations('Error');
  return (
    <div>
      <h1>{t('title')}</h1>
      <p>{t('description')}</p>
    </div>
  );
}

// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';

export default async function GlobalNotFound() {
  return (
    <html lang={routing.defaultLocale}>
      <body>
        <h1>404 - Page Not Found</h1>
      </body>
    </html>
  );
}
Next.js solo renderiza su página 404 localizada cuando el código llama expresamente a notFound(). Las rutas desconocidas sin una página coincidente muestran el 404 predeterminado de Next.js, no su versión localizada.
9

Automatizar traducciones

Cuando termine de configurar i18n, traduzca los archivos de mensajes con IA directamente desde su IDE o utilice la CLI de i18n Agent en el proceso de CI/CD para automatizar la traducción en cada implementación.

Terminal
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish

✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)
Utilice next-intl-localechain para respaldos regionales inteligentes: un usuario pt-BR ve traducciones pt-PT en lugar de inglés cuando no está disponible el portugués de Brasil.

Automatizar la calidad de la traducción

Detecte las claves ausentes y los marcadores de posición rotos antes de publicar con i18n-validate. Pruebe la interfaz con traducciones simuladas mediante i18n-pseudo antes de recibir las reales.

Herramientas de código abierto para i18n en Next.js

Estos paquetes de código abierto resuelven problemas habituales de los flujos de internacionalización en Next.js.

next-intl-localechain

next-intl estándar pasa directamente a la configuración regional predeterminada cuando falta una traducción. Un usuario de portugués de Brasil ve inglés en lugar de traducciones pt-PT perfectamente válidas. next-intl-localechain añade cadenas de respaldo inteligentes: combina en profundidad las traducciones de configuraciones relacionadas para que los usuarios regionales vean siempre la traducción disponible más próxima.

src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';

export default getRequestConfig(withLocaleChain({
  loadMessages: (locale) =>
    import(`../../messages/${locale}.json`).then(m => m.default),
  defaultLocale: 'en'
}));
Combina automáticamente y en profundidad las traducciones de las cadenas regionales
Cadenas integradas para portugués, español, francés, alemán y otros idiomas
Omite con elegancia los archivos de mensajes ausentes sin generar errores
Configuración en una línea: envuelve su getRequestConfig existente
Ver en GitHub

@i18n-agent/cli

Una herramienta de línea de comandos para traducir sus archivos de mensajes de Next.js sin salir del terminal. Traduzca archivos directamente, consulte el estado de los trabajos y descargue los resultados. Funciona en procesos de CI/CD con autenticación mediante clave de API para automatizar por completo los flujos de localización.

Terminal
# Install the CLI
npm install -g @i18n-agent/cli

# Authenticate
i18nagent login

# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es

# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,es
Traduzca JSON, YAML, PO y otros formatos de archivo i18n desde el terminal
Preparado para CI/CD: autentíquese mediante una variable de entorno en procesos automatizados
Consulte el estado, reanude trabajos fallidos y descargue los resultados
Salida JSON legible por máquinas para scripts y automatización
Ver en GitHub

Errores habituales

«Unable to find next-intl locale»

El middleware no coincidió con la solicitud. Compruebe: ¿está middleware.ts en la raíz del proyecto? ¿Excluye correctamente los archivos estáticos el patrón matcher? ¿Está incluida la configuración regional en su enrutamiento?

Renderizado dinámico inesperado

Falta setRequestLocale(locale) en una página o diseño. Sin él, next-intl utiliza cabeceras o cookies para detectar la configuración regional, lo que fuerza el renderizado dinámico e impide la generación estática.

Las rutas paralelas se rompen con i18n

Las rutas paralelas (@modal) y las rutas de intercepción ((.)photo) presentan incompatibilidades conocidas con el segmento dinámico [locale]. Utilice el enrutamiento mediante middleware como solución para estos patrones avanzados.

El cambio de idioma pierde la ruta actual

Al cambiar de configuración regional, conserve el pathname actual mediante usePathname() y sustituya únicamente el segmento regional. Tenga cuidado con los parámetros de rutas dinámicas: deben volver a resolverse para la nueva configuración.

Estructura de archivos recomendada

Project Structure
my-nextjs-app/
├── middleware.ts              # Locale routing (project root!)
├── next.config.mjs
├── messages/
│   ├── en.json                # Source messages
│   ├── de.json
│   └── ja.json
├── src/
│   ├── i18n/
│   │   ├── request.ts         # Message loading config
│   │   └── routing.ts         # Locale definitions
│   └── app/
│       └── [locale]/
│           ├── layout.tsx     # Root locale layout
│           ├── page.tsx       # Home page
│           ├── error.tsx      # Localized error page
│           ├── not-found.tsx  # Localized 404
│           └── about/
│               └── page.tsx
└── package.json

Pruebe i18n Agent ahora

Arrastre y suelte aquí su archivo de traducción

JSON, YAML, PO, XML, CSV, Markdown, Properties

o haga clic para seleccionar

Idiomas de destino

No es necesario registrarsePresupuesto al instante

Respaldo de configuraciones regionales con next-intl-localechain

Cuando falta una clave de traducción en una configuración regional como pt-BR, next-intl pasa directamente a la predeterminada en vez de comprobar primero la principal pt.

Terminal
npm install next-intl-localechain
Configuration
import { withLocaleChain } from 'next-intl-localechain';

export default withLocaleChain({
  fallbacks: {
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  },
  defaultLocale: 'en',
  loadMessages: (locale) => import(`./messages/${locale}.json`),
});

Consulte nuestra guía de respaldo de configuraciones regionales para ver todos los frameworks admitidos y las 75 cadenas integradas. Learn more →

Preguntas frecuentes