如何在 Next.js (Pages Router) v16 中实现基于语言环境的路由

使用语言环境段配置路由

问题

在构建多语言应用程序时,一个基本的决定会影响其他所有方面:应用程序如何知道显示哪种语言?如果没有明确的机制,URL /about 就会变得模糊不清——它可能代表任何语言的内容。用户无法分享特定语言版本的链接,搜索引擎也难以理解哪个版本属于哪个受众。这种模糊性会对用户体验和 SEO 造成问题,因为没有明确的方法来识别或书签特定语言的内容。

解决方案

通过配置 Next.js 内置的 i18n 路由支持,将语言标识符直接放入 URL 路径中。在 Next.js 配置中声明您想支持的语言环境和默认语言环境。Next.js 将自动处理路由,使得像 /fr/about/nl-NL/about 这样的路径可用,而默认语言环境则没有前缀。这使得每个路径都唯一对应于特定语言,从而消除了用户和搜索引擎的模糊性。

步骤

1. 在 next.config.js 中添加 i18n 配置

在 next.config.js 文件中添加 i18n 配置,以声明您的应用程序支持哪些语言环境。

module.exports = {
  i18n: {
    locales: ["en-US", "fr", "nl-NL"],
    defaultLocale: "en-US",
  },
};

语言环境是 UTS 语言环境标识符,这是一种定义语言环境的标准化格式,通常由语言、地区和脚本组成,并用连字符分隔。defaultLocale 用于访问没有语言环境前缀的路径时。

2. 在页面中访问语言环境信息

使用 useRouter() 钩子在页面组件中访问语言环境信息。

import { useRouter } from "next/router";

export default function AboutPage() {
  const router = useRouter();
  const { locale, locales, defaultLocale } = router;

  return (
    <div>
      <h1>关于我们</h1>
      <p>当前语言环境:{locale}</p>
    </div>
  );
}

locale 属性包含当前激活的语言环境,locales 包含所有配置的语言环境,而 defaultLocale 包含配置的默认语言环境。

3. 在数据获取函数中访问语言环境

在使用 getStaticProps 或 getServerSideProps 预渲染页面时,语言环境信息会在上下文中提供。

import { GetStaticProps } from "next";

export const getStaticProps: GetStaticProps = async (context) => {
  const { locale } = context;

  const messages = await import(`../messages/${locale}.json`);

  return {
    props: {
      messages: messages.default,
    },
  };
};

这使您可以在构建时或请求时根据活动语言环境加载特定于语言环境的数据。

4. 在语言环境之间切换

使用带有 locale 属性的 next/link 来切换到不同的语言环境。

import Link from "next/link";

export default function LanguageSwitcher() {
  return (
    <nav>
      <Link href="/about" locale="en-US">
        English
      </Link>
      <Link href="/about" locale="fr">
        Français
      </Link>
      <Link href="/about" locale="nl-NL">
        Nederlands
      </Link>
    </nav>
  );
}

如果未提供 locale 属性,则在客户端切换时会使用当前活动的语言环境。locale 属性允许用户在保持相同逻辑页面的同时切换语言。

5. 为所有语言环境生成静态路径

在使用 getStaticPaths 时,配置的语言环境会在上下文参数中以 locales 提供,默认语言环境以 defaultLocale 提供。

import { GetStaticPaths } from "next";

export const getStaticPaths: GetStaticPaths = async (context) => {
  const { locales } = context;

  const paths = locales.flatMap((locale) => [
    { params: { slug: "getting-started" }, locale },
    { params: { slug: "advanced" }, locale },
  ]);

  return {
    paths,
    fallback: false,
  };
};

这确保了您的动态页面的所有语言环境版本都在构建时预渲染。