1# Internationalization support 2 3<!--introduced_in=v8.2.0--> 4 5<!-- type=misc --> 6 7Node.js has many features that make it easier to write internationalized 8programs. Some of them are: 9 10* Locale-sensitive or Unicode-aware functions in the [ECMAScript Language 11 Specification][ECMA-262]: 12 * [`String.prototype.normalize()`][] 13 * [`String.prototype.toLowerCase()`][] 14 * [`String.prototype.toUpperCase()`][] 15* All functionality described in the [ECMAScript Internationalization API 16 Specification][ECMA-402] (aka ECMA-402): 17 * [`Intl`][] object 18 * Locale-sensitive methods like [`String.prototype.localeCompare()`][] and 19 [`Date.prototype.toLocaleString()`][] 20* The [WHATWG URL parser][]'s [internationalized domain names][] (IDNs) support 21* [`require('node:buffer').transcode()`][] 22* More accurate [REPL][] line editing 23* [`require('node:util').TextDecoder`][] 24* [`RegExp` Unicode Property Escapes][] 25 26Node.js and the underlying V8 engine use 27[International Components for Unicode (ICU)][ICU] to implement these features 28in native C/C++ code. The full ICU data set is provided by Node.js by default. 29However, due to the size of the ICU data file, several 30options are provided for customizing the ICU data set either when 31building or running Node.js. 32 33## Options for building Node.js 34 35To control how ICU is used in Node.js, four `configure` options are available 36during compilation. Additional details on how to compile Node.js are documented 37in [BUILDING.md][]. 38 39* `--with-intl=none`/`--without-intl` 40* `--with-intl=system-icu` 41* `--with-intl=small-icu` 42* `--with-intl=full-icu` (default) 43 44An overview of available Node.js and JavaScript features for each `configure` 45option: 46 47| Feature | `none` | `system-icu` | `small-icu` | `full-icu` | 48| ---------------------------------------- | --------------------------------- | ---------------------------- | ---------------------- | ---------- | 49| [`String.prototype.normalize()`][] | none (function is no-op) | full | full | full | 50| `String.prototype.to*Case()` | full | full | full | full | 51| [`Intl`][] | none (object does not exist) | partial/full (depends on OS) | partial (English-only) | full | 52| [`String.prototype.localeCompare()`][] | partial (not locale-aware) | full | full | full | 53| `String.prototype.toLocale*Case()` | partial (not locale-aware) | full | full | full | 54| [`Number.prototype.toLocaleString()`][] | partial (not locale-aware) | partial/full (depends on OS) | partial (English-only) | full | 55| `Date.prototype.toLocale*String()` | partial (not locale-aware) | partial/full (depends on OS) | partial (English-only) | full | 56| [Legacy URL Parser][] | partial (no IDN support) | full | full | full | 57| [WHATWG URL Parser][] | partial (no IDN support) | full | full | full | 58| [`require('node:buffer').transcode()`][] | none (function does not exist) | full | full | full | 59| [REPL][] | partial (inaccurate line editing) | full | full | full | 60| [`require('node:util').TextDecoder`][] | partial (basic encodings support) | partial/full (depends on OS) | partial (Unicode-only) | full | 61| [`RegExp` Unicode Property Escapes][] | none (invalid `RegExp` error) | full | full | full | 62 63The "(not locale-aware)" designation denotes that the function carries out its 64operation just like the non-`Locale` version of the function, if one 65exists. For example, under `none` mode, `Date.prototype.toLocaleString()`'s 66operation is identical to that of `Date.prototype.toString()`. 67 68### Disable all internationalization features (`none`) 69 70If this option is chosen, ICU is disabled and most internationalization 71features mentioned above will be **unavailable** in the resulting `node` binary. 72 73### Build with a pre-installed ICU (`system-icu`) 74 75Node.js can link against an ICU build already installed on the system. In fact, 76most Linux distributions already come with ICU installed, and this option would 77make it possible to reuse the same set of data used by other components in the 78OS. 79 80Functionalities that only require the ICU library itself, such as 81[`String.prototype.normalize()`][] and the [WHATWG URL parser][], are fully 82supported under `system-icu`. Features that require ICU locale data in 83addition, such as [`Intl.DateTimeFormat`][] _may_ be fully or partially 84supported, depending on the completeness of the ICU data installed on the 85system. 86 87### Embed a limited set of ICU data (`small-icu`) 88 89This option makes the resulting binary link against the ICU library statically, 90and includes a subset of ICU data (typically only the English locale) within 91the `node` executable. 92 93Functionalities that only require the ICU library itself, such as 94[`String.prototype.normalize()`][] and the [WHATWG URL parser][], are fully 95supported under `small-icu`. Features that require ICU locale data in addition, 96such as [`Intl.DateTimeFormat`][], generally only work with the English locale: 97 98```js 99const january = new Date(9e8); 100const english = new Intl.DateTimeFormat('en', { month: 'long' }); 101const spanish = new Intl.DateTimeFormat('es', { month: 'long' }); 102 103console.log(english.format(january)); 104// Prints "January" 105console.log(spanish.format(january)); 106// Prints either "M01" or "January" on small-icu, depending on the user’s default locale 107// Should print "enero" 108``` 109 110This mode provides a balance between features and binary size. 111 112#### Providing ICU data at runtime 113 114If the `small-icu` option is used, one can still provide additional locale data 115at runtime so that the JS methods would work for all ICU locales. Assuming the 116data file is stored at `/some/directory`, it can be made available to ICU 117through either: 118 119* The [`NODE_ICU_DATA`][] environment variable: 120 121 ```bash 122 env NODE_ICU_DATA=/some/directory node 123 ``` 124 125* The [`--icu-data-dir`][] CLI parameter: 126 127 ```bash 128 node --icu-data-dir=/some/directory 129 ``` 130 131(If both are specified, the `--icu-data-dir` CLI parameter takes precedence.) 132 133ICU is able to automatically find and load a variety of data formats, but the 134data must be appropriate for the ICU version, and the file correctly named. 135The most common name for the data file is `icudt6X[bl].dat`, where `6X` denotes 136the intended ICU version, and `b` or `l` indicates the system's endianness. 137Check ["ICU Data"][] article in the ICU User Guide for other supported formats 138and more details on ICU data in general. 139 140The [full-icu][] npm module can greatly simplify ICU data installation by 141detecting the ICU version of the running `node` executable and downloading the 142appropriate data file. After installing the module through `npm i full-icu`, 143the data file will be available at `./node_modules/full-icu`. This path can be 144then passed either to `NODE_ICU_DATA` or `--icu-data-dir` as shown above to 145enable full `Intl` support. 146 147### Embed the entire ICU (`full-icu`) 148 149This option makes the resulting binary link against ICU statically and include 150a full set of ICU data. A binary created this way has no further external 151dependencies and supports all locales, but might be rather large. This is 152the default behavior if no `--with-intl` flag is passed. The official binaries 153are also built in this mode. 154 155## Detecting internationalization support 156 157To verify that ICU is enabled at all (`system-icu`, `small-icu`, or 158`full-icu`), simply checking the existence of `Intl` should suffice: 159 160```js 161const hasICU = typeof Intl === 'object'; 162``` 163 164Alternatively, checking for `process.versions.icu`, a property defined only 165when ICU is enabled, works too: 166 167```js 168const hasICU = typeof process.versions.icu === 'string'; 169``` 170 171To check for support for a non-English locale (i.e. `full-icu` or 172`system-icu`), [`Intl.DateTimeFormat`][] can be a good distinguishing factor: 173 174```js 175const hasFullICU = (() => { 176 try { 177 const january = new Date(9e8); 178 const spanish = new Intl.DateTimeFormat('es', { month: 'long' }); 179 return spanish.format(january) === 'enero'; 180 } catch (err) { 181 return false; 182 } 183})(); 184``` 185 186For more verbose tests for `Intl` support, the following resources may be found 187to be helpful: 188 189* [btest402][]: Generally used to check whether Node.js with `Intl` support is 190 built correctly. 191* [Test262][]: ECMAScript's official conformance test suite includes a section 192 dedicated to ECMA-402. 193 194["ICU Data"]: http://userguide.icu-project.org/icudata 195[BUILDING.md]: https://github.com/nodejs/node/blob/HEAD/BUILDING.md 196[ECMA-262]: https://tc39.github.io/ecma262/ 197[ECMA-402]: https://tc39.github.io/ecma402/ 198[ICU]: http://site.icu-project.org/ 199[Legacy URL parser]: url.md#legacy-url-api 200[REPL]: repl.md#repl 201[Test262]: https://github.com/tc39/test262/tree/HEAD/test/intl402 202[WHATWG URL parser]: url.md#the-whatwg-url-api 203[`--icu-data-dir`]: cli.md#--icu-data-dirfile 204[`Date.prototype.toLocaleString()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString 205[`Intl.DateTimeFormat`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat 206[`Intl`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl 207[`NODE_ICU_DATA`]: cli.md#node_icu_datafile 208[`Number.prototype.toLocaleString()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString 209[`RegExp` Unicode Property Escapes]: https://github.com/tc39/proposal-regexp-unicode-property-escapes 210[`String.prototype.localeCompare()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare 211[`String.prototype.normalize()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize 212[`String.prototype.toLowerCase()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase 213[`String.prototype.toUpperCase()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase 214[`require('node:buffer').transcode()`]: buffer.md#buffertranscodesource-fromenc-toenc 215[`require('node:util').TextDecoder`]: util.md#class-utiltextdecoder 216[btest402]: https://github.com/srl295/btest402 217[full-icu]: https://www.npmjs.com/package/full-icu 218[internationalized domain names]: https://en.wikipedia.org/wiki/Internationalized_domain_name 219