C++ 国际化 (i18n):从基础到高级技术
国际化(缩写为 i18n,来自英文 "internationalization",其中 18 表示第一个字母 'i' 和最后一个字母 'n' 之间的字母数量)是指设计软件使其能够适应不同语言和区域特性而无需修改代码的过程。在 C++ 中,这项任务有其特殊性:该语言不提供用于处理翻译的内置工具,但有几种强大的库可以解决这个问题。
为什么 i18n 对 C++ 项目很重要?
现代 C++ 应用程序很少局限于单一语言。桌面程序、游戏、服务器端解决方案——所有这些都需要支持多种区域设置。i18n 解决的主要问题包括:
- 编码处理——从 ASCII 过渡到 UTF-8、UTF-16 和其他多字节编码;
- 数字、日期和货币的格式化——不同国家使用不同的分隔符和格式;
- 句子中的词序——俄语需要变格,而英语需要冠词;
- 复数形式——复数规则各不相同(俄语有 3 种形式,英语有 2 种)。
C++ 中主要的 i18n 库
1. GNU gettext——经典之作
GNU gettext 是 C 和 C++ 中最流行的国际化库。它使用独立的翻译文件 (.po/.mo),并允许将字符串与代码分离。
基本使用示例:
#include <iostream>#include <libintl.h>#include <locale.h>
#define _(str) gettext(str)
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 工具提取字符串,该工具扫描源代码并创建 .pot 文件。然后翻译人员处理 .po 文件。
优点:
- 集成简单;
- 庞大的社区和众多工具(Poedit、Lokalize);
- 通过
ngettext()支持复数形式; - 可在任何平台上运行。
缺点:
- 没有额外技巧的情况下不支持上下文翻译;
- 需要单独的构建步骤来生成 .mo 文件。
2. Boost.Locale——现代 C++ 方法
Boost.Locale 库提供了更现代且类型安全的接口。它构建在 ICU(International Components for Unicode)或系统区域设置之上。
翻译工作示例:
#include <boost/locale.hpp>#include <iostream>
int main() { using namespace boost::locale; generator gen; std::locale loc = gen("ru_RU.UTF-8"); std::locale::global(loc); // 创建翻译器 translator tr; std::cout << tr("Hello, world!") << std::endl; std::cout << tr("Today is {1}", "Monday") << std::endl; // 复数形式 std::cout << tr("You have {1} message", "You have {1} messages", 5) << std::endl; return 0;}优点:
- 原生支持 UTF-8;
- 日期、数字和货币的格式化;
- 支持上下文翻译;
- 可与 std::string 和 std::wstring 一起使用。
缺点:
- 依赖 Boost(重量级库);
- 翻译人员的工具较少。
3. ICU——工业标准
ICU(Intern