
本文旨在解决 next.js 13 国际化路由中常见的 ‘incorrect locale information provided’ 错误。当浏览器发送 `[‘*’]` 作为语言偏好时,next.JS 的 i18n 模块可能无法正确识别。通过引入一个条件判断,将无效的 `[‘*’]` 语言数组替换为预设的默认语言(如 ‘ar’),可以有效规避此问题,确保国际化路由正常工作。
Next.js 提供了强大的国际化 (i18n) 路由功能,允许开发者根据用户的语言偏好提供多语言内容。然而,在实际应用中,有时会遇到一个棘手的问题,即在遵循官方文档配置 i18n 路由后,系统抛出 “Incorrect locale information provided” 错误。这个错误通常发生在语言数组中包含一个特殊的通配符 *,而 Next.js 的 i18n 模块无法将其识别为有效的语言环境标识符。
问题分析:[‘*’] 语言偏好引发的错误
在某些情况下,用户的浏览器可能会在 Accept-Language 请求头中发送 * 作为其语言偏好,或者在处理语言数组时,由于某种原因导致最终的语言数组变为 [‘*’]。根据 BCP 47 语言标签标准,* 并非一个有效的语言环境标识符。Next.js 的国际化路由机制依赖于标准的语言标签来匹配和解析路由。当它接收到一个包含 [‘*’] 的语言数组时,由于无法将其映射到任何已定义的语言环境,便会抛出 “Incorrect locale information provided” 错误。
这个问题的核心在于,Next.js 期望接收到诸如 en、zh-CN、fr 等符合标准的语言代码。而 * 作为一个通配符,在语言环境识别的上下文中是无效的。
解决方案:条件性语言回退
解决此问题的关键在于在 Next.js 处理语言数组之前,对其进行预处理。我们需要识别并替换掉无效的 [‘*’] 语言数组,将其替换为一个我们预设的默认或回退语言。
以下是如何实现这一逻辑的示例代码:
// 假设这是你在 Next.js middleware.ts 或某个处理语言偏好的工具函数中 // 获取到用户语言偏好的逻辑 function getPreferredLocale(requestHeaders) { // 从请求头或其他来源获取语言数组 // 例如,通过 next/server 的 `NextRequest` 对象获取 `Accept-Language` let languages = ['en']; // 默认值,以防万一 // 实际应用中,这里会解析 requestHeaders['Accept-Language'] // 假设解析后得到一个数组,例如 ['en-US', 'en', '*'] 或 ['*'] // 模拟从请求头获取的语言数组 // For demonstration: // const acceptLanguageHeader = requestHeaders.get('Accept-Language'); // if (acceptLanguageHeader) { // languages = acceptLanguageHeader.split(',').map(lang => lang.split(';')[0].trim()); // } // 核心解决方案:处理 ['*'] 的情况 if (languages.Length === 1 && languages[0] === '*') { // 当语言数组仅包含 '*' 时,将其替换为应用程序的默认语言 // 例如,替换为 'en' (英语) 或 'ar' (阿拉伯语,根据原始问题) console.warn("Detected invalid locale preference ['*'], falling back to default locale."); languages = ['en']; // 替换为你的应用默认语言,例如 'en', 'zh', 'ar' 等 } // 接下来,你可以根据这个 languages 数组来决定最终的 locale // 比如,与你应用支持的语言列表进行匹配 const supportedLocales = ['en', 'zh', 'ar']; // 你的应用支持的语言列表 const foundLocale = languages.find(lang => supportedLocales.includes(lang.split('-')[0])) || supportedLocales[0]; return foundLocale; } // 示例用法 (在 Next.js 的 middleware.ts 中) // import { NextRequest, NextResponse } from 'next/server'; // export function middleware(request: NextRequest) { // const preferredLocale = getPreferredLocale(request.headers); // // 之后,你可以将 preferredLocale 用于重定向或设置请求头等 // // 例如: // // const { pathname } = request.nextUrl; // // if (!pathname.startsWith(`/${preferredLocale}/`) && pathname !== `/${preferredLocale}`) { // // return NextResponse.redirect(new URL(`/${preferredLocale}${pathname}`, request.url)); // // } // return NextResponse.next(); // } // 假设我们直接有一个 languages 数组 let userLanguages = ['*']; let effectiveLocale = getPreferredLocale({ /* mock headers if needed */ }); // 调用时传入模拟或实际的请求头 console.log("Effective locale after processing:", effectiveLocale); // 预期输出 'en' userLanguages = ['en-US', 'en']; effectiveLocale = getPreferredLocale({ /* mock headers if needed */ }); console.log("Effective locale for en-US, en:", effectiveLocale); // 预期输出 'en' userLanguages = ['fr', 'en']; effectiveLocale = getPreferredLocale({ /* mock headers if needed */ }); console.log("Effective locale for fr, en:", effectiveLocale); // 预期输出 'en' (因为 fr 不在 supportedLocales 中,所以回退到第一个)
代码解释:
- getPreferredLocale(requestHeaders) 函数: 这个函数模拟了从请求头中获取用户语言偏好的过程。在实际的 Next.js 应用中,这通常会在 middleware.ts 文件中进行,通过 NextRequest 对象的 headers 属性来获取 Accept-Language。
- 条件判断: if (languages.length === 1 && languages[0] === ‘*’) 是解决方案的核心。它检查解析出的语言数组是否只包含一个元素,并且这个元素是 *。
- 语言替换: 如果条件为真,我们将 languages 数组替换为一个包含应用程序默认语言的新数组。在示例中,我们使用了 [‘en’],你可以根据你的项目需求将其更改为 [‘zh’]、[‘ar’] 或其他你希望的默认语言。
- 后续处理: 替换后,languages 数组现在包含一个有效的语言标识符。你可以继续按照 Next.js 官方文档的指示,使用这个有效的语言数组来确定当前的语言环境,并进行相应的路由处理或内容渲染。
部署与注意事项
- 位置: 最佳实践是将此逻辑放置在 Next.js 的 middleware.ts 文件中。middleware 允许你在请求到达页面之前拦截并处理它们,非常适合进行语言环境检测和重定向。
- 默认语言选择: 确保你选择的默认语言是你的应用程序所支持的,并且是一个合理的 fallback 选项。
- 多语言回退策略: 如果你的应用程序支持多种语言,并且希望在 [‘*’] 之外的无效语言偏好出现时也有一个回退机制,你可能需要一个更复杂的语言匹配逻辑,例如遍历 languages 数组,找到第一个与 supportedLocales 匹配的语言,如果都没有匹配,则使用 supportedLocales 中的第一个作为默认值。
- 测试: 务必在不同浏览器和语言设置下测试你的国际化路由,特别是模拟 Accept-Language 头为 * 的情况,以确保解决方案的健壮性。
通过上述方法,你可以有效地处理 Next.js 国际化路由中因 [‘*’] 语言偏好而导致的 “Incorrect locale information provided” 错误,从而提高应用程序的鲁棒性和用户体验。