Qt程序国际化指的是提取程序源码中的需要进行翻译的字符串,翻译成相应的语言,置于界面程序中,使得软件能够满足不同国家和地区的用户需求,软件的汉化即是程序国际化的一种表现形式。在程序中需要进行国际化翻译的字符串必须使用tr()。
在国内,界面程序中一般会使用汉字来方便用户使用,除了利用Qt程序国际化工具进行翻译汉化程序之外,另一种方式是直接在源码中使用汉字,如:action->setText(tr("开始")),并且在main函数中需要添加红色部分所示的代码:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec *codec = QTextCodec::codecForName("GB2312");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
MainWindow w;
w.show();
return a.exec();
}
其中存在的问题是,使用GB2312格式保存这篇代码,其他人使用UTF-8方式打开代码后,其中的汉字部分显示的是乱码。特别是在Linux环境下,默认的编码方式是UTF-8,无论使用Qt-creator或者gedit,打开后都会显示乱码。
Qt提供了强大的lupdate、Qt linguist、lrelease三种国际化翻译工具,方便用户进行Qt程序的国际化。因此,通用的做法是在代码中所有需要进行翻译的地方都用一段英文暂时代替,并用tr()函数做标记,随后使用Qt linguist对所有被tr()函数标记的字符串进行翻译,并发布翻译包,最后在程序中加载翻译包。图1为Qt程序进行国际化翻译工作的基本流程。以下分别介绍图中各个步骤的详细执行过程。
图1 Qt程序国际化流程
Qt4.7.3版本中的lupdate工具存在BUG,使用时会出现cirtual inclusion的问题,无法编译通过,Qt在4.8.3版本中修复此问题。所以需使用4.8.3及以上Qt版本的lupdate工具。
首先需要判断lupdate是否能正常使用,在Qt命令行终端中输入:lupdate -version,如图2所示,显示lupdate的版本号(图中为4.8.4版本)。如果终端提示“不是内部或外部命令”,表示系统无法查找到该工具,此时需要将lupdate所在的目录(Qt安装目录下的/bin文件夹,如C:\Qt\4.8.4\bin)添加到系统环境变量中。
图2 lupdate版本显示
lupdate使用方式为:
① Qt命令行终端,进入需要工程文件目录下(.pro文件所在目录),如图3所示,输入命令:lupdate xxx.pro -ts xxx.ts。也可以在.pro文件中添加TRANSLATIONS += xxx.ts,此时终端中lupdate输入命令为:lupdate xxx.pro,其中xxx.pro为Qt工程文件,xxx.ts为生成的ts文件。图3 lupdate工具使用
当用户修改工程源码中的tr,利用lupdate重新生成.ts文件,lupdate能够识别进行修改的tr对象,并且进行更新,而不更新用户未修改的对象。这样,在下一步使用Qt linguist翻译文字时,无需翻译重复的文字,大大减少了翻译的工作量。
Qt linguist是一种图形化工具,使用该工具可对.ts文本进行检查,翻译。
Qt linguist使用方式为:
①在系统开始菜单-Qt程序选项中打开该工具,打开上一步生成的.ts文件,如图4所示,为.ts文件的显示和编辑界面。图4 Qt linguist打开.ts文件的界面显示
②按照界面提示,翻译完成后可以直接保存(下一步利用lrelease发布为.qm文件),或者点击菜单-文件-发布,发布为.qm文件。
在第2)步中,如果直接利用Qt linguist工具将翻译完成的.ts文件发布为.qm文件,此步骤可以省略,直接进入第4)步。
lrelease工具使用方式:
① 打开Qt命令行终端,在终端输入:lrelease xxx.ts -qm xxx.qm,即可生成.qm文件,该文件为二进制文件,经过高度优化,占用空间较小。其中xxx.ts为上一步翻译完成的.ts文件,xxx.qm为生成的.qm文件。
如果需要Qt程序支持翻译之后的语言,还需要在在工程主函数main()中添加代码:
QTranslator qtTranslator;
qtTranslator.load("xxx.qm");
application.installTranslator(&qtTranslator);
因为.qm文件是动态添加的,因此可以将xxx.qm文件复制到.exe所在的目录下,运行程序,即发现完成翻译工作。
1. 对需要进行国际化翻译的字符串必须使用tr(“”)函数,否则无法对其进行翻译;
2. 在全局函数和全局变量中使用tr时,必须显式调用QObject函数,如Main函数中使用tr:w.setWindowTitle(QObject::tr("MyApp")),
全局变量使用tr:const QString g_strLockGroup =QObject::tr("LockConfig");
class CLockManager : public QObject
{
Q_OBJECT
public:
virtual ~CLockManager();
}
原因是tr()函数是QObject类的接口,如果类不是继承自QObject,就不能直接使用tr()函数,否则无法通过编译;
3. 如果在系统中需要使用动态string,则需要使用arg()方法。例如:
QMessageBox::warning(NULL, tr("Error"),tr("Can not open the file %1").arg(file.fileName()));
4. 如果要翻译外部字符串,允许tr()中出现变量,则需要使用QT_TR_NOOP,如
QStringFriendlyConversation::greeting(int type)
{
static const char *greeting_strings[] ={ QT_TR_NOOP("Hello"),
QT_TR_NOOP("Goodbye") };
return tr(greeting_strings[type]);
}
5. findChild()、setObjectName()接口中的字符串一般不需要进行翻译工作,因此不建议使用tr();
6. 在程序界面中添加控件,如使用QLabel、QPushButton、QAction时,需要在实例化该对象时使用tr();
7. setWindowTitle()、setText()中需要使用tr();