QT tr与Qstring的差别

在论坛中漂,经常遇到有人遇到tr相关的问题。用tr的有两类人:

  • (1)因为发现中文老出问题,然后搜索,发现很多人用tr,于是他也开始用tr
  • (2)另一类人,确实是出于国际化的需要,将需要在界面上显示的文件都用tr包起来,这有分两种:
    • (2a) 用tr包住英文(最最推荐的用法,源码英文,然后提供英文到其他语言的翻译包)
    • (2b) 用tr包住中文(源码用中文,然后提供中文到其他语言的翻译包)

注意哦,如果你正在用tr包裹中文字符,却不属于(2b),那么,这是个信号:

  • 你在误用tr
  • 你需要的是QString,而不是tr

如果你确实属于(2b),请做好心理准备,你可能还会遇到很多困难,请考虑Qt国际化(源码含中文时)的点滴分析

tr 是做什么的?下面二者的区别是什么?

QString text1 = QObject::tr("hello"); QString text2 = QString("hello");

tr是用来实现国际化,如果你为这个程序提供了中文翻译包(其中hello被翻译成中文"你好"),那么text1的内容将是中文"你好";如果你为程序提供且使用日文翻译包,那么text1的内容将是日文。

tr是经过多级函数调用才实现了翻译操作,是有代价的,所以不该用的时候最好不要用。

关注的对象

本文关注的是tr或translate中包含中文字符串的情况:

  • QObject::tr()

  • QCoreApplication::translate()

  • QTextCodec::setCodecForTr

这个问题本多少可说的。因为涉及到的编码问题和QString 与中文问题中是完全一样的,只不过一个是用的setCodecForCStrings一个用的是setCodecForTr。

简单回顾QString的中文问题

  • QString 采用的unicode,在中文支持上不存在任何问题
  • "我是中文" 这是传统的 const char * 的窄字符串

  • 当将窄字符串赋值到QString时,我们需要告诉它我们的窄串采用的何种编码(gbk?、utf-8?)
  • 究竟何种编码主要取决于我们的源代码文件的编码(windows上一般是gbk,其他平台一般utf-8)

例子:

QString s1 = "我是中文"; QString s2("我是中文"); QString s3; s3 = "我是中文"
  • s1、s2 用的是QString的构造函数QString ( const char * str )

  • s3 用的是QString的赋值操作符 QString & operator= ( const char * str)

如果不指定编码,s1,s2,s3将全部都是(国内大多数人所称的)乱码。因为QString将这些const char *按照latin1来解释的,而不是用户期待的gbk或utf8。

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"))

这两条语句中的一条可以解决问题,至于如何选择,此处不再重复。

QObject::tr

说实话,在tr中使用中文不是个好主意。不过既然总有人用(无论是(1)还是(2b)),而且总有人遇到问题,所以还是简单整理一下吧。

相比QCoreApplication::translate,大家用tr应该用的很多了,尽管不少人不清楚tr究竟是做什么的^_^

 

 

tr("我是中文");

这调用的是下面这个函数(至少我们可这么认为是)。

QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )

与QString("我是中文")完全一样,你必须告诉tr这个窄字符串是何种编码?你不告诉它,它就用latin1。于是所谓的乱码问题就出来了。

如何告诉tr你写的这几个汉字在磁盘中保存的是何种编码呢?这正是

QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312")); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

所做的。这两个选择的原则,由于和前文完全一样,此处也不再重复。

如果你的编码采用的utf8,可以直接使用trUtf8而不必设置setCodecForTr。

如果你只关心乱码问题,到此为止就可以了(下面不再关注编码)。如果想对tr进一步了解,不妨。。继续。。

 

QCoreApplication::translate

我们知道tr是用于实现程序的国际化(或者说多语言翻译),看Qt相关资料的话,我们知道实现该功能的还有下面这个函数:

QString QCoreApplication::translate ( const char * context, const char * sourceText, const char * disambiguation, Encoding encoding, int n )

其实,这个才是真正进行翻译操作的函数,前面我们提到的tr最终是通过调用该函数来实现翻译功能的(稍后我们会看tr是如何调用translate的)。

对tr和这个函数,manual中都有比较详尽的解释。我们这儿简单看一下它的这几个参数:

  • context 上下文,一般就是需要翻译的字符串所在的类的名字
  • sourceText 需要翻译的字符串。(我们关注的编码其实就是它的编码)
  • disambiguation 消除歧义用的。(比如我们的类内出现两处"close",一处含义是关闭,另一处含义是亲密的。显然需要让翻译人员知道这点区别)
  • encoding 指定编码。它有两个值
    • CodecForTr 使用setCodecForTr()设置的编码来解释 sourceText

    • UnicodeUTF8 使用utf8编码来解释 sourceText
    • 其实这两个分别对应tr和trUtf8
  • n 处理单复数(对中文来说,不存在这个问题)

tr与translate

这两个函数的说明,一个在QObject的manual,另一个在QCoreApplication的manual中。

介绍一下tr与translate的关系。前面提到了,tr调用的是translate。如果仅仅这样一说,没有证据,还真难以让大家相信。好吧,继续

tr 在何处定义

你可能说:这不废话吗,manual中写得明白的,它是QObject的静态成员函数。而且还有源码为证:

//来自 src/corelib/kernel/qobject.h #ifdef qdoc static QString tr(const char *sourceText,const char *comment = 0int n = -1); static QString trUtf8(const char *sourceTextconstchar *comment = 0int n = -1); #endif

嘿嘿,差点就被骗了,发现没:它们被预处理语句包住了。

这说明了什么呢?说明了这段代码仅仅是用来生成Qt那漂亮的文档的(qdoc3从代码中抽取信息,生成一系列的html格式的manual)。

啊,也就是说,这是假的。那么真正的定义呢??在一个大家都很熟悉的地方,猜猜看?

这就是

Q_OBJECT

该宏的定义在src/corelib/kernel/qobjectdefs.h中

#define Q_OBJECT \  public: \  Q_OBJECT_CHECK \  static const QMetaObject staticMetaObject; \  Q_OBJECT_GETSTATICMETAOBJECT \  virtual const QMetaObject *metaObject() const; \  virtual void *qt_metacast(const char *); \  QT_TR_FUNCTIONS \  virtual int qt_metacall(QMetaObject::Call, int, void **); \  private:

其中的宏QT_TR_FUNCTIONS

# define QT_TR_FUNCTIONS \  static inline QString tr(const char *s, const char *c = 0) \  { return staticMetaObject.tr(s, c); } \  static inline QString trUtf8(const char *s, const char *c = 0) \  { return staticMetaObject.trUtf8(s, c); } \  static inline QString tr(const char *s, const char *c, int n) \  { return staticMetaObject.tr(s, c, n); } \  static inline QString trUtf8(const char *s, const char *c, int n) \  { return staticMetaObject.trUtf8(s, c, n); }

现在看到:tr调用的是 staticMetaObject对象的tr函数,staticMetaObject 的定义在moc生成的 xxx.moc 或 moc_xxx.cpp 文件内(你随时可以验证的)。

staticMetaObject 是一个 QMetaObject 类的实例,我们继续看一下该类的源码:

/*!  \internal */  QString QMetaObject::tr(const char *sconst char *cconst  {  returnQCoreApplication::translate(d.stringdatascQCoreApplication::CodecForTr);   /*! \internal */ QString QMetaObject::trUtf8(const char *sconst char *cconst { returnQCoreApplication::translate(d.stringdatascQCoreApplication::UnicodeUTF8);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

printf的扩展

#define printf(format , ...) printf("FILE[%s] LINE[%d]" format , __FILE__ , __LINE__ , ##__VA_ARGS__)这个宏应用好几个技巧:1、使用printf宏,和原来的printf相同。这样我们不需要修改源码,直接替换原来的printf的函数。2、…

[react] contextType是什么?它有什么用?

[react] contextType是什么?它有什么用? 定义当前组件要使用哪一个context const MyContext React.createContext(defaultValue);class MyClass extends React.Component {componentDidMount() {let value this.context;/* perform a side-effect at…

shell 基本知识

shell--脚本基础知识 ****shell 脚本基础知识**** 一、基本脚本编译 知识内容: # 构建脚本 # 将命令串联起来 # 存储变量 # 数学计算 # 重定向输出 # 检查代码shell不像高级语言需要编译后执行,而是直接处理每一条命令,可以将多条命令连接起来…

Lombok(1.14.8) - @Log

Log Logs,生成一个日志对象。 package com.huey.lombok;import lombok.extern.java.Log;Log public class LogExample {public static void main(String[] args) {log.info("This is an info message."); }} 除了,Log还有其他annotatio…

让LwIP拥有PING其他设备的能力

LwIP是个很不错的协议栈,但是由于其体积过于小巧,使其只能支持ICMP的ECHO类型。 因为在“icmp.c”中的“void icmp_input(struct pbuf *p, struct netif *inp)”函数里有个很长的switch case语句(大约80行的位置)。 而这个语句只…

[react] 在React怎么使用Context?

[react] 在React怎么使用Context? context : Context提供了一种方式,能够让数据在组件树中传递,而不必一级一级手动传递。 API : createContext(defaultValue?)。 使用方法: 首先要引入createContext import React, { Component…

H.264详解

From: http://netliuwei.blog.163.com/blog/static/93642191201111721931583/ H.264 H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组&…

使用UDP

基本UDP客户端 #!/usr/bin/env python # UDP Example - Chapter 2 import socket, sys, time host sys.argv[1] textport sys.argv[2] s socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: port int(textport) except ValueError: # That didnt work. Look it up in…

QT中的MessageBox设置自动关闭退出

一、概述 由于弹出的MessageBox需要手动操作,点击相关操作程序才会进一步执行,所以有时程序使用了MessageBox会阻塞相关功能代码执行。例如,在串口编程中,接收到数据或某项配置成功后弹出一个MessageBox,由于没有及时…

(剑指Offer)面试题54:表示数值的字符串

题目: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14"…

Loopback Address

ping 127.0.0.1 是你本地的回环地址! 实际上只要是127.0.0.1到127.255.255.255都是回环地址!都是可以PING检查的! 它能ping通,说明你的TCP/IP协议栈没问题!如果有问题,你就得检查TCP/IP协议栈,或…

[react] Consumer向上找不到Provider的时候怎么办?

[react] Consumer向上找不到Provider的时候怎么办? 当consumer向上层找不到provider时,此时就会取创建context时传给createContext的那个值,也就是当前context对象的默认值,在定义provider时的value中的值不是默认值,…

VSCode中配置prettier和ESLint

文章目录 了解ESLint和Prettier的作用prettier配置ESLint配置常见问答ESLint 和Prettier 有什么区别?为什么我应该同时使用ESLint 和Prettier?在使用ESLint 和Prettier 时,有可能出现它们之间的规则冲突吗?我已经在项目中使用了ES…

赵丽词汇速记5500幻星笔记 (0、1)

赵丽词汇速记<5500>幻星笔记00-1开场白自我介绍http://teacherzhaoli.nease.net/上课要求:需要准备一个笔记本able adj.enable v.ability n.如何记笔记&#xff1a;把笔记打成三格单词中文助记方法搜索引擎&#xff1a;赵丽词汇词汇重要性词汇当先1.阅读离不开单…

matlab 数据是否符合正态分布的判断方法

一、问题描述 给定序列X(x1,x2,x3,...,xn)&#xff0c;判断是否该数据序列X符合正态分布。 二、方法 常见已知分布的检验方法&#xff1a;kstest、jbtest、lillietest、chi2gof等&#xff0c;这里使用使用Lilliefors检验进行描述。 语法&#xff1a; 1&#xff1a;h lillie…

什么是CIF/4CIF/QCIF/D1?

From: http://www.c-ps.net/trade/content/2008/8/8009.html QCIF全称Quarter common intermediate format。QCIF是常用的标准化图像格式。在H.323协议簇中&#xff0c;规定了视频采集设备的标准采集分辨率。QCIF 176144像素。 CIF是常用的标准化图像格式&#xff08;Commo…

字符串string和内存流MemoryStream及比特数组byte[]互转

定义string变量为str,内存流变量为ms,比特数组为bt 1.字符串转比特数组 (1)byte[] btSystem.Text.Encoding.Default.GetBytes("字符串"); (2)byte[] btConvert.FromBase64String("字符串"); 2.字符串转流 (1)MemoryStream msnew MemoryStream(System.Text.…

Lwip使用经验

LWIP使用经验 一 LWIP内存管理 数据包管理 设置内存大小 宏编译开关 二 LWIP启动时序 三 LWIP运行逻辑 接收数据包 SequentialAPI函数调用 四 TCPIP核心知识点 滑动窗口 三次握手 断开连接 TCP状态转换 同时打开 同时关闭 五正确使用LWIP 六 LWIP常见问题 网卡驱动程序 内存…

Keil5 编译生成bin二进制文件的设置方法

勾选&#xff1a;After Build/Rebuild Run #1 代码&#xff1a;fromelf --bin .\output\node.axf --output .\output\NoiseApp.bin 解释&#xff1a; .\ 指当前工程文件.uvprojx所在的目录.\output\node.axf 表示给定axf所在的位置.\output\NoiseApp.bin 表示bin文件输出的…

数据库三大范式详解

引言数据库的设计范式是数据库设计所需要满足的规范&#xff0c;满足这些规范的数据库是简洁的、结构明晰的&#xff0c;同时&#xff0c;不会发生插入&#xff08;insert&#xff09;、删除&#xff08;delete&#xff09;和更新&#xff08;update&#xff09;操作异常。反之…