Next.js i18n如何将带区域的locale匹配到已支持的通用语言?
这个匹配能力完全可以实现,你遇到的不符合预期的情况是Next.js默认的Accept-Language匹配采用严格字符串匹配逻辑,不会自动将带区域后缀的locale(如de-DE、en-US)映射到同主语言的通用locale。你可以通过自定义中间件替换默认匹配逻辑来实现需求,步骤如下:
1. 配置自定义匹配中间件
在项目根目录新建middleware.js文件,实现按语言主标签匹配的逻辑:
// middleware.js import { NextResponse } from 'next/server' const SUPPORTED_LOCALES = ['en', 'de'] const DEFAULT_LOCALE = 'en' function getMatchedLocale(acceptLanguage) { if (!acceptLanguage) return DEFAULT_LOCALE // 解析Accept-Language,拆分候选语言和对应权重 const localeCandidates = acceptLanguage.split(',').map(langStr => { const [fullLocale, weightPart = 'q=1'] = langStr.trim().split(';') return { // 提取主语言标签,丢弃区域后缀 mainLang: fullLocale.split('-')[0].toLowerCase(), weight: parseFloat(weightPart.split('=')[1]) } }) // 按权重从高到低排序 .sort((a, b) => b.weight - a.weight) // 匹配优先级最高的支持语言 const matchedLang = localeCandidates.find(candidate => SUPPORTED_LOCALES.includes(candidate.mainLang)) return matchedLang ? matchedLang.mainLang : DEFAULT_LOCALE } export function middleware(request) { const { pathname } = request.nextUrl // 路径已携带locale,直接放行 const hasLocaleInPath = SUPPORTED_LOCALES.some( locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` ) if (hasLocaleInPath) return NextResponse.next() // 获取匹配的locale后重定向 const acceptLanguage = request.headers.get('accept-language') const targetLocale = getMatchedLocale(acceptLanguage) request.nextUrl.pathname = `/${targetLocale}${pathname}` return NextResponse.redirect(request.nextUrl) } // 配置中间件生效范围,排除静态资源、接口等路径 export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico).*)', ], }
2. 调整next.config.js配置
关闭默认的locale检测逻辑,避免和自定义中间件逻辑冲突:
// next.config.js module.exports = { i18n: { defaultLocale: 'en', locales: ['en', 'de'], localeDetection: false } };
配置完成后即可符合你的预期匹配效果:
- Accept-Language为
de-DE时,自动匹配到/de - Accept-Language为
en-US,de时,en-US权重更高,自动匹配到/en
内容的提问来源于stack exchange,提问作者MauriceNino
相关产品推荐
相关产品推荐

