# General Translation React SDKs (gt-react, gt-next, gt-react-native): createNextMiddleware
URL: https://generaltranslation.com/en-US/docs/react/nextjs/reference/functions/create-next-middleware.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Add locale routing and detection to a Next.js app with General Translation. API reference for createNextMiddleware.

The `createNextMiddleware` function from `gt-next/middleware` detects each visitor's locale, persists it in a cookie, and routes them to the localized version of a page.

Use the [App Router middleware guide](/docs/react/nextjs/app-router-middleware) for the current setup. Pages Router apps use [Next.js internationalized routing](/docs/react/nextjs/pages-router-middleware) instead.

*Middleware is optional when you do not need request-time locale detection or locale-prefixed URLs. Without it, locale selectors keep URLs unprefixed, store the selected locale in a cookie, and refresh the App Router content.*

## Overview [#overview]

Create the middleware and export it, along with a path matcher, from your middleware file. Place it in your project root — `proxy.ts` on Next.js 16+, or `middleware.ts` on Next.js 15 and below — not inside `app/` or `pages/`.

```ts title="proxy.ts"
import { createNextMiddleware } from 'gt-next/middleware';

export default createNextMiddleware();

export const config = {
  // Match all paths except API routes, static files, and Next.js internals
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

## How it works [#how-it-works]

The middleware resolves each request's locale from these sources, in order:

1. **Reset locale cookie** — the locale just selected in the browser, while a locale-routing reset is pending.
2. **URL locale** — a supported locale prefix, such as `/es/about`, or a configured unprefixed default-locale path.
3. **Locale cookie** — the visitor's previously selected locale when no reset is pending.
4. **Referrer locale cookie** — the locale from the previous client route when no reset is pending.
5. **Browser headers** — the `Accept-Language` header, unless [`ignoreBrowserLocales`](/docs/react/nextjs/config#ignore-browser-locales) is enabled.
6. **Default locale** — your configured `defaultLocale` as the fallback.

It then sets a locale cookie and, when `localeRouting` is enabled, redirects or rewrites to the correct localized path. By default the `defaultLocale` is not prefixed (`/about` stays `/about`), while other locales are (`/es/about`). Locale codes are standardized to canonical form when General Translation services are enabled, and unsupported configured locales produce a build-time warning.

## Options [#options]

`createNextMiddleware` takes a single options object. All fields are optional.

| Option | Description | Type | Optional | Default |
| --- | --- | --- | --- | --- |
| [`localeRouting`](#locale-routing) | Enable locale-based routing. | `boolean` | Yes | `true` |
| [`prefixDefaultLocale`](#prefix-default-locale) | Prefix the default locale in the URL too. | `boolean` | Yes | `false` |
| [`ignoreSourceMaps`](#ignore-source-maps) | Skip Next.js source-map requests. | `boolean` | Yes | `true` |
| [`pathConfig`](#path-config) | Localized path aliases. | `object` | Yes | `{}` |
| [`routeOverrides`](#route-overrides) | Use a locale-specific page implementation without changing its public URL. | `RouteOverrides` | Yes | `{}` |

*Note: to restrict which pathnames the middleware runs on, set [`pathRegex`](/docs/react/nextjs/config#path-regex) in `withGTConfig` — it is not a middleware option. The `matcher` in your exported `config` is what Next.js uses to decide when the middleware runs at all.*

### `localeRouting` [#locale-routing]

**Type** `boolean` · **Optional** · **Default** `true`

Enables locale-based routing and redirects. When `false`, the middleware still detects and stores the locale but does not add locale prefixes or rewrite paths.

### `prefixDefaultLocale` [#prefix-default-locale]

**Type** `boolean` · **Optional** · **Default** `false`

When `false` (the default), the default locale is served without a prefix (`/about`) while other locales are prefixed (`/es/about`). When `true`, every locale is prefixed, including the default (`/en/about`).

### `ignoreSourceMaps` [#ignore-source-maps]

**Type** `boolean` · **Optional** · **Default** `true`

When `true`, requests for Next.js source maps are passed through untouched.

### `pathConfig` [#path-config]

**Type** `object` · **Optional** · **Default** `{}`

Maps shared paths to localized paths, so a route can have a different URL per locale. Each key is the shared path; each value is either a single localized path or a per-locale map.

```ts title="proxy.ts"
export default createNextMiddleware({
  pathConfig: {
    // English: /products, French: /fr/produits
    '/products': {
      fr: '/produits',
    },
    // Dynamic: /product/123, /fr/produit/123
    '/product/[id]': {
      fr: '/produit/[id]',
    },
    // Required catch-all: /blog/2026/launch, /fr/articles/2026/launch
    '/blog/[...slug]': {
      fr: '/articles/[...slug]',
    },
    // Optional catch-all: /news or /news/latest, /fr/actualites or /fr/actualites/latest
    '/news/[[...slug]]': {
      fr: '/actualites/[[...slug]]',
    },
  },
});
```

### `routeOverrides` [#route-overrides]

**Type** `RouteOverrides` · **Optional** · **Default** `{}`

Maps a locale to shared route patterns that have a locale-specific page implementation. The public URL still uses the shared route or its [`pathConfig`](#path-config) alias, while the middleware rewrites the request to a route with a second, static locale segment.

For example, this file structure gives French visitors custom implementations of a static page, a dynamic product page, and a family of blog pages:

<Files>
  <Folder name="app">
    <Folder name="[locale]">
      <Folder name="home">
        <File name="page.tsx" />
      </Folder>
      <Folder name="fr">
        <Folder name="home">
          <File name="page.tsx" />
        </Folder>
        <Folder name="product">
          <Folder name="[id]">
            <File name="page.tsx" />
          </Folder>
        </Folder>
        <Folder name="blog">
          <File name="page.tsx" />
          <Folder name="authors">
            <File name="page.tsx" />
          </Folder>
          <Folder name="posts">
            <File name="page.tsx" />
            <Folder name="[...slug]">
              <File name="page.tsx" />
            </Folder>
          </Folder>
        </Folder>
      </Folder>
    </Folder>
  </Folder>
</Files>

Configure each override with its shared route pattern:

```ts title="proxy.ts"
export default createNextMiddleware({
  routeOverrides: {
    fr: [
      '/home', // Static route
      '/product/[id]', // Dynamic param
      '/blog/[[...slug]]', // Route and all child paths
    ],
  },
});
```

- `/home` uses `app/[locale]/fr/home/page.tsx` for French and the shared `app/[locale]/home/page.tsx` for other locales.
- `/product/[id]` adds a product page only for French while preserving the dynamic `id`.
- `/blog/[[...slug]]` adds a blog family only for French, including `/blog`, `/blog/authors`, `/blog/posts`, and `/blog/posts/[...slug]`.

Overrides are ignored when `localeRouting` is `false`. Locale keys are standardized when General Translation services are enabled.

<Callout type="info">
  Cache and layout APIs see the internal route. Pass the rewrite destination, such as `/fr/fr/home`, to Next.js `revalidatePath`. From the `[locale]` layout, `useSelectedLayoutSegments` also includes the override's static locale segment.
</Callout>

Use [`<Link>`](/docs/react/nextjs/link) from `gt-next/link` for internal navigation so locale-prefixed routes are generated before navigation without an extra middleware redirect.

## Example [#example]

```ts title="proxy.ts"
import { createNextMiddleware } from 'gt-next/middleware';

export default createNextMiddleware({
  prefixDefaultLocale: true,
  pathConfig: {
    '/about': {
      fr: '/a-propos',
    },
  },
});

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

*Warning: test your matcher carefully. An overly broad matcher can cause redirect loops or break static assets.*

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
