Skip to main content

Next.js

The translate-projects-nextjs package has two parts: a command that translates your JSON files and utilities for using them in Next.js (App Router): language middleware, an i18next provider, Link, and hooks with autocompletion.

Requirements​

  • Node.js 20 or higher.
  • Next.js 14 or higher and React 18 or higher. They are peer dependencies: the package uses the ones from your project.
  • A Translate Projects project and an API token. See Getting started.

1. Install the package​

Terminal
npm i translate-projects-nextjs

i18next and react-i18next are installed with the package.

2. Write your texts​

Put the base language texts in src/locales/<base language>/. Each JSON file (including in subfolders) is an i18next namespace, and the nesting is preserved:

src/locales/es/translation.json
{
"home": {
"title": "Bienvenido"
}
}

3. Configure the translation​

Create translate.config.mjs in the root. The API token is read from the environment variable TRANSLATE_PROJECTS_API_KEY:

translate.config.mjs
export default {
sourceLang: 'es', // Base language: the default language of the project
targetLangs: ['en', 'pt-BR', 'fr'], // Languages to generate
apiKey: process.env.TRANSLATE_PROJECTS_API_KEY,
// outputDir: './src/locales', // Default value
// scanner: true, // Optional: extract t('...') and <Trans> from ./src
};

Add the script to package.json:

package.json
{
"scripts": {
"translate": "translate-projects-nextjs translate"
}
}

4. Translate​

Terminal
export TRANSLATE_PROJECTS_API_KEY=tu_token
npm run translate

The command does not read .env files on its own: export the variable in the terminal or in CI, or load it yourself, for example with node --env-file=.env.local node_modules/.bin/translate-projects-nextjs translate. It exits with code 0 if all languages were translated and with 1 on any error.

Files it generates​

src/locales/
├── es/translation.json ← your base language
├── en/translation.json ← generated
├── pt-BR/translation.json
└── fr/translation.json

Commit the generated files: the app imports them when building. Do not edit them by hand, they are overwritten on the next run. With the scanner enabled, <base language>/translation.json is also overwritten with the texts found in the code.

5. Use the translations in Next.js​

Middleware​

Redirects to /<language>/... and stores the language in the NEXT_LOCALE cookie. The routes /_next, /api, /locales, and /favicon.ico are always ignored.

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', 'pt-BR', 'fr'],
ignorePaths: ['/images'], // Optional
});
}

Provider​

app/[locale]/layout.tsx
import { TranslationsProvider } from 'translate-projects-nextjs/provider';
import es from '@/locales/es/translation.json';
import en from '@/locales/en/translation.json';

export default async function Layout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;

return (
<html lang={locale}>
<body>
<TranslationsProvider
lng={locale as any}
initialLocale={locale as any}
i18nConfig={{
fallbackLng: ['es'],
supportedLngs: ['es', 'en'],
resources: {
es: { translation: es },
en: { translation: en },
},
}}
>
{children}
</TranslationsProvider>
</body>
</html>
);
}

Texts with autocompletion​

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('home.title')}</h1>; // Keys are autocompleted
}

useTranslation and <Trans> from react-i18next also work.

app/[locale]/nav.tsx
'use client';
import { Link } from 'translate-projects-nextjs/link';
import { useLocalizedRouter } from 'translate-projects-nextjs/hooks';

export function Nav() {
const router = useLocalizedRouter();
return (
<>
<Link href="/about">About</Link> {/* -> /<locale>/about */}
<button onClick={() => router.push('/', undefined, 'en')}>English</button>
</>
);
}

Cache and force​

Unchanged files are not sent or translated again: a run with no changes makes a single request. If you delete a generated file, it is rewritten from the cache without new requests. This package has no --force: to translate everything again, delete ~/.config/translate-projects-core/cache.json (this affects all projects on the team, and each one is synced once) and run again. More details in Cache and errors.

Common errors​

If the API fails or returns a partial result, existing translations are kept, the command exits with code 1, and the missing texts are retried on the next run.

  • Invalid token (401): check TRANSLATE_PROJECTS_API_KEY.
  • Missing AI key (MISSING_API_KEY): configure the provider, the model, and the key in the project. In the meantime, untranslated texts are not written to the file and i18next shows the text from fallbackLng.
  • Missing required configuration fields: apiKey: the variable TRANSLATE_PROJECTS_API_KEY is not defined in the terminal where you run the command.
  • translate.config.mjs not found: the command must be run in the root of the project.
  • Dependency conflict when installing: check that your project uses Next.js 14 or higher and React 18 or higher.
Free

🚀 Automate your translations for free​

Translate Projects is free. You create your project, connect your AI provider's key, and only pay them what you spend.

  • No plans or credit card required: All features are available from day one.
  • Use your own AI: Claude, OpenAI, DeepSeek, or Gemini. Your key is stored encrypted.
  • Shared translation network: If a text has already been translated, you receive it instantly without spending your key.
  • Admin panel: Review and edit all your translations from one place.

Create free account →

Support

We're here to help​

If you have any questions, need help, or want to contribute, don't hesitate to contact me. I'm available to support you with whatever you need.

Support the Project​

If this project has been helpful to you, I invite you to buy me a coffee. Your support helps me keep improving and creating valuable content. Thanks for being here! ☕

Buy me a coffee