| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -637,6 +637,47 @@ logical processors available to the current Node.js instance. | |||
| 637 | 637 | console.log(`This process is running on ${navigator.hardwareConcurrency} logical processors`); | |
| 638 | 638 | ``` | |
| 639 | 639 | ||
| 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. The language will be determined by | ||
| 650 | + the ICU library used by Node.js at runtime based on the | ||
| 651 | + default language of the operating system. | ||
| 652 | + | ||
| 653 | + The value is representing the language version as defined in [RFC 5646][]. | ||
| 654 | + | ||
| 655 | + The fallback value on builds without ICU is `'en-US'`. | ||
| 656 | + | ||
| 657 | + ```js | ||
| 658 | + console.log(`The preferred language of the Node.js instance has the tag '${navigator.language}'`); | ||
| 659 | + ``` | ||
| 660 | + | ||
| 661 | + ### `navigator.languages` | ||
| 662 | + | ||
| 663 | + <!-- YAML | ||
| 664 | + added: REPLACEME | ||
| 665 | + --> | ||
| 666 | + | ||
| 667 | + * {Array<string>} | ||
| 668 | + | ||
| 669 | + The `navigator.languages` read-only property returns an array of strings | ||
| 670 | + representing the preferred languages of the Node.js instance. | ||
| 671 | + By default `navigator.languages` contains only the value of | ||
| 672 | + `navigator.language`, which will be determined by the ICU library used by | ||
| 673 | + Node.js at runtime based on the default language of the operating system. | ||
| 674 | + | ||
| 675 | + The fallback value on builds without ICU is `['en-US']`. | ||
| 676 | + | ||
| 677 | + ```js | ||
| 678 | + console.log(`The preferred languages are '${navigator.languages}'`); | ||
| 679 | + ``` | ||
| 680 | + | ||
| 640 | 681 | ### `navigator.platform` | |
| 641 | 682 | ||
| 642 | 683 | <!-- YAML | |
@@ -1100,6 +1141,7 @@ A browser-compatible implementation of [`WritableStreamDefaultWriter`][]. | |||
| 1100 | 1141 | [CommonJS module]: modules.md | |
| 1101 | 1142 | [ECMAScript module]: esm.md | |
| 1102 | 1143 | [Navigator API]: https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object | |
| 1144 | + [RFC 5646]: https://www.rfc-editor.org/rfc/rfc5646.txt | ||
| 1103 | 1145 | [Web Crypto API]: webcrypto.md | |
| 1104 | 1146 | [`--experimental-websocket`]: cli.md#--experimental-websocket | |
| 1105 | 1147 | [`--no-experimental-global-customevent`]: cli.md#--no-experimental-global-customevent | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,9 +5,15 @@ const { | |||
| 5 | 5 | StringPrototypeIndexOf, | |
| 6 | 6 | StringPrototypeSlice, | |
| 7 | 7 | StringPrototypeToUpperCase, | |
| 8 | + ObjectFreeze, | ||
| 9 | + globalThis, | ||
| 8 | 10 | Symbol, | |
| 9 | 11 | } = primordials; | |
| 10 | 12 | ||
| 13 | + const { | ||
| 14 | + Intl, | ||
| 15 | + } = globalThis; | ||
| 16 | + | ||
| 11 | 17 | const { | |
| 12 | 18 | ERR_ILLEGAL_CONSTRUCTOR, | |
| 13 | 19 | } = require('internal/errors').codes; | |
@@ -74,6 +80,8 @@ class Navigator { | |||
| 74 | 80 | #availableParallelism; | |
| 75 | 81 | #userAgent = `Node.js/${StringPrototypeSlice(nodeVersion, 1, StringPrototypeIndexOf(nodeVersion, '.'))}`; | |
| 76 | 82 | #platform = getNavigatorPlatform(process); | |
| 83 | + #language = Intl?.Collator().resolvedOptions().locale || 'en-US'; | ||
| 84 | + #languages = ObjectFreeze([this.#language]); | ||
| 77 | 85 | ||
| 78 | 86 | constructor() { | |
| 79 | 87 | if (arguments[0] === kInitialize) { | |
@@ -90,6 +98,20 @@ class Navigator { | |||
| 90 | 98 | return this.#availableParallelism; | |
| 91 | 99 | } | |
| 92 | 100 | ||
| 101 | + /** | ||
| 102 | + * @return {string} | ||
| 103 | + */ | ||
| 104 | + get language() { | ||
| 105 | + return this.#language; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * @return {Array<string>} | ||
| 110 | + */ | ||
| 111 | + get languages() { | ||
| 112 | + return this.#languages; | ||
| 113 | + } | ||
| 114 | + | ||
| 93 | 115 | /** | |
| 94 | 116 | * @return {string} | |
| 95 | 117 | */ | |
@@ -107,6 +129,8 @@ class Navigator { | |||
| 107 | 129 | ||
| 108 | 130 | ObjectDefineProperties(Navigator.prototype, { | |
| 109 | 131 | hardwareConcurrency: kEnumerableProperty, | |
| 132 | + language: kEnumerableProperty, | ||
| 133 | + languages: kEnumerableProperty, | ||
| 110 | 134 | userAgent: kEnumerableProperty, | |
| 111 | 135 | platform: kEnumerableProperty, | |
| 112 | 136 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,10 +1,11 @@ | |||
| 1 | - 'use strict'; | ||
| 2 | - | ||
| 3 | 1 | // Flags: --expose-internals | |
| 4 | 2 | ||
| 5 | - require('../common'); | ||
| 3 | + 'use strict'; | ||
| 4 | + | ||
| 5 | + const common = require('../common'); | ||
| 6 | 6 | const assert = require('assert'); | |
| 7 | 7 | const { getNavigatorPlatform } = require('internal/navigator'); | |
| 8 | + const { execFile } = require('child_process'); | ||
| 8 | 9 | ||
| 9 | 10 | const is = { | |
| 10 | 11 | number: (value, key) => { | |
@@ -74,3 +75,48 @@ assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'sunos' }), 'S | |||
| 74 | 75 | assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'sunos' }), 'SunOS x64'); | |
| 75 | 76 | assert.strictEqual(getNavigatorPlatform({ arch: 'ppc', platform: 'aix' }), 'AIX'); | |
| 76 | 77 | assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'reactos' }), 'Reactos x64'); | |
| 78 | + | ||
| 79 | + assert.strictEqual(typeof navigator.language, 'string'); | ||
| 80 | + assert.strictEqual(navigator.language.length !== 0, true); | ||
| 81 | + | ||
| 82 | + assert.ok(Array.isArray(navigator.languages)); | ||
| 83 | + assert.strictEqual(navigator.languages.length, 1); | ||
| 84 | + assert.strictEqual(typeof navigator.languages[0], 'string'); | ||
| 85 | + assert.strictEqual(navigator.languages[0].length !== 0, true); | ||
| 86 | + | ||
| 87 | + assert.throws(() => { | ||
| 88 | + navigator.languages[0] = 'foo'; | ||
| 89 | + }, new TypeError("Cannot assign to read only property '0' of object '[object Array]'")); | ||
| 90 | + assert.notStrictEqual(navigator.languages[0], 'foo'); | ||
| 91 | + assert.strictEqual(typeof navigator.languages[0] === 'string', true); | ||
| 92 | + assert.strictEqual(navigator.languages[0].length !== 0, true); | ||
| 93 | + | ||
| 94 | + if (common.hasIntl && common.isWindows === false) { | ||
| 95 | + const testLocale = navigator.language === 'de-DE' ? | ||
| 96 | + 'en-US' : | ||
| 97 | + 'de-DE'; | ||
| 98 | + { | ||
| 99 | + const env = { ...process.env, LC_ALL: testLocale }; | ||
| 100 | + execFile( | ||
| 101 | + process.execPath, | ||
| 102 | + ['--print', `"process.exit(navigator.language === '${testLocale}' ? 0 : 1)"`], | ||
| 103 | + { env }, | ||
| 104 | + common.mustSucceed() | ||
| 105 | + ); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + { | ||
| 109 | + const env = { ...process.env, LC_ALL: testLocale }; | ||
| 110 | + execFile( | ||
| 111 | + process.execPath, | ||
| 112 | + ['--print', `"process.exit(navigator.languages[0] === '${testLocale}' ? 0 : 1)"`], | ||
| 113 | + { env }, | ||
| 114 | + common.mustSucceed() | ||
| 115 | + ); | ||
| 116 | + } | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + Object.defineProperty(navigator, 'language', { value: 'for-testing' }); | ||
| 120 | + assert.strictEqual(navigator.language, 'for-testing'); | ||
| 121 | + assert.strictEqual(navigator.languages.length, 1); | ||
| 122 | + assert.strictEqual(navigator.languages[0] !== 'for-testing', true); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments