Using non-default locales with toLocaleString()
in Node.js
Published on in JavaScript and Node.js
Last updated on
With Node.js 13+,
it should just work.
With earlier Node.js versions,
you need to install and use the full-icu
package.
Table of contents
The problem
Using Node.js version 12 or earlier,
Date.prototype.toLocaleString()
and
Number.prototype.toLocaleString()
don't always produce correct results,
at least with non-English (or non-default) locales.
For example:
const date = new Date('2021-11-22')
console.log(date.toLocaleString('en'))
//=> Actual/expected: 11/22/2021, 2:00:00 AM (π)
console.log(date.toLocaleString('fi'))
//=> Actual: 2021-11-22 2:00:00 (β)
//=> Expected: 22.11.2021 klo 2.00.00
const number = 1234.56
console.log(number.toLocaleString('en', { style: 'currency', currency: 'USD' }))
//=> Actual/expected: $1,234.56 (π)
console.log(number.toLocaleString('fi', { style: 'currency', currency: 'USD' }))
//=> Actual: US$ 1,234.56 (β)
//=> Expected: 1 234,56 $
The solution
The results depend on the ICU data (= localization data) used by Node.js. From site.icu-project.org:
ICU is a mature, widely used set of [...] libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms [...].
Node.js 13+
Starting from version 13.0.0,
Node.js comes with full ICU support by default,
so toLocaleString()
should produce correct results.
From version 13.0.0 changelog:
Node.js releases are now built with default full-icu support. This means that all locales supported by ICU are now included and Intl-related APIs may return different values than before (Richard Lau) #29887.
Issue #19214 has also relevant discussion about this.
Note: version 13 is not an LTS (long-time support) version. Even-numbered versions β 14, 16, 18 and so on β are LTS versions and thus a better choice. See Node.js Releases.
Node.js 12 and earlier
You need to install and enable full ICU data manually:
-
Run
npm install full-icu cross-env
to install the following packages: -
Update the scripts section of
package.json
to set the environment variableNODE_ICU_DATA
. For example:{ "scripts": { // Before "start": "react-scripts start", "test": "react-scripts test", // After "start": "react-scripts start", "test": "cross-env NODE_ICU_DATA=node_modules/full-icu react-scripts test" } }
Now when you run npm test
,
Node.js will load the full ICU data from node_modules/full-icu
,
and toLocaleString()
should produce correct results.
In the example above,
you could also modify the start
script,
but it might be unnecessary;
depends on what the script does.
In this case the script opens a browser,
so modifying the script would be unnecessary.
Further resources
The same info can be found in my Stack Overflow answer.