Repository: nodejs/node
Pull request: test: move localizationd data from `test-icu-env` to external file

Refs: https://github.com/nodejs/node/pull/50515#issuecomment-1811444888

Related to: https://github.com/nodejs/node/pull/55551 (the data in current PR is generated using version `75.1`)

Changed files:
filename: test/fixtures/icu/localizationData-v74.2.json
patch: @@ -0,0 +1,128 @@
+{
+  "dateStrings": {
+    "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)",
+    "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)",
+    "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)",
+    "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)",
+    "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)",
+    "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)",
+    "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)",
+    "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)",
+    "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)",
+    "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)",
+    "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)",
+    "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)",
+    "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)",
+    "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)",
+    "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)",
+    "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)"
+  },
+  "dateTimeFormats": {
+    "en": "7/25/1980, 1:35:33 AM",
+    "zh": "1980/7/25 01:35:33",
+    "hi": "25/7/1980, 1:35:33 am",
+    "es": "25/7/1980, 1:35:33",
+    "fr": "25/07/1980 01:35:33",
+    "ar": "٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص",
+    "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM",
+    "ru": "25.07.1980, 01:35:33",
+    "pt": "25/07/1980, 01:35:33",
+    "ur": "25/7/1980، 1:35:33 AM",
+    "id": "25/7/1980, 01.35.33",
+    "de": "25.7.1980, 01:35:33",
+    "ja": "1980/7/25 1:35:33",
+    "pcm": "25/7/1980 01:35:33",
+    "mr": "२५/७/१९८०, १:३५:३३ AM",
+    "te": "25/7/1980 1:35:33 AM"
+  },
+  "dateFormats": {
+    "en": "7/25/1980",
+    "zh": "1980/7/25",
+    "hi": "25/7/1980",
+    "es": "25/7/1980",
+    "fr": "25/07/1980",
+    "ar": "٢٥‏/٧‏/١٩٨٠",
+    "bn": "২৫/৭/১৯৮০",
+    "ru": "25.07.1980",
+    "pt": "25/07/1980",
+    "ur": "25/7/1980",
+    "id": "25/7/1980",
+    "de": "25.7.1980",
+    "ja": "1980/7/25",
+    "pcm": "25/7/1980",
+    "mr": "२५/७/१९८०",
+    "te": "25/7/1980"
+  },
+  "displayNames": {
+    "en": "Switzerland",
+    "zh": "瑞士",
+    "hi": "स्विट्ज़रलैंड",
+    "es": "Suiza",
+    "fr": "Suisse",
+    "ar": "سويسرا",
+    "bn": "সুইজারল্যান্ড",
+    "ru": "Швейцария",
+    "pt": "Suíça",
+    "ur": "سوئٹزر لینڈ",
+    "id": "Swiss",
+    "de": "Schweiz",
+    "ja": "スイス",
+    "pcm": "Swítsaland",
+    "mr": "स्वित्झर्लंड",
+    "te": "స్విట్జర్లాండ్"
+  },
+  "numberFormats": {
+    "en": "275,760.913",
+    "zh": "275,760.913",
+    "hi": "2,75,760.913",
+    "es": "275.760,913",
+    "fr": "275 760,913",
+    "ar": "٢٧٥٬٧٦٠٫٩١٣",
+    "bn": "২,৭৫,৭৬০.৯১৩",
+    "ru": "275 760,913",
+    "pt": "275.760,913",
+    "ur": "275,760.913",
+    "id": "275.760,913",
+    "de": "275.760,913",
+    "ja": "275,760.913",
+    "pcm": "275,760.913",
+    "mr": "२,७५,७६०.९१३",
+    "te": "2,75,760.913"
+  },
+  "pluralRules": {
+    "en": "other",
+    "zh": "other",
+    "hi": "one",
+    "es": "other",
+    "fr": "one",
+    "ar": "zero",
+    "bn": "one",
+    "ru": "many",
+    "pt": "one",
+    "ur": "other",
+    "id": "other",
+    "de": "other",
+    "ja": "other",
+    "pcm": "one",
+    "mr": "other",
+    "te": "other"
+  },
+  "relativeTime": {
+    "en": "586,920.617 hours ago",
+    "zh": "586,920.617小时前",
+    "hi": "5,86,920.617 घंटे पहले",
+    "es": "hace 586.920,617 horas",
+    "fr": "il y a 586 920,617 heures",
+    "ar": "قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة",
+    "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে",
+    "ru": "586 920,617 часа назад",
+    "pt": "há 586.920,617 horas",
+    "ur": "586,920.617 گھنٹے پہلے",
+    "id": "586.920,617 jam yang lalu",
+    "de": "vor 586.920,617 Stunden",
+    "ja": "586,920.617 時間前",
+    "pcm": "586,920.617 áwa wé dọ́n pas",
+    "mr": "५,८६,९२०.६१७ तासांपूर्वी",
+    "te": "5,86,920.617 గంటల క్రితం"
+  }
+}

filename: test/fixtures/icu/localizationData-v75.1.json
patch: @@ -0,0 +1,128 @@
+{
+  "dateStrings": {
+    "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)",
+    "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)",
+    "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)",
+    "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)",
+    "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)",
+    "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)",
+    "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)",
+    "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)",
+    "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)",
+    "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)",
+    "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)",
+    "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)",
+    "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)",
+    "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)",
+    "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)",
+    "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)"
+  },
+  "dateTimeFormats": {
+    "en": "7/25/1980, 1:35:33 AM",
+    "zh": "1980/7/25 01:35:33",
+    "hi": "25/7/1980, 1:35:33 am",
+    "es": "25/7/1980, 1:35:33",
+    "fr": "25/07/1980 01:35:33",
+    "ar": "٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص",
+    "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM",
+    "ru": "25.07.1980, 01:35:33",
+    "pt": "25/07/1980, 01:35:33",
+    "ur": "25/7/1980، 1:35:33 AM",
+    "id": "25/7/1980, 01.35.33",
+    "de": "25.7.1980, 01:35:33",
+    "ja": "1980/7/25 1:35:33",
+    "pcm": "25/7/1980 01:35:33",
+    "mr": "२५/७/१९८०, १:३५:३३ AM",
+    "te": "25/7/1980 1:35:33 AM"
+  },
+  "dateFormats": {
+    "en": "7/25/1980",
+    "zh": "1980/7/25",
+    "hi": "25/7/1980",
+    "es": "25/7/1980",
+    "fr": "25/07/1980",
+    "ar": "٢٥‏/٧‏/١٩٨٠",
+    "bn": "২৫/৭/১৯৮০",
+    "ru": "25.07.1980",
+    "pt": "25/07/1980",
+    "ur": "25/7/1980",
+    "id": "25/7/1980",
+    "de": "25.7.1980",
+    "ja": "1980/7/25",
+    "pcm": "25/7/1980",
+    "mr": "२५/७/१९८०",
+    "te": "25/7/1980"
+  },
+  "displayNames": {
+    "en": "Switzerland",
+    "zh": "瑞士",
+    "hi": "स्विट्ज़रलैंड",
+    "es": "Suiza",
+    "fr": "Suisse",
+    "ar": "سويسرا",
+    "bn": "সুইজারল্যান্ড",
+    "ru": "Швейцария",
+    "pt": "Suíça",
+    "ur": "سوئٹزر لینڈ",
+    "id": "Swiss",
+    "de": "Schweiz",
+    "ja": "スイス",
+    "pcm": "Swítsaland",
+    "mr": "स्वित्झर्लंड",
+    "te": "స్విట్జర్లాండ్"
+  },
+  "numberFormats": {
+    "en": "275,760.913",
+    "zh": "275,760.913",
+    "hi": "2,75,760.913",
+    "es": "275.760,913",
+    "fr": "275 760,913",
+    "ar": "٢٧٥٬٧٦٠٫٩١٣",
+    "bn": "২,৭৫,৭৬০.৯১৩",
+    "ru": "275 760,913",
+    "pt": "275.760,913",
+    "ur": "275,760.913",
+    "id": "275.760,913",
+    "de": "275.760,913",
+    "ja": "275,760.913",
+    "pcm": "275,760.913",
+    "mr": "२,७५,७६०.९१३",
+    "te": "2,75,760.913"
+  },
+  "pluralRules": {
+    "en": "other",
+    "zh": "other",
+    "hi": "one",
+    "es": "other",
+    "fr": "one",
+    "ar": "zero",
+    "bn": "one",
+    "ru": "many",
+    "pt": "one",
+    "ur": "other",
+    "id": "other",
+    "de": "other",
+    "ja": "other",
+    "pcm": "one",
+    "mr": "other",
+    "te": "other"
+  },
+  "relativeTime": {
+    "en": "586,920.617 hours ago",
+    "zh": "586,920.617小时前",
+    "hi": "5,86,920.617 घंटे पहले",
+    "es": "hace 586.920,617 horas",
+    "fr": "il y a 586 920,617 heures",
+    "ar": "قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة",
+    "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে",
+    "ru": "586 920,617 часа назад",
+    "pt": "há 586.920,617 horas",
+    "ur": "586,920.617 گھنٹے پہلے",
+    "id": "586.920,617 jam yang lalu",
+    "de": "vor 586.920,617 Stunden",
+    "ja": "586,920.617 時間前",
+    "pcm": "586,920.617 áwa wé dọ́n pas",
+    "mr": "५,८६,९२०.६१७ तासांपूर्वी",
+    "te": "5,86,920.617 గంటల క్రితం"
+  }
+}

filename: test/fixtures/icu/localizationData-v76.1.json
patch: @@ -0,0 +1,128 @@
+{
+  "dateStrings": {
+    "en": "Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)",
+    "zh": "Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)",
+    "hi": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)",
+    "es": "Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)",
+    "fr": "Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)",
+    "ar": "Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)",
+    "bn": "Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)",
+    "ru": "Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)",
+    "pt": "Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)",
+    "ur": "Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)",
+    "id": "Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)",
+    "de": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)",
+    "ja": "Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)",
+    "pcm": "Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)",
+    "mr": "Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)",
+    "te": "Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)"
+  },
+  "dateTimeFormats": {
+    "en": "7/25/1980, 1:35:33 AM",
+    "zh": "1980/7/25 01:35:33",
+    "hi": "25/7/1980, 1:35:33 am",
+    "es": "25/7/1980, 1:35:33",
+    "fr": "25/07/1980 01:35:33",
+    "ar": "25‏/7‏/1980، 1:35:33 ص",
+    "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM",
+    "ru": "25.07.1980, 01:35:33",
+    "pt": "25/07/1980, 01:35:33",
+    "ur": "25/7/1980، 1:35:33 AM",
+    "id": "25/7/1980, 01.35.33",
+    "de": "25.7.1980, 01:35:33",
+    "ja": "1980/7/25 1:35:33",
+    "pcm": "25/7/1980 01:35:33",
+    "mr": "२५/७/१९८०, १:३५:३३ AM",
+    "te": "25/7/1980 1:35:33 AM"
+  },
+  "dateFormats": {
+    "en": "7/25/1980",
+    "zh": "1980/7/25",
+    "hi": "25/7/1980",
+    "es": "25/7/1980",
+    "fr": "25/07/1980",
+    "ar": "25‏/7‏/1980",
+    "bn": "২৫/৭/১৯৮০",
+    "ru": "25.07.1980",
+    "pt": "25/07/1980",
+    "ur": "25/7/1980",
+    "id": "25/7/1980",
+    "de": "25.7.1980",
+    "ja": "1980/7/25",
+    "pcm": "25/7/1980",
+    "mr": "२५/७/१९८०",
+    "te": "25/7/1980"
+  },
+  "displayNames": {
+    "en": "Switzerland",
+    "zh": "瑞士",
+    "hi": "स्विट्ज़रलैंड",
+    "es": "Suiza",
+    "fr": "Suisse",
+    "ar": "سويسرا",
+    "bn": "সুইজারল্যান্ড",
+    "ru": "Швейцария",
+    "pt": "Suíça",
+    "ur": "سوئٹزر لینڈ",
+    "id": "Swiss",
+    "de": "Schweiz",
+    "ja": "スイス",
+    "pcm": "Swítsaland",
+    "mr": "स्वित्झर्लंड",
+    "te": "స్విట్జర్లాండ్"
+  },
+  "numberFormats": {
+    "en": "275,760.913",
+    "zh": "275,760.913",
+    "hi": "2,75,760.913",
+    "es": "275.760,913",
+    "fr": "275 760,913",
+    "ar": "275,760.913",
+    "bn": "২,৭৫,৭৬০.৯১৩",
+    "ru": "275 760,913",
+    "pt": "275.760,913",
+    "ur": "275,760.913",
+    "id": "275.760,913",
+    "de": "275.760,913",
+    "ja": "275,760.913",
+    "pcm": "275,760.913",
+    "mr": "२,७५,७६०.९१३",
+    "te": "2,75,760.913"
+  },
+  "pluralRules": {
+    "en": "other",
+    "zh": "other",
+    "hi": "one",
+    "es": "other",
+    "fr": "one",
+    "ar": "zero",
+    "bn": "one",
+    "ru": "many",
+    "pt": "one",
+    "ur": "other",
+    "id": "other",
+    "de": "other",
+    "ja": "other",
+    "pcm": "one",
+    "mr": "other",
+    "te": "other"
+  },
+  "relativeTime": {
+    "en": "586,920.617 hours ago",
+    "zh": "586,920.617小时前",
+    "hi": "5,86,920.617 घंटे पहले",
+    "es": "hace 586.920,617 horas",
+    "fr": "il y a 586 920,617 heures",
+    "ar": "قبل 586,920.617 ساعة",
+    "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে",
+    "ru": "586 920,617 часа назад",
+    "pt": "há 586.920,617 horas",
+    "ur": "586,920.617 گھنٹے پہلے",
+    "id": "586.920,617 jam yang lalu",
+    "de": "vor 586.920,617 Stunden",
+    "ja": "586,920.617 時間前",
+    "pcm": "586,920.617 áwa wé dọ́n pas",
+    "mr": "५,८६,९२०.६१७ तासांपूर्वी",
+    "te": "5,86,920.617 గంటల క్రితం"
+  }
+}

filename: test/parallel/test-icu-env.js
patch: @@ -2,11 +2,38 @@
 const common = require('../common');
 const assert = require('assert');
 const { execFileSync } = require('child_process');
+const { readFileSync, globSync } = require('fs');
+const { path } = require('../common/fixtures');
+
+
+// This test checks for regressions in environment variable handling and
+// caching, but the localization data originated from ICU might change
+// over time.
+//
+// The json file can be updated using `tools/icu/update-test-data.js`
+// whenever ICU is updated. Run the update script if this test fails after
+// an ICU update, and verify that only expected values are updated.
+// Typically, only a few strings change with each ICU update. If this script
+// suddenly generates identical values for all locales, it indicates a bug.
+// Editing json file manually is also fine.
+const localizationDataFile = path(`icu/localizationData-v${process.versions.icu}.json`);
+
+let localizationData;
+try {
+  localizationData = JSON.parse(readFileSync(localizationDataFile));
+} catch ({ code }) {
+  assert.strictEqual(code, 'ENOENT');
+
+  // No data for current version, try latest known version
+  const [ latestVersion ] = globSync('test/fixtures/icu/localizationData-*.json')
+    .map((file) => file.match(/localizationData-v(.*)\.json/)[1])
+    .sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
+  console.log(`The ICU is v${process.versions.icu}, but there is no fixture for this version. ` +
+  `Trying the latest known version: v${latestVersion}. If this test fails with a few strings changed ` +
+  `after ICU update, run this: \n${process.argv[0]} tools/icu/update-test-data.mjs\n`);
+  localizationData = JSON.parse(readFileSync(path(`icu/localizationData-v${latestVersion}.json`)));
+}
 
-// system-icu should not be tested
-const hasBuiltinICU = process.config.variables.icu_gyp_path === 'tools/icu/icu-generic.gyp';
-if (!hasBuiltinICU)
-  common.skip('system ICU');
 
 // small-icu doesn't support non-English locales
 const hasFullICU = (() => {
@@ -100,45 +127,11 @@ if (isMockable) {
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toString()')),
-    [
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)',
-      'Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)',
-    ]
+    Object.values(localizationData.dateStrings)
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toLocaleString()')),
-    [
-      '7/25/1980, 1:35:33 AM',
-      '1980/7/25 01:35:33',
-      '25/7/1980, 1:35:33 am',
-      '25/7/1980, 1:35:33',
-      '25/07/1980 01:35:33',
-      '25‏/7‏/1980، 1:35:33 ص',
-      '২৫/৭/১৯৮০, ১:৩৫:৩৩ AM',
-      '25.07.1980, 01:35:33',
-      '25/07/1980, 01:35:33',
-      '25/7/1980، 1:35:33 AM',
-      '25/7/1980, 01.35.33',
-      '25.7.1980, 01:35:33',
-      '1980/7/25 1:35:33',
-      '25/7/1980 01:35:33',
-      '२५/७/१९८०, १:३५:३३ AM',
-      '25/7/1980 1:35:33 AM',
-    ]
+    Object.values(localizationData.dateTimeFormats)
   );
   assert.strictEqual(
     runEnvOutside({ LANG: 'en' }, '["z", "ä"].sort(new Intl.Collator().compare)'),
@@ -152,72 +145,23 @@ if (isMockable) {
     locales.map(
       (LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Intl.DateTimeFormat().format(333333333333)')
     ),
-    [
-      '7/25/1980', '1980/7/25',
-      '25/7/1980', '25/7/1980',
-      '25/07/1980', '25‏/7‏/1980',
-      '২৫/৭/১৯৮০', '25.07.1980',
-      '25/07/1980', '25/7/1980',
-      '25/7/1980', '25.7.1980',
-      '1980/7/25', '25/7/1980',
-      '२५/७/१९८०', '25/7/1980',
-    ]
+    Object.values(localizationData.dateFormats)
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.DisplayNames(undefined, { type: "region" }).of("CH")')),
-    [
-      'Switzerland', '瑞士',
-      'स्विट्ज़रलैंड', 'Suiza',
-      'Suisse', 'سويسرا',
-      'সুইজারল্যান্ড', 'Швейцария',
-      'Suíça', 'سوئٹزر لینڈ',
-      'Swiss', 'Schweiz',
-      'スイス', 'Swítsaland',
-      'स्वित्झर्लंड', 'స్విట్జర్లాండ్',
-    ]
+    Object.values(localizationData.displayNames)
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.NumberFormat().format(275760.913)')),
-    [
-      '275,760.913', '275,760.913',
-      '2,75,760.913', '275.760,913',
-      '275 760,913', '275,760.913',
-      '২,৭৫,৭৬০.৯১৩', '275 760,913',
-      '275.760,913', '275,760.913',
-      '275.760,913', '275.760,913',
-      '275,760.913', '275,760.913',
-      '२,७५,७६०.९१३', '2,75,760.913',
-    ]
+    Object.values(localizationData.numberFormats)
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.PluralRules().select(0)')),
-    [
-      'other', 'other', 'one', 'other',
-      'one', 'zero', 'one', 'many',
-      'one', 'other', 'other', 'other',
-      'other', 'one', 'other', 'other',
-    ]
+    Object.values(localizationData.pluralRules)
   );
   assert.deepStrictEqual(
     locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.RelativeTimeFormat().format(-586920.617, "hour")')),
-    [
-      '586,920.617 hours ago',
-      '586,920.617小时前',
-      '5,86,920.617 घंटे पहले',
-      'hace 586.920,617 horas',
-      'il y a 586 920,617 heures',
-      'قبل 586,920.617 ساعة',
-      '৫,৮৬,৯২০.৬১৭ ঘন্টা আগে',
-      '586 920,617 часа назад',
-      'há 586.920,617 horas',
-      '586,920.617 گھنٹے پہلے',
-      '586.920,617 jam yang lalu',
-      'vor 586.920,617 Stunden',
-      '586,920.617 時間前',
-      '586,920.617 áwa wé dọ́n pas',
-      '५,८६,९२०.६१७ तासांपूर्वी',
-      '5,86,920.617 గంటల క్రితం',
-    ]
+    Object.values(localizationData.relativeTime)
   );
 }
 

filename: tools/icu/update-test-data.mjs
patch: @@ -0,0 +1,81 @@
+/*
+ * This script updates the `test/fixtures/icu/localizationData.json` data
+ * used by `test/parallel/test-icu-env.js` test.
+ * Run this script after an ICU update if locale-specific output changes are
+ * causing the test to fail.
+ * Typically, only a few strings change with each ICU update. If this script
+ * suddenly generates identical values for all locales, it indicates a bug.
+ * Note that Node.js must be built with either `--with-intl=full-icu` after
+ * updating ICU, or with `--with-intl=system-icu` if system version matches.
+ * Wrong version or small-icu might produce wrong values.
+ * Manually editing the json file is fine, too.
+ */
+
+import { execFileSync } from 'node:child_process';
+import { writeFileSync } from 'node:fs';
+
+const locales = [
+  'en', 'zh', 'hi', 'es',
+  'fr', 'ar', 'bn', 'ru',
+  'pt', 'ur', 'id', 'de',
+  'ja', 'pcm', 'mr', 'te',
+];
+
+const outputFilePath = new URL(`../../test/fixtures/icu/localizationData-v${process.versions.icu}.json`, import.meta.url);
+
+const runEnvCommand = (envVars, code) =>
+  execFileSync(
+    process.execPath,
+    ['-e', `process.stdout.write(String(${code}));`],
+    { env: { ...process.env, ...envVars }, encoding: 'utf8' },
+  );
+
+// Generate the localization data for all locales
+const localizationData = locales.reduce((acc, locale) => {
+  acc.dateStrings[locale] = runEnvCommand(
+    { LANG: locale, TZ: 'Europe/Zurich' },
+    `new Date(333333333333).toString()`,
+  );
+
+  acc.dateTimeFormats[locale] = runEnvCommand(
+    { LANG: locale, TZ: 'Europe/Zurich' },
+    `new Date(333333333333).toLocaleString()`,
+  );
+
+  acc.dateFormats[locale] = runEnvCommand(
+    { LANG: locale, TZ: 'Europe/Zurich' },
+    `new Intl.DateTimeFormat().format(333333333333)`,
+  );
+
+  acc.displayNames[locale] = runEnvCommand(
+    { LANG: locale },
+    `new Intl.DisplayNames(undefined, { type: "region" }).of("CH")`,
+  );
+
+  acc.numberFormats[locale] = runEnvCommand(
+    { LANG: locale },
+    `new Intl.NumberFormat().format(275760.913)`,
+  );
+
+  acc.pluralRules[locale] = runEnvCommand(
+    { LANG: locale },
+    `new Intl.PluralRules().select(0)`,
+  );
+
+  acc.relativeTime[locale] = runEnvCommand(
+    { LANG: locale },
+    `new Intl.RelativeTimeFormat().format(-586920.617, "hour")`,
+  );
+
+  return acc;
+}, {
+  dateStrings: {},
+  dateTimeFormats: {},
+  dateFormats: {},
+  displayNames: {},
+  numberFormats: {},
+  pluralRules: {},
+  relativeTime: {},
+});
+
+writeFileSync(outputFilePath, JSON.stringify(localizationData, null, 2) + '\n');