C++ 国际化 (i18n):从基础到高级技术
国际化(缩写为 i18n,取自 "internationalization",其中 18 表示首字母和尾字母之间的字母数量)是指设计软件的过程,使其能够轻松适应不同的语言和地区,而无需修改源代码。对于传统上用于高性能和跨平台应用程序的 C++ 语言而言,正确实现 i18n 至关重要。在本文中,我们将介绍本地化 C++ 应用程序的主要方法、库和实际示例。
i18n 的基本概念
在介绍工具之前,理解关键概念很重要:
- 本地化 (l10n) — 针对特定区域调整翻译后的文本、日期、数字和货币格式。
- 区域设置 — 定义数据格式的一组规则(语言、地区、编码)。
- Unicode 和 UTF-8 — 字符编码标准,是现代国际化的必备条件。
- 复数形式 — 正确显示复数形式(例如,“1 个文件”、“2 个文件”、“10 个文件”)。
用于 C++ 的 GNU gettext 库
GNU gettext 是 Unix/Linux 世界中最流行的国际化工具,它也能很好地与 C++ 配合使用。它提供了极简的 API 和强大的实用程序,用于提取和管理翻译。
安装和配置
要在 C++ 项目中使用 gettext,需要安装 libintl 包并包含头文件:
#include <libintl.h>#include <locale.h>
#define _(STRING) gettext(STRING)基本使用示例
#include <iostream>#include <libintl.h>#include <locale.h>
int main() { setlocale(LC_ALL, ""); bindtextdomain("myapp", "./locale"); textdomain("myapp");
std::cout << _("Hello, world!") << std::endl; std::cout << _("File not found") << std::endl; return 0;}创建翻译文件
该过程包括三个步骤:
- 提取字符串:
xgettext --keyword=_ main.cpp -o messages.po - 编辑 .po 文件 — 手动或通过 Poedit 添加翻译。
- 编译为 .mo:
msgfmt messages.po -o locale/ru/LC_MESSAGES/myapp.mo
复数形式支持
Gettext 通过 ngettext 函数支持复数形式:
int count = 5;printf(ngettext("%d file deleted", "%d files deleted", count), count);ICU(Unicode 国际化组件)库
ICU 是 IBM 提供的一个强大库,提供了一套完整的国际化工具:Unicode 支持、区域设置感知排序、数字、日期、货币格式化、时区处理等等。对于 C++,使用 icu4c 包中的 C++ API。
安装 ICU
在 Ubuntu/Debian 上:sudo apt install libicu-dev
在 macOS 上:brew install icu4c
数字和日期格式化
#include <unicode/numfmt.h>#include <unicode/datefmt.h>#include <iostream>
int main() { // 为 ru_RU 区域设置格式化数字 icu::UnicodeString pattern; icu::NumberFormat* fmt = icu::NumberFormat::createInstance( icu::Locale("ru", "RU"), status); icu::UnicodeString result; fmt->format(1234567.89, result); std::string utf8; result.toUTF8String(utf8); std::cout << "Число: " << utf8 << std::endl; // 1