# General Translation Knowledge Base: How do I add i18n to a Next.js App Router app?
URL: https://generaltranslation.com/en-US/kb/add-i18n-to-nextjs.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Start with gt init to configure General Translation in a supported App Router project, then mark source content, generate translations, and verify language switching. gt-next keeps copy in JSX with translation context; the CLI, Dashboard editor, and Locadex handle generation, review, and ongoing updates. This guide also shows the explicit local-file setup.
Category: Internationalization
Last updated: 2026-10-21
Authors: Kevin Liu, Kevin Wu
Published: 2026-10-21

This walkthrough adds English, Spanish, and French to a small project page. It covers a Server Component, a Client Component, and a language switcher. It uses cookie-based language selection; locale-prefixed URLs and multilingual SEO are a separate step.

General Translation's `gt-next` is built for Next.js App Router. It keeps source copy in the JSX that gives it meaning and connects that content to translation generation. Use the [`context` prop](/docs/react/reference/components/t#context) to explain ambiguous wording, and assign [Glossary terms and Custom Prompts](/docs/platform/dashboard/guides/defining-context-for-translations) for terminology and tone. The build workflow below then updates translations as the source changes.

## Video

The video is narrated in English, with English captions.

[How do I add i18n to a Next.js app?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-add-i18n-to-nextjs.mp4) (51 sec)

General Translation lets you add i18n with `gt-next`: wrap text in `T` and generate translations. Wrap your config in `withGTConfig`, list your languages, add a `loadTranslations` file, put the `GTProvider` in your root layout, add a `<LocaleSelector>` for the menu, and run `npx gt translate` before `next build`.

## Before you start

Use an existing TypeScript App Router project with a `src/app` directory. The examples target Next.js 16 and use npm. Next.js 16 requires Node.js 20.9 or later. If you are starting from scratch, first follow the [Next.js installation guide](https://nextjs.org/docs/app/getting-started/installation). Pages Router apps should use the [Pages Router quickstart](/docs/react/nextjs-pages-router-quickstart).

The explicit example uses `gt-next@11.4.12` and `gt@2.26.5`. The MIT-licensed library can render translations you supply without an account. For service-generated translations, use a GT project and [CLI login or a scoped tooling key](/docs/cli/guides/configuring#credentials). Use a key from your CI secret store for automated builds.

## Start with the setup command

Run the setup wizard in the app directory:

```bash
npx gt@2.26.5 init
```

Choose the React framework setup for your App Router app, source and target languages, and local or CDN delivery. The wizard installs `gt-next`, adds [`GTProvider`](/docs/react/reference/components/gt-provider) and [`withGTConfig`](/docs/react/nextjs/config), and creates `gt.config.json`. With local delivery, it also creates a translation loader. The framework rewrite is experimental; review the generated diff, especially around existing providers and configuration wrappers. [Setup reference](/docs/cli/reference/commands/init).

You still mark the application content and generate its translations. If you prefer a coding agent to carry the task through verification, use [Setup for Agents](https://generaltranslation.com/agent-prompt.md).

The explicit setup below uses `src/_gt/[locale].json`. The wizard's default local output is `public/_gt/[locale].json`; keep its generated loader and output path together, or follow the explicit setup as a complete alternative.

## Configure the library explicitly and write the page

### 1. Install the SDK and CLI

Run these commands in the application directory:

```bash
npm install gt-next@11.4.12
npm install --save-dev gt@2.26.5
```

`gt-next` renders translations in the application. `gt` is the command-line tool used to collect and translate source content. [Official Next.js quickstart](/docs/react/nextjs-quickstart).

### 2. Configure Next.js and your languages

Wrap your existing Next.js configuration with [`withGTConfig`](/docs/react/nextjs/config). Keep any existing settings and integrate this with other configuration wrappers you already use.

```ts title="next.config.ts"
import { withGTConfig } from 'gt-next/config';

export default withGTConfig({});
```

Create this file at the project root:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr"],
  "files": {
    "gt": {
      "output": "src/_gt/[locale].json"
    }
  }
}
```

English is the source language. Spanish and French are the target languages. The output path tells the CLI where to write generated translations.

### 3. Add a local translation loader

Create `src/loadTranslations.ts`. The configuration plugin detects this file and uses it to load the generated locale files:

```ts title="src/loadTranslations.ts"
export default async function loadTranslations(locale: string) {
  const translations = await import(`./_gt/${locale}.json`);
  return translations.default;
}
```

This setup bundles translations with the application, so production needs no runtime calls to General Translation for this content. Translation updates ship with the build. [Local translation storage](/docs/react/guides/storing-translations).

The files do not exist yet. Complete the page and generate them in step 6 before starting the dev server; otherwise the loader's import can fail.

### 4. Add the provider to your root layout

Adapt `src/app/layout.tsx` as shown below. Preserve your existing styles, fonts, metadata, and other providers.

```tsx title="src/app/layout.tsx"
import type { PropsWithChildren } from 'react';
import { GTProvider } from 'gt-next';
import { getLocale } from 'gt-next/server';

export default async function RootLayout({ children }: PropsWithChildren) {
  const locale = await getLocale();

  return (
    <html lang={locale}>
      <body>
        <GTProvider>{children}</GTProvider>
      </body>
    </html>
  );
}
```

[`getLocale`](/docs/react/nextjs/reference/functions/get-locale) resolves the current language on the server. [`GTProvider`](/docs/react/reference/components/gt-provider) supplies the translation context for the application, including its interactive components.

### 5. Translate JSX and input attributes

Add the page below. It remains a Server Component. [`T`](/docs/react/reference/components/t) marks the static heading and paragraph for translation; [`LocaleSelector`](/docs/react/reference/components/locale-selector) supplies the language dropdown.

```tsx title="src/app/page.tsx"
import { LocaleSelector, T } from 'gt-next';
import SearchBox from './SearchBox';

export default function Home() {
  return (
    <main>
      <LocaleSelector />
      <T>
        <h1>Find your next project</h1>
        <p>Explore projects from teams around the world.</p>
      </T>
      <SearchBox />
    </main>
  );
}
```

Create the search input as a Client Component. Use [`useGT`](/docs/react/reference/hooks/use-gt) for string-valued attributes such as placeholders and accessible labels:

```tsx title="src/app/SearchBox.tsx"
'use client';

import { useGT } from 'gt-next';

export default function SearchBox() {
  const gt = useGT();

  return (
    <input
      type='search'
      placeholder={gt('Search projects')}
      aria-label={gt('Search projects')}
    />
  );
}
```

[`useGT()`](/docs/react/reference/hooks/use-gt) returns the translation function directly. In an async Server Component, use [`getGT`](/docs/react/nextjs/reference/functions/get-gt) from `gt-next/server` instead.

Keep dynamic values out of raw expressions inside [`T`](/docs/react/reference/components/t). When adding names, counts, or branches, use the appropriate [variable and formatting components](/docs/react/guides/formatting-variables).

## Generate translations and verify the result

### 6. Create the translated output

For automatic translation, sign in with [`gt login`](/docs/cli/reference/commands/login) and configure the project ID, or put a project API key and project ID in `.env.local`:

```bash title=".env.local"
GT_PROJECT_ID="your-project-id"
GT_API_KEY="your-project-api-key"
```

Keep the key private and the file out of source control. Do not expose `GT_API_KEY` through a `NEXT_PUBLIC_` variable. The tooling key needs file read/write and translation-queue permissions, plus context access when used. Follow the [API key documentation](/docs/platform/dashboard/reference/api-keys).

Generate translations:

```bash
npx gt translate
```

The command submits translation work to General Translation and writes locale files to the configured output path. Review generated text in the [Dashboard Translation Editor](/docs/platform/dashboard/guides/reviewing-translations). If you edit downloaded translations locally, [`gt save-local`](/docs/cli/reference/commands/save-local) syncs those corrections back to the platform. Service generation uses [usage-based pricing](https://generaltranslation.com/pricing).

If you want to try the library without calling the translation service, run this instead:

```bash
npx gt generate
```

[`gt generate`](/docs/cli/reference/commands/generate) creates templates containing source text; **it does not translate that text**. Edit the text values in `src/_gt/es.json` and `src/_gt/fr.json`, preserving the generated keys and JSX structure. For example, translate the Spanish heading to “Encuentra tu próximo proyecto” and the search label to “Buscar proyectos.” Translate the remaining text before treating those files as complete.

After changing source content, rerun [`gt generate`](/docs/cli/reference/commands/generate) and review the target files. It preserves existing target values, adds new entries with source text, and removes entries no longer present in the source.

### 7. Start the app and switch languages

```bash
npm run dev
```

Open the address printed by Next.js. Select Spanish and French in the dropdown. Confirm that the heading, paragraph, placeholder, and accessible input label change. Reload the page to check that the selected language persists, then switch back to English.

If the selector changes but the text stays English, inspect the target-language files. Source templates from [`gt generate`](/docs/cli/reference/commands/generate) still contain English until you translate them. If the page fails to compile because a locale file is missing, rerun the appropriate generation command before restarting development.

## Build for production

Run [`gt validate`](/docs/cli/reference/commands/validate) to catch translation syntax errors before a hosted translation request. GT's [ESLint rules](/docs/react/guides/linting-your-code) provide additional development checks. With [development translation configured](/docs/react/guides/configuring#delivery), you can also preview translated content while editing.

For the automatic translation workflow, merge this build command into your existing `package.json` scripts:

```json
{
  "scripts": {
    "build": "gt validate && gt translate && next build"
  }
}
```

Set `GT_PROJECT_ID` and `GT_API_KEY` in the build environment. Ensure the CLI, installed as a development dependency, is available during that build. Add `src/_gt/` to `.gitignore` if your build regenerates its translation output every time.

If you chose manual translation, keep your translated files in version control or retrieve them from your own translation pipeline. Use `next build` after those files are available. Do not discard the only copy of manually maintained translations by ignoring them as reproducible output.

After building, run the production app and repeat the language-switch check. This tests the files that will actually ship, rather than relying only on development behavior.

The [incremental translation workflow](/docs/cli/guides/generating-translations#retranslate) translates changed source and reuses matching translations from earlier versions. To automate repository changes as well, configure [Locadex](/docs/platform/locadex/guides/configuring-automations) to internationalize new UI, generate translations, or synchronize locale changes through pull requests. Use the trigger and review settings that fit your release process.

For updates independent of an application rebuild, choose [CDN delivery](/docs/react/nextjs/config) instead of the local loader. Published translation edits can then reach the deployed application according to its version and cache settings.

For public pages that need separate language URLs, continue with [App Router locale routing](/docs/react/nextjs/app-router-middleware). The cookie-based example here does not create `/es` and `/fr` pages or configure canonical URLs and `hreflang` metadata.

## A prompt for your coding agent

Start with the maintained [official setup prompt](https://generaltranslation.com/agent-prompt.md), then add this feature brief:

```text
Use English as the source language, with Spanish and French as targets.
Localize the project page using locally bundled translations. Preserve the
existing providers and routes. Include its heading, paragraph, search input,
accessible label, and a language selector. Use the project's shared terminology.
Verify language switching, reload persistence, server-rendered content,
client attributes, and the production build. Report what was actually tested
and what still needs language review. Do not deploy or merge.
```

For the broader workflow, read [i18n without translation files](/kb/i18n-without-translation-files) and [using a coding agent](/kb/ai-agent-i18n-setup).

## Related questions

- [Can I do i18n without translation files?](https://generaltranslation.com/en-US/kb/i18n-without-translation-files.mdx): Yes. General Translation's gt-react and gt-next libraries do React and Next.js i18n with no translation keys and no JSON file per language to maintain. Copy stays inline in JSX inside the `<T>` component, and the gt translate command generates each language's translations in your build, with context from your code. Locadex can keep them current through pull requests.
- [How do I internationalize an app with Cursor or Claude Code?](https://generaltranslation.com/en-US/kb/ai-agent-i18n-setup.mdx): Start with General Translation's Setup for Agents prompt in Cursor or Claude Code, choose a feature and target languages, and have the agent implement and verify the result. Browser sign-in, machine-readable docs, and MCP tools connect setup to translation and review. Use Locadex to automate continuing localization through pull requests.
- [How do I keep translations up to date on every deploy?](https://generaltranslation.com/en-US/kb/translations-in-ci.mdx): Run translation as a pipeline step before each production build, so new copy ships translated with the deploy that adds it. General Translation's gt CLI does this with npx gt translate, using a project API key and project ID stored as CI secrets.

## Previous and next questions

- Previous question: [Why use General Translation instead of a TMS (Smartling, Lokalise, Phrase, Crowdin, or Transifex)?](https://generaltranslation.com/en-US/kb/general-translation-vs-tms.mdx)
- Next question: [How do I format numbers, dates, and currencies for each locale?](https://generaltranslation.com/en-US/kb/format-numbers-dates-currencies.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/en-US/kb/sitemap.md) for every article.
