# General Translation React SDKs (gt-react, gt-next, gt-react-native): createNextMiddleware
URL: https://generaltranslation.com/zh/docs/react/nextjs/reference/functions/create-next-middleware.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 使用 General Translation 为 Next.js 应用添加区域设置路由和检测。createNextMiddleware 的 API 参考。

`gt-next/middleware` 中的 `createNextMiddleware` 函数会检测每位访客的区域设置，将其保存到 cookie 中，并将其路由到页面的本地化版本。

当前设置请参考 [App Router 中间件指南](/docs/react/nextjs/app-router-middleware)。Pages Router 应用则改用 [Next.js 国际化路由](/docs/react/nextjs/pages-router-middleware)。

*如果你不需要在请求时检测区域设置，也不需要带区域设置前缀的 URL，则中间件是可选的。不使用中间件时，区域设置选择器会保持 URL 不带前缀，将所选区域设置存入 cookie，并刷新 App Router 内容。*

## 概览 [#overview]

创建 `middleware`，并将它与路径匹配器一起从中间件文件中导出。把它放在项目根目录下——Next.js 16+ 使用 `proxy.ts`，Next.js 15 及以下版本使用 `middleware.ts`——不要放在 `app/` 或 `pages/` 中。

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

export default createNextMiddleware();

export const config = {
  // 匹配所有路径，但排除 API 路由、静态文件和 Next.js 内部路径
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

## 工作原理 [#how-it-works]

中间件会按以下顺序，从这些来源确定每个请求的区域设置：

1. **重置区域设置 Cookie** — 浏览器中刚选择的区域设置，此时区域设置路由重置正在等待完成。
2. **URL 区域设置** — 受支持的区域设置前缀，例如 `/es/about`，或已配置的不带前缀的默认区域设置路径。
3. **区域设置 Cookie** — 未等待重置时，访客之前选择的区域设置。
4. **来源页面区域设置 Cookie** — 未等待重置时，来自上一个客户端路由的区域设置。
5. **浏览器请求头** — `Accept-Language` 请求头，除非启用了 [`ignoreBrowserLocales`](/docs/react/nextjs/config#ignore-browser-locales)。
6. **默认区域设置** — 你配置的 `defaultLocale`，作为回退值。

随后，它会设置一个区域设置 Cookie；启用 `localeRouting` 时，还会重定向或重写到正确的本地化路径。默认情况下，`defaultLocale` 不带前缀 (`/about` 保持为 `/about`) ，而其他区域设置会带前缀 (`/es/about`) 。启用 General Translation 服务后，区域设置代码会标准化为规范格式，不受支持的已配置区域设置则会产生构建时警告。

## 选项 [#options]

`createNextMiddleware` 接收一个选项对象。所有字段均为可选。

| 选项                                              | 描述                            | 类型               | 可选 | 默认值     |
| ----------------------------------------------- | ----------------------------- | ---------------- | -- | ------- |
| [`localeRouting`](#locale-routing)              | 启用基于区域设置的路由。                  | `boolean`        | 是  | `true`  |
| [`prefixDefaultLocale`](#prefix-default-locale) | 也为 URL 中的默认区域设置添加前缀。          | `boolean`        | 是  | `false` |
| [`ignoreSourceMaps`](#ignore-source-maps)       | 跳过 Next.js 的 source-map 请求。   | `boolean`        | 是  | `true`  |
| [`pathConfig`](#path-config)                    | 本地化路径别名。                      | `object`         | 是  | `{}`    |
| [`routeOverrides`](#route-overrides)            | 在不更改公开 URL 的前提下使用特定区域设置的页面实现。 | `RouteOverrides` | 是  | `{}`    |

*注意：如果要限制中间件在哪些路径名上运行，请在 `withGTConfig` 中设置 [`pathRegex`](/docs/react/nextjs/config#path-regex)——它不是中间件选项。你在导出的 `config` 中配置的 `matcher` 才是 Next.js 用来决定是否运行中间件的依据。*

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

**类型** `boolean` · **可选** · **默认值** `true`

启用基于区域设置的路由和重定向。设为 `false` 时，中间件仍会检测并存储区域设置，但不会添加区域设置前缀，也不会重写路径。

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

**类型** `boolean` · **可选** · **默认值** `false`

当为 `false` (默认值) 时，默认区域设置的路径不带前缀 (`/about`) ，而其他区域设置的路径会带前缀 (`/es/about`) 。当为 `true` 时，所有区域设置的路径都会带前缀，包括默认区域设置 (`/en/about`) 。

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

**类型** `boolean` · **可选** · **默认值** `true`

当为 `true` 时，针对 Next.js source maps 的请求会直接透传，不做任何处理。

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

**类型** `object` · **可选** · **默认值** `{}`

将共享路径映射为本地化路径，使同一路由在不同区域设置下可以使用不同的 URL。每个键都是共享路径；每个值既可以是单个本地化路径，也可以是按区域设置分别指定的映射。

```ts title="proxy.ts"
export default createNextMiddleware({
  pathConfig: {
    // 英文：/products，法文：/fr/produits
    '/products': {
      fr: '/produits',
    },
    // 动态路由：/product/123，/fr/produit/123
    '/product/[id]': {
      fr: '/produit/[id]',
    },
    // 必需的通配路由：/blog/2026/launch，/fr/articles/2026/launch
    '/blog/[...slug]': {
      fr: '/articles/[...slug]',
    },
    // 可选的通配路由：/news 或 /news/latest，/fr/actualites 或 /fr/actualites/latest
    '/news/[[...slug]]': {
      fr: '/actualites/[[...slug]]',
    },
  },
});
```

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

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

将某个区域设置映射到拥有该区域设置专属页面实现的共享 路由 pattern。对外的 URL 仍然使用共享 路由 或其 [`pathConfig`](#path-config) 路径别名，而 中间件 会在内部将 请求 重写到带有第二个 静态 区域设置段的 路由。

例如，以下文件结构为法语访问者提供了一个静态页面、一个动态产品页面以及一组博客页面的自定义实现：

<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>

为每个 override 配置对应的共享 路由 pattern：

```ts title="proxy.ts"
export default createNextMiddleware({
  routeOverrides: {
    fr: [
      '/home', // 静态 路由
      '/product/[id]', // 动态参数
      '/blog/[[...slug]]', // 该 路由 及其所有 child 路径
    ],
  },
});
```

* `/home` 在法语下使用 `app/[locale]/fr/home/page.tsx`，其他区域设置则使用共享的 `app/[locale]/home/page.tsx`。
* `/product/[id]` 仅为法语添加产品页面，同时保留动态的 `id`。
* `/blog/[[...slug]]` 仅为法语添加一组博客路由，包括 `/blog`、`/blog/authors`、`/blog/posts` 以及 `/blog/posts/[...slug]`。

当 `localeRouting` 为 `false` 时，overrides 将被忽略。启用 General Translation 服务时，区域设置键会被标准化。

<Callout type="info">
  缓存和布局 API 看到的是内部路由。请将 rewrite 的目标路径 (例如 `/fr/fr/home`) 传给 Next.js 的 `revalidatePath`。在 `[locale]` 布局中，`useSelectedLayoutSegments` 还会包含 override 的静态区域设置片段。
</Callout>

内部导航请使用 `gt-next/link` 提供的 [`<Link>`](/docs/react/nextjs/link)，这样带区域设置前缀的路由会在导航前生成，无需额外的 中间件 重定向。

## 示例 [#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).*)'],
};
```

*警告：请务必仔细测试你的 matcher。范围过宽的 matcher 可能会导致重定向循环，或使静态资源无法正常访问。*

## Sitemap

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