如何在 React Router v7 中实现基于语言环境的路由
使用语言环境段配置路由
问题
在构建多语言应用时,一个最根本的决策会影响后续所有实现:应用如何确定显示哪种语言?如果没有明确的机制,URL /about 就会变得模糊——它可能代表任何语言的内容。用户无法分享特定语言版本的链接,搜索引擎也难以判断哪个版本对应哪个受众。这种不明确会影响用户体验和内容的可发现性。
解决方案
直接在 URL 路径中加入语言标识符,例如 /en/about 或 /fr/about。这样每个路径都唯一对应某种语言,消除了用户和搜索引擎的歧义。通过将路由定义为以语言环境参数为首段,应用可以从 URL 中提取 locale,并据此决定显示哪种语言的内容。这种方式确保每个 URL 都能明确标识页面及其语言。
步骤
1. 使用语言环境参数定义路由
在 app/routes.ts 中配置路由时,将 locale 参数作为每个路径的首段。
import { type RouteConfig, route, index } from "@react-router/dev/routes";
export default [
route(":locale", "./localized-layout.tsx", [
index("./home.tsx"),
route("about", "./about.tsx"),
route("contact", "./contact.tsx"),
]),
] satisfies RouteConfig;
冒号前缀使 locale 成为动态段,会从 URL 解析并作为参数传递给路由组件。这样会生成如 /en、/en/about、/fr/contact 这样的路由,其中首段始终为 locale。
2. 创建布局组件以提取 locale
子路由通过父路由中的 Outlet 组件进行渲染。请创建一个布局,用于提取 locale 参数并渲染嵌套路由。
import { Outlet, useParams } from "react-router";
export default function LocalizedLayout() {
const { locale } = useParams();
return (
<div>
<nav>
<a href={`/${locale}`}>Home</a>
<a href={`/${locale}/about`}>About</a>
<a href={`/${locale}/contact`}>Contact</a>
</nav>
<Outlet />
</div>
);
}
useParams 钩子用于从 URL 中获取动态片段的值。该布局利用 locale 构建导航链接,并通过 Outlet 将渲染控制权交给子路由。
3. 在页面组件中访问 locale
在任意路由组件中使用 useParams 钩子访问 locale 参数。
import { useParams } from "react-router";
export default function About() {
const { locale } = useParams();
return (
<div>
<h1>About Us</h1>
<p>Current locale: {locale}</p>
</div>
);
}
在本地化布局中渲染的每个组件都可以从 URL 中提取 locale。该值可用于加载相应的翻译、格式化日期和数字,或进行其他与 locale 相关的处理。
4. 使用 Link 组件进行客户端导航
将锚点标签替换为 Link 组件,以实现基于客户端路由的导航。
import { Outlet, useParams, Link } from "react-router";
export default function LocalizedLayout() {
const { locale } = useParams();
return (
<div>
<nav>
<Link to={`/${locale}`}>Home</Link>
<Link to={`/${locale}/about`}>About</Link>
<Link to={`/${locale}/contact`}>Contact</Link>
</nav>
<Outlet />
</div>
);
}
Link 组件在客户端处理路由,防止网页重新加载,实现页面间的平滑跳转。每个链接都包含 locale 参数,以在导航过程中保持语言环境。