QT 的国际化支持操作要点.

----------------------------------------
author: hjjdebug
date: Fri Aug 14 13:11:15 CST 2020
----------------------------------------
本篇文章帮助你理解如下几个问题:
1. 翻译过程是如何进行的?
2. 翻译的上下文是指的什么?
3. 如何使用QT_TR_NOOP, QT_TRANSLATE_NOOP
4. QObject::tr() 是如何工作的.
5. lupdate 工具是如何工作的.

6. 如何提取宏定义中的字符串? 也就是说宏定义中字符串如何支持国际化?
7. 类中字符串如何支持国际化.
8. 全局变量引用字符串如何支持国际化.

 

如果你以上问题都明白,那就不用把玩了,或者简单阅读一下代码也能温故而知新.

$cat main.cpp

#include 
#include "macro.h"
#include "classTest.h"

const char *pStr =  QT_TRANSLATE_NOOP("mygroup","中文1");
//const char *pTest =	QT_TR_NOOP("中文3"); // lupdate 提示: tr() cannot be called without context
//如下定义虽然可编译,可提取,但执行时会显示乱码,不能完成翻译工作. 
//因为此时tr()还没有初始化(QTextCodec::setCodecForTr(g_utf8)), 会按默认的iso8859工作.
//QString gStr = QObject::tr("中文2");  
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QTextCodec *g_utf8 = QTextCodec::codecForName("utf8");
	QTextCodec::setCodecForTr(g_utf8); //设置tr 的输入编码为utf8


	QTranslator *tranlator=new QTranslator;           	//创建翻译器
	tranlator->load("src_fr.qm");    		//加载语言包
	a.installTranslator(tranlator); 	//安装翻译器
	QPushButton *p = new QPushButton(QObject::tr("中文3"));
	p->show();
//	qDebug() << "gStr:"<

其它辅助代码:

hjj@hjj-Inspiron:~/tr_research$ cat macro.h 
#ifndef _MACRO_H
#define _MACRO_H
#define OPENFILE_FAIL(fn) \
		MyMessageBox::warning(NULL,QObject::tr("信息"),QObject::tr("文件<%1>读打开失败.").arg(fn),QObject::tr("确定"));
#endif
hjj@hjj-Inspiron:~/tr_research$ cat classTest.h
#ifndef _CLASS_TEST_H
#define _CLASS_TEST_H
#include 
class classTest : public QObject
{
Q_OBJECT
public:
	static const char *pTest2;
	classTest();
	virtual ~classTest(){};
};

#endif
hjj@hjj-Inspiron:~/tr_research$ cat classTest.cpp 
#include 
#include "classTest.h"
const char* classTest::pTest2 = NULL;
classTest::classTest()
{
 	pTest2 = QT_TR_NOOP("中文5"); // QT_TR_NOOP 要求必须在一个类里面. 这个"类名"就是上下文, 要调用tr()所以继承QOjejct类
	qDebug()<

通过对该代码的把玩,我有如下体会:


1. QT_TR_NOOP, QT_TRANSLATE_NOOP 是什么?
答,是两个宏
#define QT_TR_NOOP(x) (x)
#define QT_TRANSLATE_NOOP(scope, x) (x)

它们只是起一个标记作用,供lupdate 来识别提取出字符串.

2. 类中定义的tr 是调用的哪个函数?
答: QObject::tr() 最后也是调用的QApplication::translate(), 其上下文是QObject.

3. 自定义翻译上下文. 就像程序实例中使用的那样.
    "mygroup" 就是我自定义的上下文
    const char *pStr =  QT_TRANSLATE_NOOP("mygroup","中文2");

4. 注意事项:
    a. ts文件中文字符是乱码, 你应该在工程文件中指明CODECFORTR是utf8格式
    即在.pro中加下面一句.
    CODECFORTR=utf8
    这样,lupdate 就不会把源当成iso8859来抓取字符串了.

     b. 当你想翻译成法文而不是翻译成默认的英文时, 你只要把ts文件的语言选项改一下就可以了.
        
        改成
        


5. 翻译过程是如何进行的?
    a. lupdate
        project 要有一句类似 TRANSLATIONS += src_fr.ts , 这样生成的翻译源文件会是src_fr.ts
        它会提取工程中的被tr包围的字符串(主要的),以及被QT_TR_NOOP, QT_TRANSLATE_NOOP
        包围的字符串, 这些字符串都是有上下文的, tr,QT_TR_NOOP 的上下文就是类名, QT_TRANSLATE_NOOP的上下文是自定义的.

         如果在宏中定义了字符串(最好避免这样操作). 实在不行,应该用QT_TRANSLATE_NOOP 来包围,
        用QObject::tr()也可以,但你应该明白你在做什么.
        因为lupdate 并不是编译器, 它不会把宏在调用处展开再提取, 而是直接提取.
    b. linguist src_fr.ts
        翻译的源文件<例如src_fr.ts> 是一个xml 文件, 指明了源文件位置.
        需要手工翻译成对应的字符串.

    c. lrelease
        将定义的源文件<例如src_fr.ts> 翻译成对应的二进制文件
        我看了一下qm 二进制文件,
        翻译的规则是去掉了位置信息,保留了上下文及源字符串,目的字符串信息.
         由此可知,当满足上下文及源字符串时,即被翻译成目的字符串. 否则不翻译!
        .qm 就像是一个数据库, 它的输入条件是上下文和源字符串,输出是目的字符串.


代码工程可以到csdn上下载, 链接地址:

https://download.csdn.net/download/hejinjing_tom_com/12712534

你可能感兴趣的:(qt,编程)