You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js v13路由中如何设置可选locale参数?

在Next.js 13中实现带可选locale参数的路由

针对你需要的/[locale?]/lesson/[lesson](lesson必填、locale可选,默认en-US)路由需求,有几种可行的实现方式,下面是具体方案:

方案1:创建两组路由共享组件(简单直接)

Next.js不允许在路由中间段直接使用可选参数,但可以通过创建带locale和不带locale的两组路由,复用同一个业务组件来实现需求:

  1. 构建路由结构:

    app/
    ├── [locale]/
    │   └── lesson/
    │       └── [lesson]/
    │           └── page.tsx  # 核心业务组件
    └── lesson/
        └── [lesson]/
            └── page.tsx  # 复用核心组件,默认传入en-US
    
  2. 实现不带locale的页面组件:

    // app/lesson/[lesson]/page.tsx
    import LessonPage from '../../[locale]/lesson/[lesson]/page';
    
    export default function DefaultLocaleLesson({ params }: { params: { lesson: string } }) {
      // 直接复用带locale的组件,传入默认locale值
      return <LessonPage params={{ locale: 'en-US', lesson: params.lesson }} />;
    }
    
  3. 核心业务组件(app/[locale]/lesson/[lesson]/page.tsx):

    export default function LessonPage({ params }: { params: { locale: string; lesson: string } }) {
      return (
        <div>
          <h1>Lesson {params.lesson}</h1>
          <p>当前语言:{params.locale}</p>
        </div>
      );
    }
    

这种方式无需复杂配置,适合小型项目,用户访问/lesson/123会自动使用en-US,访问/zh-CN/lesson/123则使用对应locale。

方案2:结合Middleware重写路径(避免重复代码)

如果不想维护两组路由文件,可以用Middleware将不带locale的请求内部重写到带默认locale的路由,地址栏不会发生变化:

  1. 构建单一路由结构:

    app/
    └── [locale]/
        └── lesson/
            └── [lesson]/
                └── page.tsx
    
  2. 编写Middleware(middleware.ts):

    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    
    // 支持的locale列表
    const supportedLocales = ['en-US', 'zh-CN'];
    const defaultLocale = 'en-US';
    
    export function middleware(request: NextRequest) {
      const pathname = request.nextUrl.pathname;
    
      // 跳过静态资源和API路由
      if (pathname.startsWith('/_next/') || pathname.startsWith('/api/')) {
        return NextResponse.next();
      }
    
      // 检查路径是否已包含有效locale
      const hasValidLocale = supportedLocales.some(locale => 
        pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
      );
    
      if (hasValidLocale) {
        return NextResponse.next();
      }
    
      // 处理lesson路径:重写到带默认locale的路由(地址栏不变)
      if (pathname.startsWith('/lesson/')) {
        return NextResponse.rewrite(
          new URL(`/${defaultLocale}${pathname}`, request.url)
        );
      }
    
      // 其他路径:重定向到带默认locale的路由(地址栏会更新)
      return NextResponse.redirect(
        new URL(`/${defaultLocale}${pathname}`, request.url)
      );
    }
    
    // 匹配所有需要处理的路径
    export const config = {
      matcher: ['/((?!favicon.ico).*)'],
    };
    
  3. 核心组件无需修改,依然可以通过params.locale获取当前语言(不管是用户直接访问带locale的路径,还是Middleware重写过来的请求)。

方案3:使用Next.js内置国际化支持(推荐)

Next.js 13的App Router内置了国际化支持,配置后可以自动处理带/不带locale的路径映射:

  1. 在next.config.js中配置i18n:

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      i18n: {
        locales: ['en-US', 'zh-CN'],
        defaultLocale: 'en-US',
        localeDetection: false, // 关闭自动检测,用自定义逻辑控制
      },
    };
    
    module.exports = nextConfig;
    
  2. 构建路由结构:

    app/
    └── [locale]/
        └── lesson/
            └── [lesson]/
                └── page.tsx
    
  3. 此时用户访问/lesson/123会自动映射到en-US的路由,访问/zh-CN/lesson/123则使用对应locale,无需额外编写路由文件或复杂的Middleware逻辑。


内容的提问来源于stack exchange,提问作者srhuevo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:29:50