You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js使用@formatjs/intl-localematcher遇RangeError报错求助

排查Next.js + @formatjs/intl-localematcher在Vercel预览环境的RangeError问题

以下是几个大概率导致该报错的原因及对应排查方案:

1. 请求头Accept-Language包含非法locale格式

Vercel预览环境的请求头可能携带不符合BCP 47规范的locale值(比如带异常后缀、拼写错误,甚至空值),matchLocale对非法输入容错性极低,即便配置了默认值,也可能因为候选列表完全无法解析而报错。

解决方法:在中间件中先过滤并格式化请求头的locale值,确保传入matchLocale的都是合法候选值:

import { matchLocale } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

const supportedLocales = ['en', 'zh-CN', 'ja'];
const defaultLocale = 'en';

// 过滤出符合支持列表的合法locale
function filterValidLocales(acceptLanguage: string | undefined) {
  if (!acceptLanguage) return [];
  return acceptLanguage.split(',')
    .map(lang => lang.split(';')[0].trim())
    .filter(lang => supportedLocales.includes(lang));
}

export function middleware(request: NextRequest) {
  const negotiator = new Negotiator({ 
    headers: { 'accept-language': request.headers.get('accept-language') || '' } 
  });
  const clientLocales = filterValidLocales(negotiator.language());
  // 兜底:确保候选列表至少有一个合法值
  const finalLocales = clientLocales.length > 0 ? clientLocales : [defaultLocale];
  const matchedLocale = matchLocale(finalLocales, supportedLocales, defaultLocale);
  
  // 后续路由匹配逻辑...
}

2. Vercel与本地Node.js版本不一致

@formatjs/intl-localematcher依赖Node.js的Intl API,不同版本的Node.js对locale解析的实现存在差异,旧版本可能存在部分locale解析的bug,导致在本地正常的代码到Vercel环境报错。

解决方法:

  • 在项目根目录的package.json中指定Node.js版本:
    {
      "engines": {
        "node": ">=18.17.0"
      }
    }
    
  • 登录Vercel控制台,进入项目设置的「General」→「Node.js Version」,手动选择与本地一致的版本。

3. 配置文件中的locale值不符合规范

i18n.config.ts中的locales数组可能包含不符合BCP 47标准的值(比如写cn而非zh-CN),本地环境可能有额外的locale支持,但Vercel环境的Node.js未预装对应locale包,导致解析失败。

解决方法:

  • 核对所有locale值,确保符合BCP 47规范(如en-US、zh-CN);
  • 用Intl.getCanonicalLocales()校验并规范化locale:
    const rawLocales = ['en', 'zh-CN', 'ja'];
    const validLocales = rawLocales.map(locale => Intl.getCanonicalLocales(locale)[0]);
    

4. 未处理请求头为空的极端场景

当请求未携带Accept-Language头时,negotiator.language()可能返回空数组或undefined,此时直接传入matchLocale会触发报错。

解决方法:调用matchLocale前强制兜底默认locale,确保候选列表非空:

const clientLocales = negotiator.language() || [];
const safeLocales = Array.isArray(clientLocales) ? clientLocales : [clientLocales];
const finalLocales = safeLocales.length > 0 ? safeLocales : [defaultLocale];
const matchedLocale = matchLocale(finalLocales, supportedLocales, defaultLocale);

内容的提问来源于stack exchange,提问作者Lenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:29:52