通过2.3 Qt中文乱码,乱码的问题已经可以解决了,下面我来谈一谈国际化与本地化的问题,其实这也可以解决上文提到的乱码问题。
国际化是指在代码设计上加入能方便的移植到其他国家和地区的特性。而本地化是指将具有国际化支持的代码翻译成本国或地区的语言,使本地用户更容易使用。
I18n是Internationalization的简写,l10n是Localization的简写。
1) 在Qt中创建可以国际化的代码
最常见的是将要翻译的字符串加上tr语句,tr语句的标准语法是
Context::tr(sourceText,comment),比如
QString str2=QTextEdit::tr(“Letter”,”paper size”);
Context(上下文)和comment(注释)是可以省略的,它们的意思分别是:
Context:用于指明该翻译文字所在的上下文,一般为类名。因
为同样的一个字串在不同的环境中翻译出来是不一样的,比如
都是死,皇帝是崩,普通老百姓就是死。
comment: 用于指明要翻译文字的一个注释。因为作翻译的可
能并不是写代码的人。比如spring既有弹簧的意思,又有春天
的意思。
在写代码的时候,我们可能希望把所有的字符串都放在一个地方,而方便于我们自己集中作改动。真正用到的时候,用一个字符常量指针去访问。那么我们可能想到这样写代码
//wrong,这种实现Qt不认识,无法作翻译
const char *appName=“OpenDrawer 2D”;
QString translated=tr(appName);
//ok, 需要使用QT_TR_NOOP字串来提醒Qt系统该翻译的字串
const char *appName=QT_TR_NOOP(“OpenDrawer 2D”);
QString translated=tr(appName);
QT_TR_NOOP的语法是QT_TR_NOOP(sourceText),它还有两个变体,语法如下
QT_TRANSLATE_NOOP ( context, sourceText )
QT_TRANSLATE_NOOP3 ( context, sourceText, comment )
对应介绍的context和comment,其意思应该不难理解
还有一种情况是在一个字串中有一部分来源于变量。那我们看看两种正误的写法
//wrong 这种写法无法被正确识别
statusBar()->showMessage(tr(“Host ” + hostName+“ found”);
//ok 利用了QString的arg()函数。在翻译时,需保留%1
statusBar()->showMessage(tr(“Host %1 found”).arg(hostName)
在书写了含可翻译语句的程序后,我们来看看如何生成翻译文件
2)生成翻译文件
首先要修改.pro工程文件,比如在app.pro里加入一句
TRANSLATIONS+=app_zh.ts app_tw.ts #后面你可以加你想要翻译的各种版本
然后在shell里执行如下语句
$ lupdate app.pro
#会根据.pro里指示的内容,生成app_zh.ts和app_tw.ts lupdate是负责找出qt源
代码中需要翻译的字符串的。会搜
tr/QT_TR_NOOP/QT_TRANSLATE_NOOP/QT_TRANSLATE_NOOP3等语句,除了
命令行外,我们也可以执行工具->外部->Qt语言家->更新翻译,
$ linguist app_zh.ts
翻译其中一个文件,linguist是一个图形化的工具,打开之后
会看到相应需要翻译的文件,翻译之后点击保存退出即可,真正加入本地语言是在这
一步
$ lrelease *.ts
将.ts文本文件转换成.qm二进制文件,会生成app_zh.qm和
app_tw.qm,方便应用加载,除了命令行之外我们也可以执行:
工具->外部->Qt语言家->部署翻译,将生成语言文件qm
.ts 是Text String的缩写;.qm是Qt Message的缩写
所以翻译文件生成的流程就是
.cpp —> .ts —>.qm
需要提醒一下的,lupdate生成的.ts文件不会覆盖掉已经翻译过的.ts文件,只会更新其中的内容。所以其名字为languange update有了翻译文件,我们看看系统是怎么加载翻译文件的。
3)加载翻译文件
一个例子,很简单的说明问题
QTranslator qt_translator;
QTranslator app_translator;
//更具用户设置,是否添加本地化
if( usersettings.language == SimpleChinese ) {
// Qt’s own translations
qt_translator.load("qt_zh");
qApp->installTranslator( &qt_translator );
// application translation
app_translator.load("myprogram_zh");
qApp->installTranslator( &app_translator );
}
这里,我们看到先创建了两个翻译加载器,其中一个是加载应用程序的翻译文件,也就是我们在第二个步骤中生成的文件。另外一个是Qt系统的翻译文件,比如Qt的版权信息,designer的一些菜单等,名字叫qt_后带一个语言版本。
有时候我们在系统启动的时候,就需要判断本地的语言,然后加载不同的翻译文件,那么代码就是如下结构
QString locale = QLocale::system().name();
QTranslator translator;
translator.load(QString("trollprint_") + locale);
app.installTranslator(&translator);
本地设置的语言,和我们的.qm前面部分并不完全一样,有一个.qm查询的过程,假如本地字语言名字是fr_CA.ISO8859-15,加载程序会按照
trollprint_fr_CA.ISO8859-15.qm,trollprint_fr_CA.qm,trollprint_fr.qm顺序来加载,如果以上都没有,将使用默认的语言
4)一个极其简单的例子
//main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTranslator translator;
translator.load("hellotr_zh");
app.installTranslator(&translator);
QPushButton hello(QPushButton::tr("Hello world!"));
hello.resize(100, 30);
hello.show();
return app.exec();
}