Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different behaviour of Intl.NumberFormat in node and browser

Tags:

node.js

icu

If I run this code in the browser and node I obtain two different results:

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

moneyFormatter.format(1);

Browser: 1,00 €

Node: €1.00

like image 348
lifeisfoo Avatar asked Mar 15 '19 13:03

lifeisfoo


1 Answers

ICU and Node

This problem is caused by the missing ICU data in the default Node build.

Nodejs docs explain it this feature well:

Node.js (and its underlying V8 engine) uses ICU to implement these features in native C/C++ code. However, some of them require a very large ICU data file in order to support all locales of the world.

And its limitations in the default node build:

Because it is expected that most Node.js users will make use of only a small portion of ICU functionality, only a subset of the full ICU data set is provided by Node.js by default.

So:

Several options are provided for customizing and expanding the ICU data set either when building or running Node.js.

Quick solution

Install the full-icu npm package and you're done: every locale will be installed and can be used. Just start you app with a dedicated env var pointing to the icu dataset installation:

NODE_ICU_DATA=node_modules/full-icu node YOURAPP.js

Or, using the alternative node option:

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

The only disadvantage of this solution is the space required for the full icu dataset: ~27Mb.

Slow, but space optimized solution

Compile node from source bundling it with only a specific ICU.

Checking available locales

Intl.NumberFormat.supportedLocalesOf('it')

It returns an empty array [] if the locale is not supported. It returns an array with the locale id ['it'] if the locale is supported.

like image 189
lifeisfoo Avatar answered Nov 12 '22 22:11

lifeisfoo