共用方式為


Unicode 的國際元件 (ICU)

Unicode (ICU) 的國際元件是一組成熟的、廣泛使用的開放原始碼全球化 API。 ICU 利用 Unicode 龐大的通用地區設定資料存放庫 (CLDR) 作為其資料庫,為軟體應用程式提供全球化支援。 ICU 可廣泛移植,可在所有平臺上提供相同的結果給應用程式。

ICU 所提供全球化 API 服務的亮點

  • 代碼頁轉換:將文字數據轉換成 Unicode,以及幾乎任何其他字元集或編碼。 ICU 的轉換數據表是以 IBM 在數十年中收集的字元集數據為基礎,而且是隨處提供的最完整數據。
  • 定序:根據特定語言、地區或國家/地區的慣例和標準比較字串。 ICU 的定序是以 Unicode 定序演算法為基礎,加上 CLDR 的地區設定特定比較規則。
  • 格式化:根據所選地區設定慣例,格式化數位、日期、時間和貨幣金額。 這包括將月份和日期名稱翻譯成選取的語言、選擇適當的縮寫、正確排序欄位等等。此數據也來自 Common Locale Data Repository。
  • 時間計算:除了傳統的公曆之外,還提供多種行事曆類型。 提供一組完整的時區計算 API。
  • Unicode 支援:ICU 會密切追蹤 Unicode 標準,輕鬆存取所有 Unicode 字元屬性、Unicode 正規化、大小寫摺疊和其他基本作業,如 Unicode Standard所指定。
  • 正則表示式:ICU 的正則表示式完全支援 Unicode,同時提供非常具競爭力的效能。
  • Bidi:支持處理含有左至右(英文)和由右至左(阿拉伯文或希伯來文)數據的混合文字。

如需詳細資訊,您可以流覽 ICU 網站:http://site.icu-project.org/

概述

在 Windows 10 Creators Update 中,ICU 已整合至 Windows,讓 C API 和數據可供公開存取。

重要

Windows 中的ICU版本只會公開 C API。 它不會公開任何C++ API。 不幸的是,由於C++中缺少穩定的 ABI,因此不可能公開C++ API。

如需ICU C API 的檔,請參閱此處的官方ICU檔頁面:http://icu-project.org/apiref/icu4c/index.html#Module

Windows 中 ICU 連結庫變更的歷程記錄

版本 1703 (Creators Update)

ICU 連結庫第一次新增至此版本的 Windows 10 OS。 它已新增為:

  • 兩個系統 DLL:
    • icuuc.dll (這是 ICU “common” 連結庫)
    • icuin.dll (這是 ICU “i18n” 連結庫)
  • Windows 10 SDK 中的兩個頭檔:
    • icucommon.h
    • icui18n.h
  • Windows 10 SDK 中的兩個匯入連結庫:
    • icuuc.lib
    • icuin.lib

版本 1709 (Fall Creators Update)

已新增合併頭檔 icu.h,其中包含上述頭文件的內容(icucommon.h 和 icui18n.h),也會將 UCHAR 的類型變更為 char16_t

版本 1903 (2019 年 5 月更新)

已新增新的合併 DLL icu.dll,其中包含 「common」 和 「i18n」 連結庫。 此外,新的匯入連結庫已新增至 Windows 10 SDK:icu.lib

接下來,不會將任何新的 API 新增至舊標頭 (icucommon.h 和 icui18n.h) 或舊匯入 libs (icuuc.lib 和 icuin.lib)。 新的 API 只會新增至合併標頭 (icu.h) 和合併匯入 lib (icu.lib)。

開始

有三個主要步驟要遵循:(Windows 10 Creators Update 或更新版本)

  1. 您的應用程式需要以 Windows 10 版本 1703(Creators Update) 或更高版本為目標。

  2. 在標頭中新增:

    #include <icucommon.h>
    #include <icui18n.h>
    

    在 Windows 10 版本 1709 和更新版本上,您應該改為包含合併的標頭:

    #include <icu.h>
    
  3. 連結至兩個連結庫:

    • icuuc.lib
    • icuin.lib

    在 Windows 10 版本 1903 和更新版本上,您應該改用合併的連結庫:

    • icu.lib

然後,您可以從您想要的這些連結庫呼叫任何ICU C API。 (未公開C++ API。

重要

如果您使用舊版匯入連結庫 icuuc.lib 和 icuin.lib,請確定它們列在傘式連結庫之前,例如 onecoreuap.lib 或 WindowsApp.lib,位於 [其他相依性連結器] 設定中(請參閱下圖)。 否則,鏈接器會連結到icu.lib,這會導致嘗試在運行時間載入 icu.dll。 該 DLL 僅從 1903 版開始。 因此,如果使用者在 1903 版 Windows 機器上升級 Windows 10 SDK,應用程式將無法載入並執行。 如需 Windows 中 ICU 連結庫的歷程記錄,請參閱 Windows中 ICU 連結庫變更的歷程記錄。

icu 範例

注意

  • 這是「所有平臺」的組態。
  • 若要讓 Win32 應用程式使用 ICU,他們必須先呼叫 CoInitializeEx。 在 Windows 10 1903 版和更新版本上,可以使用合併的 ICU 連結庫(icu.dll/icu.lib),您可以使用合併的連結庫來省略 CoInitializeEx 呼叫。
  • ICU API 傳回的所有數據都不會與 Windows OS 一致,因為此對齊工作仍在進行中。 

ICU 範例應用程式

範例代碼段

下列範例說明如何在 C++ UWP 應用程式中使用 ICU API。 (它的目的不是完整的獨立應用程式,而是呼叫ICU方法的範例。

下列小型範例假設有一些方法 ErrorMessageOutputMessage 以某種方式將字元串輸出給使用者。

// On Windows 10 Creators Update, include the following two headers. With Windows 10 Fall Creators Update and later, you can just include the single header <icu.h>.
#include <icucommon.h>
#include <icui18n.h>

void FormatDateTimeICU()
{
    UErrorCode status = U_ZERO_ERROR;

    // Create a ICU date formatter, using only the 'short date' style format.
    UDateFormat* dateFormatter = udat_open(UDAT_NONE, UDAT_SHORT, nullptr, nullptr, -1, nullptr, 0, &status);

    if (U_FAILURE(status))
    {
        ErrorMessage(L"Failed to create date formatter.");
        return;
    }

    // Get the current date and time.
    UDate currentDateTime = ucal_getNow();

    int32_t stringSize = 0;
    
    // Determine how large the formatted string from ICU would be.
    stringSize = udat_format(dateFormatter, currentDateTime, nullptr, 0, nullptr, &status);

    if (status == U_BUFFER_OVERFLOW_ERROR)
    {
        status = U_ZERO_ERROR;
        // Allocate space for the formatted string.
        auto dateString = std::make_unique<UChar[]>(stringSize + 1);

        // Format the date time into the string.
        udat_format(dateFormatter, currentDateTime, dateString.get(), stringSize + 1, nullptr, &status);

        if (U_FAILURE(status))
        {
            ErrorMessage(L"Failed to format the date time.");
            return;
        }

        // Output the formatted date time.
        OutputMessage(dateString.get());
    }
    else
    {
        ErrorMessage(L"An error occured while trying to determine the size of the formatted date time.");
        return;
    }

    // We need to close the ICU date formatter.
    udat_close(dateFormatter);
}