← Blog

Cómo traducir una app de Next.js (App Router) a varios idiomas con i18next

Guía paso a paso: traduce tu app de Next.js del español a inglés, japonés, portugués y francés con npm run translate e i18next. Con la salida real.

· 3 min de lectura

Casi todos los proyectos de Next.js con i18n acaban igual: un translation.json en español y una tarde copiándolo en ChatGPT, pegando la respuesta y revisando que no se haya cambiado ninguna clave. Luego alguien añade un texto y vuelta a empezar.

En esta guía traducimos una app de Next.js (App Router) del español a inglés, japonés, portugués y francés con un solo comando, npm run translate, usando i18next y el paquete translate-projects-nextjs. Todo lo que ves abajo (archivos y terminal) es la salida real de una ejecución.

Qué necesitas

  • Node.js 20 o superior, Next.js 14+ y React 18+.
  • Una cuenta gratis de Translate Projects con un proyecto y su API token (Primeros pasos).
  • La API key de tu proveedor de IA: Claude, OpenAI, DeepSeek o Gemini. No hay planes ni tarjeta: pagas solo a tu proveedor por lo que uses.

1. Instala el paquete

npm i translate-projects-nextjs

i18next y react-i18next se instalan con el paquete.

2. Escribe tus textos en el idioma base

Cada archivo JSON dentro de src/locales/<idioma base>/ es un namespace de i18next, y el anidamiento se conserva. Este es el archivo de la app de ejemplo:

// src/locales/es/translation.json
{
  "nav": {
    "inicio": "Inicio",
    "precios": "Precios"
  },
  "hero": {
    "titulo": "Organiza tus tareas sin perder el ritmo",
    "subtitulo": "Planifica tu semana, comparte proyectos con tu equipo y recibe recordatorios a tiempo.",
    "boton": "Empieza gratis"
  },
  "login": {
    "email": "Correo electrónico",
    "password": "Contraseña",
    "entrar": "Iniciar sesión",
    "olvido": "¿Olvidaste tu contraseña?"
  }
}

3. Configura los idiomas

Crea translate.config.mjs en la raíz del proyecto. El token se lee de la variable de entorno TRANSLATE_PROJECTS_API_KEY:

export default {
  sourceLang: 'es',
  targetLangs: ['en', 'ja', 'pt-BR', 'fr'],
  apiKey: process.env.TRANSLATE_PROJECTS_API_KEY,
};

Y añade el script en package.json:

{
  "scripts": {
    "translate": "translate-projects-nextjs translate"
  }
}

4. Traduce

export TRANSLATE_PROJECTS_API_KEY=tu_token
npm run translate

Salida real de la ejecución (sin las marcas de tiempo):

✅ Success: Total languages to translate: 4
ℹ️  Info: 🔄 Syncing (9) - src/locales/es/translation.json...
✅ Success: Translation completed: EN 📄 -> 📁 `src/locales/en/translation.json`
✅ Success: Translation completed: JA 📄 -> 📁 `src/locales/ja/translation.json`
✅ Success: Translation completed: PT-BR 📄 -> 📁 `src/locales/pt-BR/translation.json`
✅ Success: Translation completed: FR 📄 -> 📁 `src/locales/fr/translation.json`
✅ Success: Translation completed successfully.

Nueve textos a cuatro idiomas tardaron unos 14 segundos. Así queda el inglés, con las mismas claves:

// src/locales/en/translation.json
{
  "nav": {
    "inicio": "Home",
    "precios": "Pricing"
  },
  "hero": {
    "titulo": "Organize your tasks without losing momentum",
    "subtitulo": "Plan your week, share projects with your team and get reminders on time.",
    "boton": "Start for free"
  },
  "login": {
    "email": "Email",
    "password": "Password",
    "entrar": "Sign in",
    "olvido": "Forgot your password?"
  }
}

Y el japonés:

// src/locales/ja/translation.json
{
  "nav": {
    "inicio": "ホーム",
    "precios": "料金"
  },
  "hero": {
    "titulo": "ペースを崩さずタスクを整理しよう",
    "subtitulo": "週間計画を立て、チームとプロジェクトを共有し、期限に合わせてリマインダーを受け取れます。",
    "boton": "無料で始める"
  },
  "login": {
    "email": "メールアドレス",
    "password": "パスワード",
    "entrar": "ログイン",
    "olvido": "パスワードをお忘れですか?"
  }
}

El comando no lee .env por sí solo: exporta la variable en la terminal o en CI, o cárgala con node --env-file=.env.local node_modules/.bin/translate-projects-nextjs translate.

5. Usa las traducciones en Next.js

El paquete trae también la parte de la app: un middleware que redirige a /<idioma>/... y guarda la cookie NEXT_LOCALE, un provider de i18next, un Link localizado y hooks con autocompletado de claves.

// middleware.ts
import { NextRequest } from 'next/server';
import { langMiddleware } from 'translate-projects-nextjs/middleware';

export function middleware(request: NextRequest) {
  return langMiddleware({
    request,
    defaultLocale: 'es',
    locales: ['es', 'en', 'ja', 'pt-BR', 'fr'],
  });
}
// app/[locale]/title.tsx
'use client';
import { useTypedTranslation } from 'translate-projects-nextjs/hooks';
import type es from '@/locales/es/translation.json';

export function Title() {
  const { t } = useTypedTranslation<typeof es>();
  return <h1>{t('hero.titulo')}</h1>; // las claves se autocompletan
}

El provider (TranslationsProvider) va en app/[locale]/layout.tsx; el código completo está en la guía de Next.js. useTranslation y <Trans> de react-i18next también funcionan.

Cómo evita traducir dos veces

  • Solo se envían los archivos que cambiaron: una ejecución sin cambios hace una sola petición.
  • Hay una red compartida de traducciones: si un texto ya se tradujo antes a ese idioma, llega al instante sin gastar tu key de IA.
  • Si borras un archivo generado, se vuelve a escribir desde la caché sin peticiones nuevas.
  • Si la API falla, las traducciones existentes se conservan, el comando sale con código 1 y lo que falte se reintenta en la siguiente ejecución.

Errores comunes

  • Token inválido (401): revisa TRANSLATE_PROJECTS_API_KEY.
  • Missing required configuration fields: apiKey: la variable no está definida en la terminal donde corres el comando.
  • Falta la key de IA (MISSING_API_KEY): configura proveedor, modelo y key en el proyecto.
  • No encuentra translate.config.mjs: ejecuta el comando en la raíz del proyecto.

También hay paquetes para React, Astro, Docusaurus (npm) y Django (PyPI). Crea tu proyecto gratis en translateprojects.dev y traduce tu app hoy.