不同版本的Intl.NumberFormat在Node和浏览器中表现不同。

20

如果我在浏览器和Node中运行这段代码,我会得到两个不同的结果:

const moneyFormatter = new Intl.NumberFormat('it-IT', {
    style: 'currency',
    currency: 'EUR',
    minimumFractionDigits: 2
});

moneyFormatter.format(1);

浏览器:1,00 €

Node:€1.00

1个回答

22

ICU和Node

这个问题是由于默认Node构建中缺少ICU数据引起的。

Nodejs文档很好地解释了国际化功能的工作原理:

Node.js(及其底层V8引擎)使用ICU在本地C/C++代码中实现这些功能。然而,其中一些功能需要非常大的ICU数据文件才能支持世界上所有语言环境。

同时,它也解释了在默认Node构建中你会遇到的限制:

因为预期大多数Node.js用户只会使用ICU功能的一小部分,所以Node.js默认情况下仅提供了完整ICU数据集的子集。

因此:

提供了几种选项来自定义和扩展ICU数据集,无论是在构建还是运行Node.js时。

快速解决方案

安装 full-icu npm包,问题就解决了:每个语言环境都将被安装并在您的代码中可用。只需使用专用的环境变量启动您的应用程序,指向ICU数据集安装路径:

NODE_ICU_DATA=node_modules/full-icu node YOURAPP.js

或者,使用特定的Node选项:

node --icu-data-dir=node_modules/full-icu YOURAPP.js

这个解决方案唯一的缺点就是需要完整 ICU 数据集所占用的空间约为 27Mb。
慢但空间优化的解决方案是,从源代码编译 Node 并 仅捆绑特定的 ICU 版本
检查可用的区域设置。
Intl.NumberFormat.supportedLocalesOf('it')

如果不支持该语言环境,则返回一个空数组[]。 如果支持该语言环境,则返回带有语言环境id['it']的数组。

我在尝试让快速解决方案工作时遇到了问题。 YOURAPP.js 是 server.js 还是 src/server.js?这两个都对我不起作用。 NODE_ICU_DATA 应该在 .env 文件中定义,对吗? - Lull
@Lull 你需要检查一下你的应用程序源代码中主要的js文件在哪里。它可能被称为index、app或其他任何名称。尝试在package.json脚本中查找它。是的,NODE_ICU_DATA是一个环境变量,但是你可能需要在命令中传递它,因为它必须由node读取,而不是从你的应用程序中读取(node启动,然后加载和执行你的应用程序)。通常,在node启动之后,.env文件会被库解析。 - lifeisfoo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接