國際化支援#

Node.js 有許多功能,讓撰寫國際化程式變得更簡單。其中一些是

Node.js 和底層的 V8 引擎使用 Unicode 國際元件 (ICU) 以原生 C/C++ 程式碼實作這些功能。完整的 ICU 資料集預設由 Node.js 提供。不過,由於 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()none (函式為 no-op)fullfullfull
String.prototype.to*Case()fullfullfullfull
Intlnone (物件不存在)部分/全部 (取決於作業系統)部分 (僅英文)full
String.prototype.localeCompare()部分 (不具備區域感知)fullfullfull
String.prototype.toLocale*Case()部分 (不具備區域感知)fullfullfull
Number.prototype.toLocaleString()部分 (不具備區域感知)部分/全部 (取決於作業系統)部分 (僅英文)full
Date.prototype.toLocale*String()部分 (不具備區域感知)部分/全部 (取決於作業系統)部分 (僅英文)full
舊版 URL 分析器部分 (不支援 IDN)fullfullfull
WHATWG URL 分析器部分 (不支援 IDN)fullfullfull
require('node:buffer').transcode()none (函式不存在)fullfullfull
REPL部分 (不精確的行編輯)fullfullfull
require('node:util').TextDecoder部分 (支援基本編碼)部分/全部 (取決於作業系統)部分 (僅 Unicode)full
RegExp Unicode 屬性逸出none (無效的 RegExp 錯誤)fullfullfull

「(不具備區域感知)」標示表示函式會執行其作業,就像函式的非 Locale 版本一樣,如果有的話。例如,在 none 模式下,Date.prototype.toLocaleString() 的作業與 Date.prototype.toString() 相同。

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

如果選擇此選項,ICU 會停用,而上述大部分國際化功能在產生的 node 二進位檔中將會不可用

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

Node.js 可以連結到系統上已安裝的 ICU 建置。事實上,大多數 Linux 發行版都已經安裝 ICU,而此選項將讓系統中其他元件能重複使用同一組資料。

僅需要 ICU 函式庫本身的功能,例如 String.prototype.normalize()WHATWG URL parser,在 system-icu 下獲得完全支援。此外,需要 ICU 地區資料的功能,例如 Intl.DateTimeFormat可能會獲得完全或部分支援,具體取決於系統上安裝的 ICU 資料的完整性。

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

此選項會讓產生的二進位檔靜態連結到 ICU 函式庫,並在 node 可執行檔中包含 ICU 資料的子集(通常僅包含英文地區資料)。

僅需要 ICU 函式庫本身的功能,例如 String.prototype.normalize()WHATWG URL parser,在 small-icu 下獲得完全支援。此外,需要 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 資料的更多詳細資訊。

npm 模組 full-icu 透過偵測執行中 node 可執行檔的 ICU 版本,並下載適當的資料檔,大幅簡化 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 的區段。