检测用户的首选语言
将新访客重定向到他们最可能使用的语言
问题
当用户首次访问应用程序的根路径(例如 /)时,默认会显示一种语言,例如英语。这会给使用其他语言的用户带来直接的障碍,迫使他们手动寻找语言切换器,即使他们的浏览器已经传达了他们的语言偏好。
解决方案
使用中间件拦截对根路径(/)的请求。检查用户的 Accept-Language HTTP 头以确定他们的首选语言。如果该语言被应用程序支持,则将用户重定向到该语言的根路径(例如 /fr)。如果不支持,则将他们重定向到默认语言(例如 /en)。
步骤
1. 安装语言解析器
Accept-Language 头可能很复杂(例如 fr-CH, fr;q=0.9, en;q=0.8)。一个小型库可以帮助解析此头并从支持的语言列表中找到最佳匹配。
在终端中运行以下命令:
npm install accept-language-parser
2. 定义您的语言和默认值
创建一个中央配置文件来存储支持的语言列表并定义一个默认语言。如果用户的浏览器偏好与您支持的任何语言都不匹配,将使用此默认语言。
// i18n.config.ts
export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
3. 创建中间件
在项目根目录下创建一个 middleware.ts 文件。此文件将在传入请求时运行,允许您检查路径和头信息。
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import parser from 'accept-language-parser';
import { locales, defaultLocale } from './i18n.config';
// 辅助函数,用于找到最佳语言匹配
function getBestLocale(acceptLangHeader: string | null) {
if (!acceptLangHeader) {
return defaultLocale;
}
// 使用解析器找到最佳支持语言
const bestMatch = parser.pick(locales, acceptLangHeader, {
loose: true,
});
return bestMatch || defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. 检查请求是否为根路径
if (pathname === '/') {
// 获取用户的首选语言
const acceptLang = request.headers.get('Accept-Language');
const bestLocale = getBestLocale(acceptLang);
// 重定向到最佳匹配的语言路径
request.nextUrl.pathname = `/${bestLocale}`;
return NextResponse.redirect(request.nextUrl);
}
// 2. 对于所有其他路径,正常继续
return NextResponse.next();
}
export const config = {
matcher: [
// 跳过以下路径开头的所有请求:
// - api(API 路由)
// - _next/static(静态文件)
// - _next/image(图像优化文件)
// - favicon.ico(网站图标文件)
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
此代码仅对根路径(/)运行逻辑。如果用户访问 /,它会检查他们的 Accept-Language 头,找到最佳匹配(例如 es),并将他们重定向到 /es。所有其他请求,例如 /en/about,都不会受到此逻辑的影响并直接通过。