如何在 TanStack Start v1 中验证 URL 中的语言环境参数
优雅地处理不支持的语言环境代码
问题
当语言代码成为 URL 结构的一部分时,它们会转变为必须验证的用户输入。用户可以手动在语言区域段中输入任何字符串,例如 /xx/about、/gibberish/contact 或 /typo123/products,就像输入有效代码(如 /en/about 或 /fr/contact)一样简单。如果没有进行验证,应用程序可能会尝试加载不存在的语言区域的翻译,显示损坏的内容,或者崩溃。每个无效的语言区域都可能成为用户无法恢复或导航到正常页面的死胡同。
未验证的语言区域参数会导致不可预测的行为。应用程序可能会在加载翻译时静默失败,呈现混合的回退内容和缺失内容,或者在访问翻译键时抛出运行时错误。跟随损坏链接或输入错误 URL 的用户将无法获得明确的反馈,无法了解问题出在哪里或如何解决。
解决方案
在路由的 beforeLoad 函数中,根据支持的语言区域列表验证 URL 中的语言区域参数。当语言区域无效或缺失时,将用户重定向到带有默认语言区域的有效 URL,或者抛出未找到错误以显示有用的错误页面。这确保了只有支持的语言区域会被处理,并且用户始终会进入一个有效且可翻译的页面。
beforeLoad 函数在路由加载之前运行,是检查语言区域的理想位置。通过抛出 redirect() 或 notFound() 错误,可以防止路由在无效语言区域下渲染,并引导用户进入正常状态。
步骤
1. 定义支持的语言区域
创建一个包含有效语言代码的常量数组和一个类型安全的验证函数。
const SUPPORTED_LOCALES = ["en", "fr", "es", "de"] as const;
type Locale = (typeof SUPPORTED_LOCALES)[number];
function isValidLocale(locale: string | undefined): locale is Locale {
return SUPPORTED_LOCALES.includes(locale as Locale);
}
这提供了一个支持语言区域的单一事实来源,以及一个 TypeScript 可理解的可重用验证函数。
2. 创建带有语言环境验证的布局路由
使用可选的语言环境参数,并在 beforeLoad 中进行验证。
import { createFileRoute, redirect } from "@tanstack/react-router";
const DEFAULT_LOCALE: Locale = "en";
export const Route = createFileRoute("/{-$locale}")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw redirect({
to: "/{-$locale}",
params: { locale: undefined },
replace: true,
});
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
});
beforeLoad 函数会检查语言环境参数。如果参数存在但无效,用户将被重定向到没有语言环境前缀的相同路径,这会解析为默认语言环境。验证后的语言环境会在上下文中返回,供子路由使用。
3. 在嵌套路由中验证语言环境
对于需要语言环境的路由,验证它并在无效时抛出 notFound()。
import { createFileRoute, notFound } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/products")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw notFound();
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
component: ProductsPage,
});
function ProductsPage() {
const { locale } = Route.useRouteContext();
return <div>Products in {locale}</div>;
}
这种方法会为无效的语言环境显示一个未找到页面,而不是重定向,这在您希望表明 URL 格式错误而不是静默更正时非常有用。
4. 为无效语言环境添加未找到组件
在根路由上定义一个 notFoundComponent,以优雅地处理无效语言环境错误。
import { createRootRoute } from "@tanstack/react-router";
export const Route = createRootRoute({
notFoundComponent: () => {
return (
<div>
<h1>页面未找到</h1>
<p>您请求的语言或页面不存在。</p>
<a href="/">返回主页</a>
</div>
);
},
});
当 notFound() 从 beforeLoad 中抛出时,此组件会渲染,为用户提供清晰的信息以及返回有效页面的方式。