Hay dos formas de traducir un sitio web Next.js. El ruta del código: poner cada ruta bajo un app/[lang] segmento, detecta el idioma del visitante en proxy.js, cargue un diccionario de traducción por configuración regional y genere etiquetas hreflang con el alternates campo de metadatos. El ruta sin código: agregue el script de un servicio de traducción a su diseño raíz y deje que traduzca las páginas renderizadas, con URL traducidas servidas desde un subdirectorio o subdominio para SEO.
La ruta del código le brinda control total y funciona mejor cuando el texto se encuentra en su base de código y un desarrollador lo mantiene. La ruta sin código es más rápida cuando el texto proviene de un CMS, cuando los no desarrolladores necesitan editar traducciones o cuando se necesitan muchos idiomas a la vez. Esta guía muestra ambos, según la documentación de Next.js 16, y termina con una lista de verificación para SEO multilingüe de cualquier manera.
Conclusiones clave
- Enrutador de aplicaciones: páginas de nido debajo
app/[lang], redirigir enproxy.js(llamadomiddleware.jsantes de Next.js 16), cargue diccionarios JSON en componentes del servidor y prerenderice locales congenerateStaticParams. - Enrutador de páginas: utilice el integrado
i18nconfigurar ennext.config.js. No funciona conoutput: 'export'. - Next.js no agrega hreflang por usted. En el enrutador de aplicaciones, utilice
alternates.languagesengenerateMetadata. - La opción sin código es una
<Script>etiquetarapp/layout.tsx. Para páginas traducidas indexables, utilice una configuración de subdirectorio o subdominio en lugar de la traducción únicamente en el navegador. - Cualquiera que sea la ruta que elijas, establece
<html lang>, traduce títulos y descripciones, y vincula cada versión de idioma con hreflang.
Opción 1: Internacionalizar Next.js con el enrutador de aplicaciones
Esto sigue a la Guía oficial de internacionalización de Next.js (versión 16.3 al momento de escribir este artículo).
Paso 1: Coloque sus rutas en un segmento de idioma
Mueva sus páginas y diseños a app/[lang]/. Luego, cada página recibe la configuración regional como parámetro de ruta:
// app/[lang]/page.tsx
export default async function Page({ params }: PageProps<'/[lang]'>) {
const { lang } = await params;
return <h1>{lang}</h1>;
}El enrutamiento puede utilizar una subruta (/fr/products) o un dominio (my-site.fr/products). La subruta es más sencilla de alojar y mantiene todos los idiomas en un dominio.
Paso 2: Detectar el idioma y redirigir en proxy.js
En Next.js 16 el middleware La convención de archivos pasó a llamarse proxy (hay un codemod: npx @next/codemod@canary middleware-to-proxy .). El proxy comprueba si la URL ya tiene una configuración regional y, si no, redirecciona:
// proxy.js
import { NextResponse } from 'next/server';
const locales = ['en', 'fr', 'de'];
function getLocale(request) {
// Read Accept-Language, e.g. with @formatjs/intl-localematcher and negotiator
return 'en';
}
export function proxy(request) {
const { pathname } = request.nextUrl;
const hasLocale = locales.some((l) => pathname.startsWith(`/${l}/`) || pathname === `/${l}`);
if (hasLocale) return;
request.nextUrl.pathname = `/${getLocale(request)}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: ['/((?!_next).*)'],
};Tenga cuidado con las redirecciones automáticas. Orientación de Google para sitios multilingües recomienda permitir a los usuarios elegir: “Considere agregar hipervínculos a versiones de una página en otros idiomas” Redirigir solo cuando la URL no tenga configuración regional, nunca lejos de una configuración regional que el visitante (o Googlebot) solicitó y siempre mostrar un selector de idioma.
Paso 3: Cargue un diccionario por idioma
Mantenga un archivo JSON por idioma y cárguelo en el servidor:
// app/[lang]/dictionaries.ts
import 'server-only';
const dictionaries = {
en: () => import('./dictionaries/en.json').then((m) => m.default),
fr: () => import('./dictionaries/fr.json').then((m) => m.default),
};
export type Locale = keyof typeof dictionaries;
export const hasLocale = (l: string): l is Locale => l in dictionaries;
export const getDictionary = async (l: Locale) => dictionaries[l]();// app/[lang]/page.tsx
import { notFound } from 'next/navigation';
import { getDictionary, hasLocale } from './dictionaries';
export default async function Page({ params }: PageProps<'/[lang]'>) {
const { lang } = await params;
if (!hasLocale(lang)) notFound();
const dict = await getDictionary(lang);
return <button>{dict.products.cart}</button>;
}Debido a que las páginas del enrutador de aplicaciones son componentes del servidor de forma predeterminada, los diccionarios no se envían al navegador. Los documentos también describen next/root-params, que permite leer cualquier componente del servidor lang sin pasarlo por los accesorios.
Paso 4: Representa previamente cada idioma y establece el atributo html lang
// app/[lang]/layout.tsx
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'fr' }, { lang: 'de' }];
}
export default async function RootLayout({ children, params }: LayoutProps<'/[lang]'>) {
return (
<html lang={(await params).lang}>
<body>{children}</body>
</html>
);
}Paso 5: Agregue hreflang y etiquetas canónicas
Next.js no sabe qué páginas son traducciones unas de otras, por lo que lo declaras. Con el API de metadatos, alternates genera los enlaces canónicos y hreflang:
// app/[lang]/pricing/page.tsx
export async function generateMetadata({ params }) {
const { lang } = await params;
return {
alternates: {
canonical: `https://example.com/${lang}/pricing`,
languages: {
en: 'https://example.com/en/pricing',
fr: 'https://example.com/fr/pricing',
de: 'https://example.com/de/pricing',
'x-default': 'https://example.com/en/pricing',
},
},
};
}Cada versión de idioma debe enumerar todas las versiones, incluida ella misma. Nuestro artículo sobre etiquetas hreflang autorreferenciales explica por qué eso es importante.
Bibliotecas que hacen el trabajo pesado
La documentación de Next.js enumera varias bibliotecas para enrutamiento y traducción, incluidas next-intl, next-international, next-i18n-router, paraglide-next, lingui y tolgee. Agregan pluralización, formato de números y fechas y claves de mensajes de tipo seguro. Para cualquier cosa más allá de un sitio pequeño, elija uno en lugar de escribir el suyo propio.
Opción 1b: El enrutador de páginas
Si su proyecto todavía utiliza el pages/ directorio, Next.js tiene enrutamiento i18n incorporado desde la versión 10. Agregue las ubicaciones a next.config.js:
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'de'],
defaultLocale: 'en-US',
},
};Esto te da /fr/blog y /de/blog automáticamente y establece <html lang>Según la Páginas Guía del enrutador, dos límites importan: todavía agregas hreflang tú mismo (con next/head), y “El enrutamiento internacionalizado no se integra con output: 'export'”. Las exportaciones estáticas necesitan el enfoque App Router o una configuración diferente.
Cuánto te cuesta la ruta del código
La ruta del código es la opción correcta para la interfaz de usuario de un producto cuyas cadenas viven en componentes. Se vuelve caro para todo lo demás:
- Contenido fuera de tu código (un CMS sin interfaz gráfica, feeds de productos, contenido generado por el usuario) necesita su propio flujo de traducción.
- Cada nueva cadena necesita una clave y una traducción en todos los idiomas antes de su lanzamiento.
- Los no desarrolladores no pueden arreglar una traducción sin una solicitud de extracción, a menos que agregue una herramienta de gestión de traducción.
- Más idiomas significan más archivos para mantenerse sincronizado.
Opción 2: Traducir un sitio Next.js sin cambiar tu código
Un servicio de traducción de sitios web como ConveyThis traduce el HTML que representa su aplicación Next.js, por lo que no crea diccionarios ni cambia rutas.
Paso 1: Crea una cuenta y agrega tu dominio
Crea una cuenta ConveyThis, agregue su dominio y elija sus idiomas de origen y de destino.
Paso 2: agrega el script a tu diseño raíz
ConveyThis le proporciona una URL de script con su clave API. En el enrutador de aplicaciones, agréguelo una vez app/layout.tsx con next/script:
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://cdn.conveythis.com/javascript/conveythis.js?api_key=YOUR_API_KEY"
strategy="afterInteractive"
/>
</body>
</html>
);
}El widget observa los cambios de página y la navegación del lado del cliente, por lo que el contenido que React representa después de la primera carga y las rutas que cambian sin una recarga completa también se traducen. También establece la página lang atributo al idioma que se muestra. Los pasos generales son los mismos que en nuestro Artículo de ayuda para la traducción de React y el JavaScript guía de integración.
Paso 3: Elija una estructura de URL compatible con SEO
Un script que intercambia texto en el navegador es suficiente para los visitantes, pero los motores de búsqueda necesitan una URL separada para cada idioma para indexarlo. En el panel ConveyThis, elija Subdominio (fr.example.com) o Subdirectorio (example.com/fr/) bajo estructura de URL. Luego, las páginas traducidas se sirven en sus propias URL con etiquetas hreflang agregadas. Para un sitio personalizado, el subdominio suele ser la opción más sencilla: su host Next.js sigue sirviendo el dominio principal y usted agrega un registro CNAME por idioma, mientras que el subdirectorio significa enrutar todo el dominio a través de ConveyThis. Ambas opciones están en el plan de negocios y arriba; el Artículo de ayuda sobre subdominios y subdirectorios explica los registros DNS que cada uno necesita. Si su dominio ya está en Cloudflare, el Configuración de Cloudflare Workers (O2O) mantiene tu zona en su lugar.
Paso 4: Revisar y perfeccionar las traducciones
La traducción automática le proporcionará una primera versión completa en minutos. Luego utilice el editor visual para ajustar la redacción en contexto, agregar términos de marca al glosario e invitar a un traductor o colega con roles de equipo. Consulte la lista completa en página de características.
¿Ruta con código o ruta sin código?
| Enrutador de aplicaciones i18n (código) | ConveyThis (sin código) | |
|---|---|---|
| Configuración | Reestructurar rutas, agregar proxy, diccionarios, metadatos | Una etiqueta de script más DNS para URL de SEO |
| De dónde viene el texto | Tus diccionarios | Cualquiera que sea la representación de la página, incluido el contenido del CMS |
| Quien edita las traducciones | Desarrolladores (o un TMS) | Cualquiera con acceso al panel de control |
| hreflang | Lo agregas con alternates | Agregado con URL de subdirectorio o subdominio |
| Mejor para | Cadenas de interfaz de usuario de la aplicación, control total | Sitios de marketing, contenido CMS, muchos idiomas |
| Costo | Tiempo de desarrollador | Plan basado en palabras e idiomas (Precios) |
Muchos equipos los combinan: i18n basado en código para la aplicación iniciada, un servicio de traducción para el sitio de marketing y un centro de ayuda.
Lista de verificación de SEO multilingüe para Next.js
- Una URL por idioma (
/fr/…ofr.example.com), nunca la misma URL para todos los idiomas. <html lang>coincide con el idioma de la página.- Título y meta descripción traducidos para cada idioma.
- Canónico en cada página traducida apunta a sí mismo, no a la página en inglés.
- Hreflang enumera todas las versiones de idioma, incluida la página en sí, además
x-default. - El mapa del sitio incluye todas las URL de idiomas.
- Un selector de idioma visible con enlaces reales, no solo un menú desplegable que cambia de estado.
- No hay redirecciones forzadas que se alejen del idioma solicitado por el visitante.
Para obtener una visión más amplia, lea nuestro Descripción general del SEO multilingüe.
Preguntas frecuentes
¿Next.js tiene traducción incorporada? Se ha incorporado la internacionalización enrutamiento en Pages Router y patrones i18n documentados para App Router. El texto traducido en sí proviene de sus diccionarios, una biblioteca o un servicio de traducción.
¿Qué pasó con middleware.js? En Next.js 16, el middleware La convención de archivos quedó obsoleta y se le cambió el nombre a proxy. La lógica para la detección local es la misma.
¿Next.js agrega etiquetas hreflang automáticamente? No. Uso alternates.languages en los metadatos del enrutador de aplicaciones, o next/head en el enrutador de páginas.
¿Puedo traducir un sitio Next.js exportado estáticamente? El enrutamiento del enrutador Pages i18n no funciona con output: 'export', y el proxy no es compatible con exportaciones estáticas. Utilice pregenerado [lang] rutas, o un servicio de traducción que sirve páginas traducidas desde su propio subdirectorio o subdominio.
¿Quieres que tu sitio Next.js esté en varios idiomas esta semana en lugar del próximo trimestre? Crea una cuenta ConveyThis, agregue el script a su diseño raíz y elija la estructura de URL que se ajuste a su plan de SEO.