Skip to content

Commit ec11b6d

Browse files
committed
lib: add navigator.language & navigator.languages
1 parent 14af167 commit ec11b6d

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

doc/api/globals.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,40 @@ logical processors available to the current Node.js instance.
637637
console.log(`This process is running on ${navigator.hardwareConcurrency} logical processors`);
638638
```
639639

640+
### `navigator.language`
641+
642+
<!-- YAML
643+
added: REPLACEME
644+
-->
645+
646+
* {string}
647+
648+
The `navigator.language` read-only property returns a string representing the
649+
preferred language of the Node.js instance.
650+
651+
The value is representing the language version as defined in RFC <5646>.
652+
The default value is `'en-US'`.
653+
654+
```js
655+
console.log(`The preferred language of the Node.js instance has the tag '${navigator.language}'`);
656+
```
657+
658+
### `navigator.languages`
659+
660+
<!-- YAML
661+
added: REPLACEME
662+
-->
663+
664+
* {Array<string>}
665+
666+
The `navigator.languages` read-only property returns an array of strings
667+
representing the preferred languages of the Node.js instance.
668+
The default value is `['en-US']`.
669+
670+
```js
671+
console.log(`The preferred languages are '${navigator.language}'`);
672+
```
673+
640674
### `navigator.userAgent`
641675

642676
<!-- YAML

lib/internal/navigator.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
const {
44
ObjectDefineProperties,
5+
ObjectFreeze,
56
Symbol,
67
} = primordials;
78

9+
const {
10+
Intl,
11+
} = globalThis;
12+
813
const {
914
ERR_ILLEGAL_CONSTRUCTOR,
1015
} = require('internal/errors').codes;
@@ -24,6 +29,8 @@ class Navigator {
2429
// Private properties are used to avoid brand validations.
2530
#availableParallelism;
2631
#userAgent = `Node.js/${nodeVersion.slice(1, nodeVersion.indexOf('.'))}`;
32+
#language = Intl?.Collator().resolvedOptions().locale || 'en-US';
33+
#languages = ObjectFreeze([this.#language]);
2734

2835
constructor() {
2936
if (arguments[0] === kInitialize) {
@@ -40,6 +47,20 @@ class Navigator {
4047
return this.#availableParallelism;
4148
}
4249

50+
/**
51+
* @return {string}
52+
*/
53+
get language() {
54+
return this.#language;
55+
}
56+
57+
/**
58+
* @return {Array<string>}
59+
*/
60+
get languages() {
61+
return this.#languages;
62+
}
63+
4364
/**
4465
* @return {string}
4566
*/
@@ -50,6 +71,8 @@ class Navigator {
5071

5172
ObjectDefineProperties(Navigator.prototype, {
5273
hardwareConcurrency: kEnumerableProperty,
74+
language: kEnumerableProperty,
75+
languages: kEnumerableProperty,
5376
userAgent: kEnumerableProperty,
5477
});
5578

test/parallel/test-navigator.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,21 @@ is.number(navigator.hardwareConcurrency, 'hardwareConcurrency');
1515
assert.ok(navigator.hardwareConcurrency > 0);
1616
assert.strictEqual(typeof navigator.userAgent, 'string');
1717
assert.match(navigator.userAgent, /^Node\.js\/\d+$/);
18+
19+
assert.strictEqual(typeof navigator.language, 'string');
20+
assert.strictEqual(navigator.language, 'en-US');
21+
22+
assert.ok(Array.isArray(navigator.languages));
23+
assert.strictEqual(navigator.languages.length, 1);
24+
assert.strictEqual(typeof navigator.languages[0], 'string');
25+
26+
assert.throws(() => {
27+
navigator.languages[0] = 'foo';
28+
}, new TypeError("Cannot assign to read only property '0' of object '[object Array]'"));
29+
assert.notStrictEqual(navigator.languages[0], 'foo');
30+
assert.strictEqual(navigator.languages[0], 'en-US');
31+
32+
Object.defineProperty(navigator, 'language', { value: 'de-DE' });
33+
assert.strictEqual(navigator.language, 'de-DE');
34+
assert.strictEqual(navigator.languages.length, 1);
35+
assert.strictEqual(navigator.languages[0], 'en-US');

0 commit comments

Comments
 (0)