國際化支援#

Node.js 有許多功能可以更輕鬆地編寫國際化程式。其中一些是:

Node.js 和底層的 V8 引擎使用國際化統一碼元件 (ICU) 在本地 C/C++ 程式碼中實現這些功能。預設情況下,Node.js 提供完整的 ICU 資料集。但是,由於 ICU 資料檔案的大小,提供了幾個選項用於在構建或執行 Node.js 時自定義 ICU 資料集。

構建 Node.js 的選項#

為了控制 ICU 在 Node.js 中的使用方式,編譯期間有四個 configure 選項可用。有關如何編譯 Node.js 的更多詳細資訊,請參見 BUILDING.md

  • --with-intl=none/--without-intl
  • --with-intl=system-icu
  • --with-intl=small-icu
  • --with-intl=full-icu (預設)

每個 configure 選項下可用的 Node.js 和 JavaScript 功能概覽:

功能nonesystem-icusmall-icufull-icu
String.prototype.normalize()無 (函式為空操作)完整完整完整
String.prototype.to*Case()完整完整完整完整
Intl無 (物件不存在)部分/完整 (取決於作業系統)部分 (僅限英語)完整
String.prototype.localeCompare()部分 (不感知語言環境)完整完整完整
String.prototype.toLocale*Case()部分 (不感知語言環境)完整完整完整
Number.prototype.toLocaleString()部分 (不感知語言環境)部分/完整 (取決於作業系統)部分 (僅限英語)完整
Date.prototype.toLocale*String()部分 (不感知語言環境)部分/完整 (取決於作業系統)部分 (僅限英語)完整
舊版 URL 解析器部分 (不支援 IDN)完整完整完整
WHATWG URL 解析器部分 (不支援 IDN)完整完整完整
require('node:buffer').transcode()無 (函式不存在)完整完整完整
REPL部分 (行編輯不精確)完整完整完整
require('node:util').TextDecoder部分 (支援基本編碼)部分/完整 (取決於作業系統)部分 (僅限 Unicode)完整
RegExp Unicode 屬性轉義無 (無效的 RegExp 錯誤)完整完整完整

“(不感知語言環境)”的標記表示該函式的執行方式與其非 Locale 版本的函式(如果存在)完全相同。例如,在 none 模式下,Date.prototype.toLocaleString() 的操作與 Date.prototype.toString() 的操作完全相同。

停用所有國際化功能 (none)#

如果選擇此選項,ICU 將被停用,並且上述大多數國際化功能在生成的 node 二進位制檔案中將不可用

使用預安裝的 ICU 構建 (system-icu)#

Node.js 可以連結到系統上已安裝的 ICU 構建。實際上,大多數 Linux 發行版都已安裝 ICU,此選項可以重用作業系統中其他元件所使用的同一組資料。

system-icu 模式下,僅需要 ICU 庫本身的功能(例如 String.prototype.normalize()WHATWG URL 解析器)會得到完全支援。而額外需要 ICU 語言環境資料的功能(例如 Intl.DateTimeFormat可能會得到完全或部分支援,具體取決於系統上安裝的 ICU 資料的完整性。

嵌入一組有限的 ICU 資料 (small-icu)#

此選項使生成的二進位制檔案靜態連結到 ICU 庫,並在 node 可執行檔案中包含 ICU 資料的子集(通常只有英語語言環境)。

small-icu 模式下,僅需要 ICU 庫本身的功能(例如 String.prototype.normalize()WHATWG URL 解析器)會得到完全支援。而額外需要 ICU 語言環境資料的功能(例如 Intl.DateTimeFormat)通常只支援英語語言環境。

const january = new Date(9e8);
const english = new Intl.DateTimeFormat('en', { month: 'long' });
const spanish = new Intl.DateTimeFormat('es', { month: 'long' });

console.log(english.format(january));
// Prints "January"
console.log(spanish.format(january));
// Prints either "M01" or "January" on small-icu, depending on the user’s default locale
// Should print "enero" 

此模式在功能和二進位制檔案大小之間提供了一種平衡。

在執行時提供 ICU 資料#

如果使用 small-icu 選項,仍然可以在執行時提供額外的語言環境資料,以便 JS 方法能支援所有 ICU 語言環境。假設資料檔案儲存在 /runtime/directory/with/dat/file,可以透過以下任一方式使其對 ICU 可用:

  • --with-icu-default-data-dir 配置選項

    ./configure --with-icu-default-data-dir=/runtime/directory/with/dat/file --with-intl=small-icu 

    這隻會將預設資料目錄路徑嵌入到二進位制檔案中。實際的資料檔案將在執行時從此目錄路徑載入。

  • NODE_ICU_DATA 環境變數

    env NODE_ICU_DATA=/runtime/directory/with/dat/file node 
  • --icu-data-dir CLI 引數

    node --icu-data-dir=/runtime/directory/with/dat/file 

當指定了多個選項時,--icu-data-dir CLI 引數的優先順序最高,其次是 NODE_ICU_DATA 環境變數,然後是 --with-icu-default-data-dir 配置選項。

ICU 能夠自動查詢和載入各種資料格式,但資料必須與 ICU 版本匹配,並且檔名必須正確。資料檔案最常見的名稱是 icudtX[bl].dat,其中 X 表示目標 ICU 版本,bl 表示系統的位元組序。如果無法從指定目錄讀取預期的資料檔案,Node.js 將無法載入。與當前 Node.js 版本對應的資料檔名可以透過以下方式計算:

`icudt${process.versions.icu.split('.')[0]}${os.endianness()[0].toLowerCase()}.dat`; 

有關其他支援的格式和 ICU 資料的更多詳細資訊,請查閱 ICU 使用者指南中的 "ICU Data" 文章。

full-icu npm 模組可以大大簡化 ICU 資料的安裝,它會檢測正在執行的 node 可執行檔案的 ICU 版本並下載相應的資料檔案。透過 npm i full-icu 安裝該模組後,資料檔案將位於 ./node_modules/full-icu。然後可以將此路徑傳遞給 NODE_ICU_DATA--icu-data-dir(如上所示),以啟用完整的 Intl 支援。

嵌入整個 ICU (full-icu)#

此選項使生成的二進位制檔案靜態連結到 ICU,幷包含完整的 ICU 資料集。以這種方式建立的二進位制檔案沒有進一步的外部依賴,並支援所有語言環境,但可能會相當大。如果沒有傳遞 --with-intl 標誌,這是預設行為。官方釋出的二進位制檔案也是在此模式下構建的。

檢測國際化支援#

要驗證 ICU 是否已啟用(system-icusmall-icufull-icu),只需檢查 Intl 的存在即可:

const hasICU = typeof Intl === 'object'; 

或者,檢查 process.versions.icu 也可以,這個屬性僅在 ICU 啟用時才會被定義:

const hasICU = typeof process.versions.icu === 'string'; 

要檢查對非英語語言環境的支援(即 full-icusystem-icu),Intl.DateTimeFormat 是一個很好的區分因素:

const hasFullICU = (() => {
  try {
    const january = new Date(9e8);
    const spanish = new Intl.DateTimeFormat('es', { month: 'long' });
    return spanish.format(january) === 'enero';
  } catch (err) {
    return false;
  }
})(); 

對於更詳盡的 Intl 支援測試,以下資源可能會有所幫助:

  • btest402:通常用於檢查帶有 Intl 支援的 Node.js 是否構建正確。
  • Test262:ECMAScript 的官方一致性測試套件,其中包含專門針對 ECMA-402 的部分。