toLocaleString()及moment/luxon多语言日期格式化失效求助
首先,这个问题的核心原因是你的Node.js运行环境缺少非英语的本地化(ICU)数据支持。不管是原生的toLocaleString(),还是moment、luxon这类库,在Node.js默认配置下,只有英语的本地化数据是完整的,其他语言会因为缺少对应数据而输出异常格式。
下面给你几个可行的解决方案:
方案1:给Node.js补全ICU支持(原生API/moment/luxon通用)
Node.js默认只包含基础ICU数据,要支持多语言格式化,需要安装full-icu包来补全所有语言的本地化数据:
安装依赖:
npm install full-icu --save配置运行时参数:
在启动你的Node.js应用时,添加--icu-data-dir参数指定ICU数据目录:node --icu-data-dir=node_modules/full-icu your-app.js或者在
package.json的scripts里配置启动命令,避免每次手动输入:{ "scripts": { "start": "node --icu-data-dir=node_modules/full-icu app.js" } }
这样配置后,你原来的expireAt.toLocaleString('fr-FR', options)代码就能正常输出法语格式的日期了,moment和luxon也会随之恢复正常。
方案2:用Moment.js自带的语言包(无需依赖系统ICU)
如果你不想折腾ICU配置,可以直接用Moment.js的独立语言包,它不依赖系统的Intl API:
安装对应语言的Moment语言包(比如法语、意大利语、西班牙语):
npm install moment moment-fr moment-it moment-es --save修改你的JS代码:
const moment = require('moment'); // 根据locale加载对应语言包 require(`moment/locale/${locale}`); // 格式化日期(格式字符串对应你的需求:星期全称 日 月全称 年) const formattedExpireAt = moment(expireAt).locale(locale).format('dddd D MMMM YYYY'); return email.send({ template: 'file-expiration', message: { to: to, }, locals: { fileUuid: fileUuid, expireAt: formattedExpireAt, locale: locale, }, });
这种方式不需要依赖系统的ICU数据,Moment.js自带了所有语言的本地化规则,稳定性更高。
方案3:检查服务器系统语言包(针对Linux服务器)
如果你的应用部署在Linux服务器上,也可以尝试安装系统级的语言包,比如Ubuntu下:
# 安装法语语言包 sudo apt-get install language-pack-fr # 意大利语 sudo apt-get install language-pack-it # 西班牙语 sudo apt-get install language-pack-es
不过这种方式依赖服务器环境,不如前两种方案通用,适合固定环境的部署场景。
验证一下,用方案1或2之后,法语环境应该能输出你预期的dimanche 22 septembre 2019,其他语言也会正常显示对应格式。
内容的提问来源于stack exchange,提问作者Kerhael

