Qt翻译

如何进行翻译

  • 第一步:写规范的代码
    • 用 QString 包裹不需要翻译的文本
    • 用 tr() 包裹需要翻译的文本
    • 定义上下文
    • 如何翻译非 Qt 类
      • 第一种:利用 QCoreApplication::tr() 函数
      • 第二种:利用 QCoreApplication::translate() 函数
      • 第三种:利用 QCoreApplication 类的 Q_DECLARE_TR_FUNCTIONS 宏
      • 第四种:使用 QT_TR_NOOP() 宏和 QT_TRANSLATE_NOOP() 宏
    • 给翻译添加个注释
      • 第一种:添加注释的格式
      • 第二种:tr() 函数的双参数
    • 如何翻译复数?
  • 第二步:转成 ts 文件
    • 在 pro 文件中指定 ts 文件
    • 用 lupdate 生成 ts 文件
  • 第三步:翻译并生成 qm 文件
  • 最后一步:源代码中加载、安装翻译文件

 

我们到底在翻译什么?

大多数情况我们可能只进行文字上的翻译,比如英语翻译成汉语、俄语、日语等等这些肉眼就可以看得到的东西。但是你有想过阿拉伯文可是从右往左书写的;各国的货币符号可是不一样的(人民币是¥,美元是$);各国的大数表示方式可是不一样的,比如我们写100万就是“100 0000”,美国人习惯于“1,000,000”,中间的逗号咋办呀?要是静态的数字还好办,那万一要显示的数字是个变量就没辙了。所以“区域”的设置也属于翻译的一部分。

除了肉眼能看到的以外,还有就是眼睛看不到的字符编码转换问题。这部分不是给用户看的,而是给程序员看的。假设我们得到一段以“KIO8-R”为编码格式的俄文字节流,我要怎么把这段数据转换成比如 GBK18030 编码的中文啊?所以“编码的转换”也属于翻译的一部分。Qt 也同样提供了针对这个问题的类

综上所述,一个完整的翻译包括三部分:(1)文字的翻译;(2)区域格式的翻译;(3)语言编码的翻译。然鹅,绝大多数的新手可能只关注第一条而忽略了后两条。

 

QLocale 类

Qt翻译_第1张图片

 

和翻译相关的 Qt 类

Qt 的翻译功能很简单,所用到的工具类就那么几个,最常用的就是 QTranslator、QTextCodec、QLocale 这三个类。所有关于翻译的类及其说明如下:

  • QTranslator:存储翻译文件,执行翻译操作。
  • QLocale:存储本机的区域设置,还可以不同区域格式的转换。
  • QTextCodec:一个编/解码的小工具。
  • QTextDecoder:可以根据字节流的状态正确拼接字节流,从而进行解码操作,常用于网络。
  • QTextEncoder:可以根据字节流的状态正确拼接字节流,从而进行编码操作,常用于网络。
  • QCollator:基于不同区域来对比字符串的类。
  • QCollatorSortKey:用于加速一个字符串的排序。

翻译流程框架图

大致的流程是这样的:首先源代码产生 ts 文件,然后送给 Qt Linguist(Qt语言家)这个 Qt 自带的小工具进行处理产生 qm 翻译文件,最后源代码里加载这个 qm 翻译文件。

Qt翻译_第2张图片

感觉有一点迭代的意思,其实不影响翻译。因为最后一步进行加载 qm 翻译文件所写的代码已经没有和界面相关的字符串了。 

第一步:写规范的代码

(1)用 QString 包裹不需要翻译的文本。

因为 QString 内部采用 Unicode 编码格式,而 Unicode 几乎能表达世界上任何一个语言,并且很多 Qt 库函数的参数也是 QString 类型,所以处理起来会比较方便。

当然用 char* 也可以,但是便宜的时候 Qt 内部还是会转换成 QString,这就会带来一定的系统开销。关于 char* -> QString 的转换问题,Qt 默认会把 char* 当成 UTF-8 编码格式。因此如果 char* 中的内容是其他编码格式的,需要用 QTextCodec 类来转换。

(2)用 tr() 包裹需要翻译的文本

回顾本文最开头的概述,那么凡是你要进行翻译的文本都要用 tr() 函数来包裹。这个 tr() 是 QObject 类的一个函数,用它包裹的文本会被 Qt Linguist(Qt语言家)捕捉到从而进行翻译工作。或者你也可以这样理解,用 tr() 包裹的文本会添加到 ts 文件中。关于 ts 文件在下文会说到。例如我们的示例工程就是这样写的:

Qt翻译_第3张图片

 QML 的翻译是用 qsTr() 来代替 tr() 函数。

(3)定义上下文

什么叫上下文?请看下图,上下文一般指这个要翻译的文本属于哪个类。QObject 类及其子类只要使用了 Q_OBJECT 宏,默认是当前类作为上下文。

当然你也可以显示的调用某个类的 tr() 函数来改变文本所属的上下文。比如还是下图,如果直接写 tr("Hello"),那么打开 Qt Linguist 的话这一条会属于 MainWindow 这个上下文。但我这里写 QScroller::tr("Hello") 的话,图中显示就是属于 QScroller 这个类作为上下文。

Qt翻译_第4张图片

(4)如何翻译非 Qt 

QObject 类有现成的 tr() 函数可以方便使用,但是如果是非 QObject 类没有 tr() 函数怎么办呢?方法有四种:

第一种:利用 QCoreApplication::tr() 函数

用 QCoreApplication::tr() 这个函数来包裹要翻译的文本,只有这样才能被 Qt Linguist 捕捉到。

第二种:利用 QCoreApplication::translate() 函数

第三种:利用 QCoreApplication 类的 Q_DECLARE_TR_FUNCTIONS 宏

使用这个宏当然要 #include 啦。使用之后就可以用 tr() 函数了。

内部的原理依靠元对象系统,使用该宏后会自动在该类添加如下两个静态函数。这样就可以用啦。

static inline QString tr(const char *sourceText, const char *comment = 0);
static inline QString trUtf8(const char *sourceText, const char *comment = 0);

Qt翻译_第5张图片Qt翻译_第6张图片

 第四种:使用 QT_TR_NOOP() 宏和 QT_TRANSLATE_NOOP() 宏

(5)给翻译添加个注释

添加注释可以更好的帮助翻译人员进行理解这个文本的含义,尤其是不同语境下有不同含义时。添加注释有两种方法,一种是采用固定的注释格式,另一种就是利用 tr() 的第二个参数。

(6)如何翻译复数?

有时候会遇到这样一个场景,英语中有这样两句话: 

I have 1 book.
I have 2 books.

 

int n = books.count();
showMessage(tr("I have %n book(s).", "", n));

 上述代码的 tr() 函数,第一个参数是实际展示的文本,变量用 %n表示,就好比 %1、%2等之类的。book 的复数形式用括号括起来,翻译之后就会根据数来显示不同的形式;第二个参数是注释用的,这里面写不写看你自己,反正是给翻译人员看的;第三个就是这个变量 n。

翻译后的中文:我有%n本书

第二步:转成 ts 文件,注意转换之前要保存

三步:翻译并生成 qm 文件

用 Qt Linguist 打开 ts 文件并翻译后记得时刻保存,至此 ts 文件制作完毕,接下来就是 qm 文件的生成。

qm 文件生成可以直接在 Qt Linguist 里点击“文件”-“发布”,或者在 Qt Creator 中点击“工具”-“外部”-“Qt语言家”-“发布翻译(lrelease)”都可以。

至此,qm 文件生成完毕。

最后一步:源代码中加载、安装翻译文件

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTranslator translator;
    translator.load("app_zh");
    app.installTranslator(&translator);
    return app.exec();
}

多说两句,在上文第二步我们说过,翻译文件的命名如果遵循 Qt 的规范写的话会自动被识别这是哪个语言的翻译文件,比如“app_zh.ts”中的“zh”。所以高手们用 QTranslator:: load() 函数一般是这样的:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QString locale = QLocale::system().name();
    QTranslator translator;
    translator.load(QString("app_") + locale);
    app.installTranslator(&translator);
    return app.exec();
}

你看,用 QLocale 直接就能获得计算机的区域设置“zh”了。如果这个程序在德语的操作系统环境下就会加载“app_de.qm”文件。

你可能感兴趣的:(Qt)