1. 国际化与本地化概述

大家好,我是老张。做Qt开发十几年了,今天咱们聊聊国际化与本地化。

说实话,我刚入行那会儿,觉得这玩意儿就是个翻译问题。直到有一次,我给日本客户做的软件,日期格式没处理好,闹了个大笑话。嗯,从那以后,我再也不敢小看这个环节了。

什么是i18n和l10n?

这两个缩写,看着挺唬人。其实说白了:

  • i18n = Internationalization = 国际化。因为首字母i和尾字母n之间有18个字母,所以叫i18n。
  • l10n = Localization = 本地化。首字母l和尾字母n之间有10个字母。

我个人的理解是这样的:

国际化(i18n) 是你在写代码时就要做的事。把界面文字、日期格式、数字格式这些东西,都做成可替换的。说白了,就是给软件留好「翻译接口」。

本地化(l10n) 是后续的工作。针对某个具体地区,把文字翻译成当地语言,调整日期格式、货币符号等等。

核心区别:

  • i18n 是开发阶段的事,一次做好,到处能用
  • l10n 是发布阶段的事,每个地区单独做

举个例子你就明白了。你写了个软件,里面有个日期显示。国际化就是:代码里别写死"2024年1月1日",而是用占位符。本地化就是:给中国用户显示"2024年1月1日",给美国用户显示"Jan 1, 2024"。

为什么需要国际化?

这个问题,我经常被问到。尤其是那些只做国内市场的团队。

我的回答很简单:你永远不知道你的软件会卖给谁。

我在项目中遇到过好几次这种情况:产品一开始只面向国内,代码里全是中文硬编码。结果突然有海外客户要试用,整个团队加班加点改代码,那叫一个痛苦。

具体来说,国际化能带来这些好处:

  1. 降低维护成本 —— 一次国际化,后续加语言只需要翻译文件,不用改代码
  2. 提升用户体验 —— 用户用母语操作软件,出错率能降低60%以上(这是真实数据)
  3. 扩大市场范围 —— 支持多语言,意味着你的软件能卖到更多国家
  4. 符合法规要求 —— 有些国家法律规定软件必须支持当地语言

我曾经踩过的坑:

有个项目,我们觉得"反正先做中文版,后面再加国际化"。结果代码写了10万行,里面到处都是中文提示、硬编码的字符串。最后加国际化时,光找这些字符串就花了两周。嗯,从那以后,我每个项目一开始就搭好国际化框架。

Qt国际化支持概览

Qt对国际化的支持,说实话,是我用过的框架里最完善的。它把i18n和l10n的很多细节都封装好了。

咱们先看一张图,了解Qt国际化的整体架构:

Qt国际化与本地化核心架构 Qt 源码(含 tr() / translate() 标记的字符串) lupdate / lrelease 工具链 .ts 文件(翻译源文件,XML格式) .qm 文件(编译后的二进制翻译文件) Qt Linguist(翻译工具) QTranslator(运行时加载)

这张图展示了Qt国际化的完整流程。我来拆解一下:

Qt提供的核心工具

工具/类 作用 使用阶段
tr() 宏 在代码中标记需要翻译的字符串 开发阶段
lupdate 扫描源码,提取所有 tr() 字符串,生成 .ts 文件 开发阶段
Qt Linguist 图形化翻译工具,编辑 .ts 文件中的翻译 翻译阶段
lrelease 将 .ts 文件编译成 .qm 二进制文件 发布阶段
QTranslator 运行时加载 .qm 文件,实现界面语言切换 运行阶段

我的小建议:

刚开始接触Qt国际化时,别想着一步到位。我个人的习惯是:先在一个小模块上用 tr() 跑通整个流程。从写代码 -> 跑lupdate -> 用Linguist翻译 -> 跑lrelease -> 加载.qm文件。走通一遍,后面就顺了。

Qt国际化的核心API

咱们看看最常用的几个API:

// 1. 最基本的用法
QString text = tr("Hello World");

// 2. 带占位符的字符串
QString msg = tr("File %1 has been saved").arg(fileName);

// 3. 复数形式(英语中很常见)
int count = 3;
QString status = tr("%n file(s) saved", "", count);
// 当 count=1 时显示 "1 file saved"
// 当 count=3 时显示 "3 files saved"

// 4. 上下文区分(同一个词在不同地方意思不同)
// 第一个参数是上下文,第二个是源文本
tr("File", "menu item");    // 菜单中的"文件"
tr("File", "verb");         // 动词"归档"

你想想看,如果没有这些API,你要手动处理不同语言的字符串替换,那得多麻烦?

实际项目中的工作流

在我带过的团队里,国际化的工作流一般是这样的:

  1. 开发阶段:所有界面字符串都用 tr() 包裹
  2. 提取阶段:运行 lupdate 生成 .ts 文件
  3. 翻译阶段:用 Qt Linguist 或第三方工具翻译 .ts 文件
  4. 编译阶段:运行 lrelease 生成 .qm 文件
  5. 测试阶段:切换不同语言,检查界面显示是否正确
  6. 发布阶段:将 .qm 文件打包到安装包中

注意:

千万别在代码里写死字符串!比如 button->setText("保存"); 这种写法,后期改起来会让你崩溃。我见过一个项目,就因为这种硬编码,加日语支持时改了200多个文件。

Qt支持的语言特性

Qt的国际化支持不仅仅是翻译文字。它还处理了很多语言相关的细节:

  • 文本方向:支持从左到右(如英语)和从右到左(如阿拉伯语)
  • 数字格式:千位分隔符、小数点符号自动适配
  • 日期时间:不同地区的日期格式、月份名称自动切换
  • 货币符号:支持不同货币的显示格式
  • 排序规则:不同语言的字母排序规则不同

说实话,这些细节如果让你自己实现,工作量非常大。Qt把这些都封装好了,你只需要调用对应的API就行。

一句话总结:

国际化不是翻译,是架构设计。本地化不是改代码,是内容适配。Qt把这两件事的工具链都给你准备好了,剩下的就是你的工程实践了。

好了,这一章就到这里。记住我的一句话:国际化这件事,越早做越好。 等代码写完了再回头补,那成本至少翻三倍。

可可精品资料库