如何在 TanStack Start v1 中实现基于语言环境的路由

使用语言环境段配置路由

问题

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

解决方案

将语言标识符直接放入 URL 路径中,例如 /en/about/fr/about。这使得每个路径都唯一对应于特定语言,消除了用户和搜索引擎的模糊性。通过在路由结构中使用区域设置参数,每个 URL 都变得自描述且可分享,允许用户将内容以其首选语言书签或分享链接,同时使搜索引擎能够正确索引每种语言的变体。

步骤

1. 创建一个区域设置布局路由

使用 {-$locale} 语法定义一个可选的区域设置参数,以创建灵活的路由模式,其中区域设置参数是可选的。TanStack Start 使用基于文件的路由,其中路由定义在 src/routes 目录中。

import { createFileRoute, Outlet } from "@tanstack/react-router";

export const Route = createFileRoute("/{-$locale}")({
  component: LocaleLayout,
});

function LocaleLayout() {
  return <Outlet />;
}

此路由同时匹配 /about(区域设置未定义)和 /en/about(区域设置为 "en"),允许您支持带有或不带有区域设置前缀的 URL。

2. 在区域设置布局下创建子路由

TanStack Router 使用嵌套路由将 URL 与正确的组件树匹配以进行渲染。创建作为 locale 参数子级的路由文件,以从 URL 继承 locale。

import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/{-$locale}/about")({
  component: AboutPage,
});

function AboutPage() {
  const { locale } = Route.useParams();
  const currentLocale = locale || "en";

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

路由文件结构 {-$locale}/about.tsx 创建了像 /about/en/about 这样的路径,这两者都渲染相同的组件并可以访问 locale 参数。

3. 在组件中访问 locale 参数

使用 useParams 钩子从 URL 中读取 locale 并确定显示的语言。

import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/{-$locale}/products")({
  component: ProductsPage,
});

function ProductsPage() {
  const { locale } = Route.useParams();
  const displayLocale = locale || "en";

  return (
    <div>
      <h1>{displayLocale === "fr" ? "Produits" : "Products"}</h1>
    </div>
  );
}

当 locale 参数未定义时,组件会默认使用基础语言,从而使应用程序能够处理本地化和非本地化的 URL。

4. 创建保留 locale 的链接

使用带有 locale 参数的 Link 组件在页面之间导航,同时保持当前语言。

import { Link, createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/{-$locale}/")({
  component: HomePage,
});

function HomePage() {
  const { locale } = Route.useParams();

  return (
    <nav>
      <Link to="/{-$locale}/about" params={{ locale }}>
        关于
      </Link>
      <Link to="/{-$locale}/products" params={{ locale }}>
        产品
      </Link>
    </nav>
  );
}

通过在 params 属性中传递当前的 locale,链接会自动生成与用户当前语言环境匹配的 URL,例如在查看法语版本时生成 /fr/about