基于语言的路由

在 Next.js(App Router)中设置基于语言的路由

问题

当应用支持多种语言时,像 /about 这样的单一 URL 本身是有歧义的。用户访问该 URL 时会收到默认语言的内容,但无法链接或收藏该页面的其他语言版本。这种歧义会让搜索引擎困惑,可能导致并未索引所有语言版本,或将不同语言混合索引。

解决方案

直接在 URL 路径中加入语言标识符,例如 /en/about/fr/about。这样每个路径都唯一对应某种语言,既解决了用户端的歧义,也方便搜索引擎正确索引。

步骤

1. 创建动态语言分段

在 Next.js App Router 中,可以通过在 app 目录下创建动态分段文件夹来实现语言路由。在 app 目录下新建名为 [lang] 的文件夹,并将主 page.tsx 文件移入其中。

// app/[lang]/page.tsx

export default function Home({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>Home page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

[lang] 文件夹会捕获 URL 的第一部分(如 'en' 或 'fr'),并作为 lang 属性传递到 params 对象中,供页面组件使用。现在可以通过 /en/fr 这样的 URL 访问页面。

2. 更新根布局

你的根 layout.tsx 也应移动到 app/[lang] 文件夹内。它同样会接收到 lang 参数,你应使用该参数为 <html> 标签设置 lang 属性,以提升可访问性和 SEO。

// app/[lang]/layout.tsx

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

此布局现在会将所有页面包裹在特定语言环境下。在这里设置 lang 属性,可以告知浏览器页面内容所用的语言。

3. 定义支持的语言

要告知 Next.js 哪些语言分段是有效的,可以从根布局导出一个 generateStaticParams 函数。这样 Next.js 就能在构建时静态生成这些路由。

// app/[lang]/layout.tsx

export async function generateStaticParams() {
  return [{ lang: 'en' }, { lang: 'es' }, { lang: 'fr' }];
}

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

此函数告知 Next.js 你的应用支持 /en/es/fr。对于其他路径(如 /de),会返回 404 Not Found 页面。

4. 添加嵌套路由

你应用中的其他所有页面现在都需要在 [lang] 文件夹内创建。例如,要创建一个 'about' 页面,可以添加 app/[lang]/about/page.tsx

// app/[lang]/about/page.tsx

export default function AboutPage({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>About page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

此文件会自动创建可通过 /en/about/es/about/fr/about 访问的路由。如果需要获取正确的翻译内容,lang 参数在所有页面中都可用。