如何在 React Router v7 中检测用户的语言偏好
基于浏览器偏好自动重定向
问题
每个浏览器在发送 HTTP 请求时都会附带一个 Accept-Language 头,指明用户按优先顺序偏好的语言。这一头信息包含了用户期望看到的语言的宝贵信息,但大多数应用程序完全忽略了它。相反,它们向每位访问者显示默认语言——通常是英语,迫使用户手动寻找语言切换器,即使他们的浏览器已经传达了他们的偏好。这种做法增加了不必要的摩擦,尤其是对国际用户来说,留下了糟糕的第一印象。
解决方案
为根路径创建一个加载器,从传入请求中读取 Accept-Language 头。解析该头以提取用户偏好的语言及其质量值。将偏好的语言与应用程序支持的语言区域进行比较。如果找到匹配项,将用户重定向到该语言区域的路径。如果没有支持的语言匹配,则重定向到默认语言区域。这确保了用户根据他们已在浏览器中配置的偏好,自动进入网站的本地化版本。
步骤
1. 安装一个库来解析 Accept-Language 头
Accept-Language 头具有特定的格式和质量值,需要仔细解析。使用专门的库来正确处理这一点。
npm install accept-language-parser
此库将头字符串解析为按顺序排列的语言偏好列表,按照 HTTP 规范处理质量值和边界情况。
2. 定义支持的语言区域
创建一个辅助文件,列出应用程序支持的语言区域并指定默认回退语言。
export const supportedLocales = ["en", "fr", "de", "es", "ja"] as const;
export const defaultLocale = "en";
export type Locale = (typeof supportedLocales)[number];
这为应用程序可以提供的语言提供了单一的事实来源,并确保了代码库中的类型安全性。
3. 创建一个语言环境检测助手
构建一个函数,该函数接收 Accept-Language 头的值并返回最佳匹配的支持语言环境。
import parser from "accept-language-parser";
import { supportedLocales, defaultLocale, type Locale } from "./locales";
export function detectLocale(acceptLanguageHeader: string | null): Locale {
if (!acceptLanguageHeader) {
return defaultLocale;
}
const languages = parser.parse(acceptLanguageHeader);
for (const lang of languages) {
const code = lang.code.toLowerCase();
if (supportedLocales.includes(code as Locale)) {
return code as Locale;
}
}
return defaultLocale;
}
此函数解析头信息,按优先级顺序遍历用户的语言偏好,并返回与支持语言环境的第一个匹配项,或者回退到默认值。
4. 配置根索引路由
在路由配置中添加一个索引路由,用于处理对根路径的请求。
import { type RouteConfig, index, route } from "@react-router/dev/routes";
export default [
index("routes/index.tsx"),
route(":locale", "routes/locale-root.tsx", []),
] satisfies RouteConfig;
索引路由将在任何其他路由匹配之前拦截根路径请求,允许您执行语言检测并进行重定向。
5. 使用语言检测实现索引路由加载器
创建索引路由模块,该模块读取 Accept-Language 头并重定向到适当的语言环境路径。
import { redirect } from "react-router";
import type { Route } from "./+types/index";
import { detectLocale } from "~/utils/detect-locale";
export async function loader({ request }: Route.LoaderArgs) {
const acceptLanguage = request.headers.get("Accept-Language");
const locale = detectLocale(acceptLanguage);
return redirect(`/${locale}`);
}
当用户访问根路径时,此加载器从请求中提取 Accept-Language 头,确定最佳语言环境,并将其重定向到该语言环境的根路径,确保用户从首次页面加载时就能看到其首选语言的内容。