Qt中的i18n
翻译流程
- 在源代码中标记待翻译的字符串
- 使用
lupdate
生成.ts
文件 - 使用
linguist
工具读写.ts
文件进行翻译 - 使用
lrelease
工具将.ts
文件转换成.qm
文件 - 在Qt程序中加载
.qm
文件。
标记字符串
常用的有QObject::tr(),QCoreApplication::translate()和QT_TRANSLATE_NOOP,lupdate工具也支持其他一些标记宏,可以命令行去查看。
在Qt中,每个待翻译的字符串都要属于一个context,所以,标记的时候要注意的也是context。
- QT_TRANSLATE_NOOP
QT_TRANSLATE_NOOP仅仅用于标记字符串,可以查看这个宏的定义,这个宏需要传入两个参数,第一个参数是context,第二个参数是待翻译的字符串。但是,宏的最终结果知识单纯的使用字符串本身。其实,这个宏仅仅是给lupdate工具识别使用的,lupdate遇到这个宏的时候,它就知道了“字符串clay是需要翻译的,并且属于clay_context上下文”。
如此,在Qt程序运行时,运行到源码中QT_TRANSLATE_NOOP的位置时,这依然是一个普通的字符串而已,如果需要翻译,需要再次调用QCoreApplication::translate(),传入context和字符串。
- tr()
继承自QObject的对象,都有一个tr()方法,只需要传入待翻译的字符串即可。这个方法实际上做了两件事:
- 标记字符串
- 运行时执行翻译
tr()方法实际上会把当前的类名作为context,最终调用QCoreApplication::translate()进行翻译。
-
QCoreApplication::translate()
这是一个全局可用的翻译方法,它同样需要context和字符串这两个参数。QCoreApplication::translate()和tr()一样做了两件事,不同的是,QCoreApplication::translate()方法可以传入context参数,并且可以全局调用。 -
自定义标记宏
可以自定义类似QT_TRANSLATE_NOOP标记的宏,但是,在自定义以后,调用lupdate生成.ts
文件的时候,需要增加额外的参数告诉lupdate你定义的这个标记红,lupdate才能识别到。
-
尽量不要动态修改语言,因为qt中安装、卸载translator的时候,不是线程安全的!
之前遇到过一个情况,一个子线程在不断的调用QProcess::waitFinished(0)
,在waitFinished方法的内部,如果超时,实际上会抛出一个错误,而这个错误会用QObject::tr()翻译!这种隐藏在Qt源代码里边的翻译行为,我们是无法预知的,所以动态切换语言,实在是有点风险,如果全部的翻译操作对开发人员来说都是可知并且可控的话,那么这个行为才是安全的! -
在Qt的程序中,不使用Qt框架下的这套i18n工具,动态切换语言,或许才是安全的。