QT国际化
引入
在代码里面写中文就很low,运行时多语言切换是客户端程序都应该具备的。
qt国际化其实就是qt中字符串的字符集编码的设置。当然这个设置不是简单的选择一下什么语言就好,这个需要编程人员来处理的。
通常对于非拉丁字符(主要指latin1字符集)的字符串,就需要使用到unicode字符集,而通常使用UTF-8编码。如果只是本地使用一下,直接使用""包含文件就可以了。但是有时候设计到网络传输等情况,就要考虑这些了。
QT提供了QTextCodec类来进行文本字符集的转换操作。
本文的重点不在于此。深入学习可以看
QTextCodec && 字符编码
Qt 编码问题QTextCodec
本文的重点在于QT界面显示的中文化。
1、控制需要翻译的文本
在编写QT程序的时候,对于要翻译的文本,应当使用tr()包含起来。
我们先来看看tr函数的原型,注意,这是一个静态函数。
QString QObject::tr(const char * sourceText, const char * disambiguation = 0, int n = -1)
因为Qt中的类都继承自QObject类,所以这里直接使用了tr,如果不是在继承自QT的类中使用,应该用Object::tr(…)来调用。
这还不是很准确,在宏定义Q_OBJECT展开后,会创建一个QMetaObject对象,即static const QMetaObject staticMetaObject;这个可以看看源码
对于Q_OBJECT的解析可以看Qt信号与槽机制的基石-MOC详解
#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,而这里面定义了一个内联的tr函数。可以看出这里实际是使用了一个静态对象staticMetaObject的成员函数tr。
# 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); }
例如对于一个QLabel控件,将其显示的文本使用tr括起来。tr是经过多级函数调用才实现了翻译操作,是有代价的,所以不该用的时候最好不要用。
QLable *label = new QLable(tr("hello"),this);
这次还是以一个hello world为例。
先看hello.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();
public slots:void btn_click();
};#endif // WIDGET_H
再看hello.cpp
#include "widget.h"
#include <QPushButton>
#include <QMessageBox>Widget::Widget(QWidget *parent): QWidget(parent)
{//创建一个PushButtonQPushButton * btn = new QPushButton(tr("click me"),this);//连接信号和槽connect(btn,SIGNAL(clicked()),this,SLOT(btn_click()));
}Widget::~Widget()
{
}void Widget::btn_click()
{QMessageBox::information(NULL, tr("click button"),tr("hello world"), QMessageBox::Yes);
}
2、lupdate更新翻译
在上面,源文件中的相关字符串已经使用tr函数包装起来了。现在要做的就是更新这些要翻译的字符串到ts文件。
lupdate就是用于扫描pro文件中指定的代码或UI文件中被tr包装起来的文本的工具
lupdate的使用
lupdate的使用可以使用lupdate --help来查看。
粗略的说一下这个工具的用法:
使用方法:
lupdate [选项] [项目文件]…
lupdate [选项] [源文件 | 路径 | @ lst 文件]…-ts ts 文件 | @ lst 文件
(lst文件是一个文本文件,保存一些文件名称,一行一个)
| 常用选项 | 说明 |
|---|---|
| -ts … | 指定输出文件。 |
| -codecfortr | 指定为 tr() 调用假设的编解码器。只有与-ts 有效。 |
| -extensions [,]… | 扩展支持的文件后缀。扩展名列表必须用逗号分隔。默认值:‘java,jui,ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx,js,qs,qml’。 |
| -no-recursive | 指定不递归扫描的目录 |
| -recursive | 递归扫描指定目录 |
| -I or -I | 附加的包含文件目录 |
| -no-ui-lines | 对ui文件的扫描不保留行号 |
| -pro | .Pro 文件的名称。对于具有.pro 文件语法,但不同的文件后缀的文件非常有用。 |
| -source-language [_] | 指定新文件的源字符串的语言。默认值Posix 标准。 |
| -target-language [_] | 指定新文件翻译的语言。如果未指定,则猜测系统语言。 |
| @lst-file | 从 lst 文件读取附加文件的名称 (每行一个)。 |
生成ts文件
1. 在命令行中指定方式生成
这里只生成一个翻译文件zh_hans.ts,其实可以跟多个文件名来生成多个用于翻译的ts文件。这个方式会忽略掉pro文件中指定要生成的翻译文件。
o@o-pc:~/hello$ lupdate hello.pro -ts zh_hans.ts
Updating 'zh_hans.ts'...Found 3 source text(s) (3 new and 0 already existing)
2. 在pro文件中指定
这里我们先修改一个hello.pro文件。
这是原本的hello.pro文件:
QT += core gui
TARGET = hello
TEMPLATE = app
SOURCES += main.cpp\hello.cpp
HEADERS += hello.h
LIBS += -lxcb
现在我们添加一句
TRANSLATIONS = zh_hans.ts
添加之后使用lupdate来生成zh_hans.ts文件
o@o-pc:~/hello$ lupdate hello.pro
3. linguits翻译文本
生成了ts文件后就要进行翻译了。ts文件实际上是类似于xml文件的,我们可以直接打开它来翻译。
- 直接翻译
打开ts文件,我们只需要在和之间填写我们翻译后的文件即可。
例如我们将"click me"翻译为点击我。则修改为:
<message><location filename="widget.cpp" line="9"/><source>click me</source><translation type="unfinished">点击我</translation>
</message>
如果你认为翻译合格了,没有问题了,可以将translation type=“unfinished”>中的type="unfinished"删除。
- 使用linguits工具翻译
1、点击菜单栏 文件 --> 打开 弹出文件选择对话框后选择生成的ts文件
2、设置源语言和目标语言,然而并没什么用
1、选择要翻译的短语
2、填写翻译的文本
3、翻译完成后记得保存
4. lrelease发布翻译
所谓发布翻译,就是使用lrelease工具将ts文件转换输出不包含多余信息的qm文件(qm文件是二进制文件,非文本文件)。
我们先来看看翻译后的ts文件。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context><name>Widget</name><message><location filename="widget.cpp" line="9"/><source>click me</source><translation>点击我^_^</translation></message><message><location filename="widget.cpp" line="20"/><source>click button</source><translation>单击按钮</translation></message><message><location filename="widget.cpp" line="21"/><source>hello world</source><translation>你好 世界</translation></message>
</context>
</TS>
使用lrelease生成qm文件
o@o-pc:~/hello$ lrelease zh_hans.ts -qm zh_hans.qm
lrelease使用简要说明
使用方法:
lrelease [选项] 项目文件
lrelease [选项] ts 文件 [-qm qm 文件]
| 选项 | 说明 |
|---|---|
| -idbased | 使用 Id 而不是源字符串作为消息的键 |
| -compress | QM 文件压缩 |
| -nounfinished | 不使用未完成的翻译 |
| -removeidentical | 如果源文本与翻译后的文本相同,不使用这个 |
| -markuntranslated | 如果消息有没有真正的翻译,使用源文本和 |
5. 在程序中使用翻译文件
在QT程序中要使用翻译文件,需要使用到类QTranslation。现在来修改main.cpp.
#include "widget.h"
#include <QApplication>
#include <QTranslator>int main(int argc, char *argv[])
{QApplication a(argc, argv);QTranslator tsor; //创建翻译器tsor.load("zh_hans.qm"); //加载语言包a.installTranslator(&tsor); //安装翻译器Widget w;w.show();return a.exec();
}
参考
- QT国际化(lupdate/linguits/lrelease)
相关文章:
QT国际化
引入 在代码里面写中文就很low,运行时多语言切换是客户端程序都应该具备的。 qt国际化其实就是qt中字符串的字符集编码的设置。当然这个设置不是简单的选择一下什么语言就好,这个需要编程人员来处理的。 通常对于非拉丁字符(主要指latin1字符…...
微信小程序button按钮去除边框去除背景色
button边框 去除button边框 在button上添加plain“true”在css中添加button.avatar-wrapper {background: none}用于去除button背景色在css中添加button.avatar-wrapper[plain]{ border:0 }用于去除button边框...
Neo4j深度学习
Neo4j的简介 Neo4j是用Java实现的开源NoSQL图数据库。从2003年开始开发,2007年正式发布第一版,其源码托管于GitHtb。Neo4j作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理、软件分析、组织和…...
【数据结构C/C++】链式存储与顺序存储结构栈
文章目录 链式存储结构顺序存储结构 下面这篇文章是我大二时候写的比较详细的实现过程,再这篇文章我也会再一次比较简单的再次简述一下链式与顺序存储结构的实现方式。 链式存储结构与顺序存储结构详解 这里我就不使用C再一次实现这两个栈了,有兴趣的也可…...
【数据库系统概论】数据定义之基本表的定义/创建、修改和删除
前言 🚩定义/创建基本表语法示例 修改基本表语法示例 删除基本表语法示例 感谢 💖 前言 🚩 SQL支持数据库系统的三级模式结构,其模式、外模式和内模式中的基本对象有表、视图和索引,因此,SQL的数据定义功能…...
面试算法22:链表中环的入口节点(1)
题目 如果一个链表中包含环,那么应该如何找出环的入口节点?从链表的头节点开始顺着next指针方向进入环的第1个节点为环的入口节点。 例如,在如图4.3所示的链表中,环的入口节点是节点3。 分析 第1步:确认是否包含环…...
蓝桥杯---第二讲---二分与前缀和
文章目录 前言Ⅰ. 数的范围0x00 算法思路0x00 代码书写 Ⅱ. 数的三次方根0x00 算法思路0x01代码书写 Ⅲ. 前缀和0x00 算法思路0x01 代码书写 Ⅳ. 子矩阵的和0x00 算法思路0x01 代码书写 Ⅴ. 机器人跳跃问题0x00 算法思路0x01 代码书写 Ⅵ. 四平方和0x00 算法思路0x01 代码书写 …...
d3dx9_39.dll如何修复?最新修复d3dx9_39.dll方法分享
大家好!今天我要和大家分享的主题是“d3dx9_39.dll丢失的修复方法”。我们都知道,在使用电脑的过程中,经常会遇到各种问题,而其中最常见的就是文件丢失。d3dx9_39.dll就是其中一个常见的丢失文件。那么,如何修复这个丢…...
阿里云轻量应用服务器月流量限制说明(部分套餐不限流量)
阿里云轻量应用服务器部分套餐限制月流量,轻量应用服务器按照套餐售卖,有的套餐限制月流量,有的不限制流量。像阿里云轻量2核2G3M带宽轻量服务器一年108元和轻量2核4G4M带宽一年297.98元12个月,这两款是不限制月流量的。阿里云百科…...
项目设计:YOLOv5目标检测+机构光相机(intel d455和d435i)测距
1.介绍 1.1 Intel D455 Intel D455 是一款基于结构光(Structured Light)技术的深度相机。 与ToF相机不同,结构光相机使用另一种方法来获取物体的深度信息。它通过投射可视光谱中的红外结构光图案,然后从被拍摄物体表面反射回来…...
WPF中DataContext的绑定技巧
先看效果: 上面的绑定值都是我们自定义的属性,有了以上的提示,那么我们可以轻松绑定字段,再也不用担心错误了。附带源码。 目录 1.建立mvvm项目 2.cs后台使用DataContext绑定 3.xaml前台使用DataContext绑定 4.xaml前台使用Da…...
【Spring MVC研究】MVC原理:DispatcherServlet的初始化,初始化好等于MVC准备好
文章目录 1. EnableWebMVC 开启 MVC 功能2. 初始化自定义的 MVC 组件2.1. 初始化过程2.2. 如何分析复杂的 Spring 组件注册 3. 容器启动后会初始化 DispatcherServlet4. DispatcherServlet 初始化过程总结5. 资料参考 把DispatcherServlet 准备好意味着服务器已经可以处理请求了…...
Kafka的分布式架构与高可用性
导语 一开始我们就说过Kafka是一款开源的高吞吐、分布式的消息队列系统,那么今天我们就来说下它的分布式架构和高可用性以及双/多中心部署。 Kafka 体系架构简介 以下是 Kafka 的软件架构,整个 Kafka 体系结构由 Producer、Consumer、Broker、ZooKeepe…...
Spring Cloud学习笔记【分布式请求链路跟踪-Sleuth】
文章目录 Spring Cloud Sleuth概述概述主要功能:Sleuth中的术语和相关概念官网 zipkin配置下载运行zipkin下载zipkin运行 demo配置服务提供者 lf-userpom.xmlapplication.ymlUserController 服务调用者 lf-authpom.xmlapplication.ymlAuthController 测试 Spring Cl…...
Java开发中的操作日志详解(InsCode AI 创作助手)
Java开发中的操作日志详解 一、操作日志的作用 故障排除和调试: 操作日志可以记录应用程序的各种活动,包括错误、异常、警告和信息性消息。这有助于开发人员快速定位和解决问题。性能分析: 通过记录关键操作和性能指标,操作日志…...
FutureTask和CompletableFuture的模拟使用
模拟了查询耗时操作,并使用FutureTask和CompletableFuture分别获取计算结果,统计执行时长 package org.alllearn.futurtask;import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; imp…...
Redis作为缓存,mysql的数据如何与redis进行同步?
Redis作为缓存,mysql的数据如何与redis进行同步? 一定要设置前提,先介绍业务背景 延时双删 双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致 读操作:缓存命中,直接返回;缓存未…...
申请免费 SSL 证书为您的小程序加密通信
在今天的网络环境中,数据安全和隐私保护变得尤为重要。无论是网站还是应用程序,为其提供安全的通信渠道都是至关重要的。对于小程序开发者来说,使用 SSL(Secure Sockets Layer)证书可以有效地保障用户数据的安全&#…...
Go 并发编程
并发编程 1.1 并发与并⾏ 并⾏与并发是两个不同的概念,普通解释: 并发:交替做不同事情的能⼒并⾏:同时做不同事情的能⼒ 如果站在程序员的⻆度去解释是这样的: 并发:不同的代码块交替执⾏并⾏…...
鱼眼相机去畸变(图像拉直/展开/矫正)算法及实战总结
本文介绍两种方法 1、经纬度矫正法 2、棋盘格矫正法 一、经纬度矫正法 1、算法说明 经纬度矫正法, 可以把鱼眼图想象成半个地球, 然后将地球展开成地图,经纬度矫正法主要是利用几何原理, 对图像进行展开矫正。 经过P点的入射光线…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...
用鸿蒙HarmonyOS5实现国际象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的国际象棋小游戏的完整实现代码,使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├── …...
aurora与pcie的数据高速传输
设备:zynq7100; 开发环境:window; vivado版本:2021.1; 引言 之前在前面两章已经介绍了aurora读写DDR,xdma读写ddr实验。这次我们做一个大工程,pc通过pcie传输给fpga,fpga再通过aur…...
