16-1_Qt 5.9 C++开发指南_多语言界面

文章目录

  • 1. 多语言界面设计概述
  • 2. tr()函数的使用
  • 3. 生成语言翻译文件
  • 4. 使用Qt Linguist 翻译 ts 文件
  • 5. 调用翻译文件改变界面语言
    • 5.1 生成qm文件
    • 5.2 项目启动时设置界面语言
    • 5.3 动态切换语言

1. 多语言界面设计概述

有些软件需要开发多语言界面版本,如中文版和英文版,并且在软件里可以方便地切换界面语言。Qt 为多语言界面提供了很好的支持,使用 Qt 的一些规则和工具,可以很方便地为应用程序开发提供多语言界面支持。
用 Qt 开发多语言界面应用程序,主要包括以下几个步骤。

(1)在程序设计阶段,程序代码中每一个用户可见的字符串都用 tr()函数封装,以便 Qt 提取界面字符串用于生成翻译资源文件。用 UI设计器可视化设计窗体时统一用一种语言,如汉语。

(2)在项目配置文件 (.pro 文件)中设置需要导出的翻译文件 (.ts 文件)名称,使用 lupdate工具扫描项目文件中需要翻译的字符串,并生成翻译文件。

(3)使用Qt的 Linguist 程序打开生成的翻译文件,将程序中的字符串翻译为需要的语言,如将所有中文字符串翻译为英文。

(4)使用lrelease 工具编译翻译好的翻译文件,生成更为紧凑的“.qm”文件。

(5)在应用程序中用QTranslator 调用不同的“qm”文件,实现不同的语言界面

2. tr()函数的使用

为了让 Qt 能自动提取程序中用户可见的字符串,对于每个字符串都需要使用tr()函数封装。tr()是 QObject 的一个静态函数,在使用了Q_OBJECT 宏定义的类或 Object 的子类中,都可以直接使用tr()函数,否则需要使用 QObject::tr()进行调用。或者在类定义中用 Q_DECLARE_TR_FUNCTIONS 宏把tr()函数添加到类中之后,再直接调用 tr()函数。

tr()函数的定义是:

[static] QString QObject::tr(const char *sourceText, const char *disambiguation = nullptr, int n = -1)

其中,sourceText 是源字符串,disambiguation 是为翻译者提供额外信息的字符串,用于对一些容易混淆的地方作说明,内容如下:

LabCellPos = new QLabel(tr("当前单元格:"),this);
QMessageBox::information(thistr("信息")tr("信息提示?),QMessageBox::Yes);
QString str1=tr("左右",“大约的意思");
QString str2=tr("左右""掌握、控制的意思");

使用tr()函数,需要注意以下一些事项。

尽量使用常量字符串,不要使用字符串变量。在tr()函数中应直接传递字符串常量,而不是用变量传递字符串,如下面的代码使用了字符串变量,使用 lupdate 工具提取项目中的字符串时,将不能提取“不能删除记录”这个字符串。

char *errorStr="不能删除记录";
QString str2=tr(errorStr);

使用字符串变量时需要用 Qt_TR_NOOP()宏进行标记。若要在tr()函数中使用字符串变量,需要在定义字符串的地方用 Qt_TR_NOOP()宏进行标记,这在使用字符串数组时比较有用,例如:

const char *cities [4] = {Qt_TR_NOOP("Beijing"),Qt_TR_NOOP("Qingdao"),Qt_TR_NOOP("Wuhan")};
for (int i=0;i<4;i++)comboBOx->addItem(tr(cities[i]));

tr()不能使用拼接的动态字符串。tr()不能使用拼接的动态字符串,例如,下面的用法是错误的:

LabCellPos->setText(tr("第"+ QString::number(current,row()) +"行");

正确的方式如下:

LabCellPos->setText(tr("第 %1 行").arg(current.row()));

翻译的字符串是"第 %1 行",然后再用 QString 的 arg()去替换占位符“%1”的内容。

Qt_NO_CAST_FROM_ASCII 的作用。在一个需要翻译为多语言的应用程序中,如果编写程序时忘了对某个字符串使用 tr()函数,lupdate 生成的翻译资源文件就会遗漏这个字符串。为了避免这种疏忽错误,可以在项目配置文件 (.pro 文件) 中添加如下的定义:

DEFINES += Qt_NO_CAST_FROM_ASCII

这样在编译时,会禁止从const char* 到 QString 的隐式转换,强制每个字符串都必须使用 tr()或QLatin1String()封装,避免出现遗漏未翻译的字符串。

3. 生成语言翻译文件

要生成多语言界面相关的翻译文件,除了之前所说的在对每个字符串都使用 tr()函数封装之外,还需要在项目配置文件 (.pro 文件) 中使用 TRANSLATIONS 定义语言翻译文件(.ts 文件),并使用 lupdate 工具生成语言翻译文件。

作为实例,将第 6 章的 samp6_2 作为多语言界面设计实例,复制项目 samp6_2 的全部文件,并将项目名称更改为 samp16_1。在项目的配置文件中增加如下的设置语句:

TRANSLATIONS  =samp16_1_cn.ts\samp16_1_en.ts

这里设置生成两个语言翻译文件“samp16_1_cn.ts”和“samp16_1_en.ts”,分别是中文和英文翻译文件。文件名称可以任意设计,只要有所区分即可。

原始的程序设计采用中文。为了便于进行语言切换,在主窗口上设置了两个工具栏按钮,分别用于切换中文和英文界面 (如图 16-1 所示,界面语言切换的代码实现会在下一小节介绍

在这里插入图片描述

为了让 lupdate 工具能提取项目代码内的字符串,这里对项目程序里的字符串全部采用 tr()函数封装,对于不符合 tr()函数使用规则的地方进行修改。例如,之前在状态栏上显示当前单元格的行号和列号的程序是:

LabCellPos->setText(QString::asprintf("当前单元格:%d 行,%d列",current.row(),current.column()));

现在就修改为如下形式:

LabCellPos->setText(QString::asprintf(tr("当前单元格:%d 行,%d列"),current.row(),current.column()));

在项目设计期间,任何时候都可以使用 lupdate 工具生成或更新翻译文件,方法是单击 QCreator 主菜单的“Tools”-“External”-“Qt 语言家”-“Update Translations(lupdate)”菜单项,若项目的源程序目录下没有 samp16_1_cn.ts 和 samp16_1_en.ts 这两个文件,就会自动生成,如果文件已经存在,则会更新这两个文件的内容

4. 使用Qt Linguist 翻译 ts 文件

生成的 samp16_1_cn.ts 和 samp16_1_en.ts 文件内包含了项目源程序和 UI界面里的所有字符串,使用 QtLinguist 可以将这些字符串翻译为需要的语言版本。在 Qt 安装后的程序组里可以找到Qt Linguist 软件。

samp16_1_cn.ts是中文界面的翻译文件,由于源程序的界面就是用中文设计的,所以无需再翻译。samp16_1_en.ts是英文翻译文件,需要将提取的所有中文字符串翻译为英文。

在 Linguist 软件中打开文件 sampl6_1_en.ts,当第一次打开一个ts 文件时,Linguist 会出现如图 16-2 所示的语言设置对话框,用于设置目标语言和所在国家和地区。这个对话框也可以通过Linguist 主菜单的“编辑”->“翻译文件设置”菜单项调出。samp16_1_en.ts 是用英文界面的翻译文件,所以选择语言“English”,国家/地区可选择“UnitedStates"。

在这里插入图片描述

打开samp16_1_en.ts 文件后的Linguist软件界面如下图所示。左侧“上下文”列表里列出了项目中的所有窗口或类,这个项目有 4 个窗口。“字符串”列表里列出了从项目的 UI窗口和代码文件中提取的字符串,右侧“短语和表单”会显示窗口界面的预览或字符串在源程序中出现的代码段。

在“字符串”列表中选择一个源文后,在下方会出现译文编辑框,在此填写字符串对应的英文译文。Linguist 可以同时打开项目的多个 ts 文件,在选中一个源文后,在下方会出现对应的多个语言的译文编辑框,可以同时翻译为多个语言版本。

在这里插入图片描述

5. 调用翻译文件改变界面语言

5.1 生成qm文件

使用 Linguist 软件编辑翻译文件,将所有字符串都翻译后,在 Qt Creator 中单击主菜单项“Tools”-“External”-“Qt 语言家”-“Release Translations(lrelease)”,会在项目源程序目录下生成与ts 文件对应的 qm 文件,这是更为紧凑的翻译文件。本实例生成的是 samp16_1_cn.qm和samp16_1_en.qm。

5.2 项目启动时设置界面语言

使用QTranslator 类设置界面的不同语言版本,需在应用程序启动时设置界面语言翻译文件,即在main()函数中进行处理。项目 samp16_1的main.cpp 的代码如下:

#include "mainwindow.h"
#include    <QApplication>
#include    <QTranslator>#include    <QSettings>QTranslator *trans=NULL;QString readSetting();int main(int argc, char *argv[])
{QApplication app(argc, argv);trans=new QTranslator;QString curLang=readSetting(); //读取语言设置if (curLang=="EN")trans->load("samp16_1_en.qm");elsetrans->load("samp16_1_cn.qm");app.installTranslator(trans);MainWindow w;w.show();return app.exec();
}QString readSetting()
{//从注册表读取上次设置的语言QString organization="WWB-Qt";//用于注册表,QString appName="samp16_1"; //HKEY_CURRENT_USER/WWB-Qt/amp13_1QSettings  settings(organization,appName);//创建QString Language=settings.value("Language","EN").toString();//读取 saved键的值return  Language;
}

这里定义了一个全局变量 trans,在 main.cpp 里定义了一个函数readSetting(),用于从注册表里读取上次设置的界面语言版本。注册表里数据的读取和写入使用到 QSetings 类,在6.5 节有详细介绍。

在main()函数中,创建QTranslator 类的对象trans 后,调用readSetting()函数从注册表里读取上次的语言版本,若为“EN”,就用 load()函数载入编译后的英文翻译文件 samp16_1_en.qm,否则就载入中文翻译文件 samp16_1_cn.qm。然后再执行app.installTranslator(trans),就可以给应用程序安装翻译器,实现需要的界面版本。
samp16_1_en.qm 和samp16_1_cn.qm 文件是被编译到项目的可执行文件中的,无需将这两个文件复制到可执行文件目录下。

在 main()函数里加载翻译器是相比之下一劳永逸的方法,这样一来,随后应用程序的任何窗口都会自动应用开始设置的语言。所以,一些大型的软件在重新设置了语言版本后,通常都会要求重新启动软件才生效。

5.3 动态切换语言

在软件运行时可以动态切换语言,即无需重启软件就可以切换界面语言。在 samp16_1 的主窗口上有“中文”和“English”两个工具栏按钮,用于实现中文和英文界面的切换。下面是这两个按钮的响应代码:

void MainWindow::on_actLang_CN_triggered()
{//中文界面qApp->removeTranslator(trans);delete trans;trans=new QTranslator;trans->load("samp16_1_cn.qm");qApp->installTranslator(trans);ui->retranslateUi(this);QSettings   settings("WWB-Qt","samp16_1"); //注册表键组settings.setValue("Language","CN"); //界面语言,汉语
}void MainWindow::on_actLang_EN_triggered()
{//英文界面qApp->removeTranslator(trans);delete trans;trans=new QTranslator;trans->load("samp16_1_en.qm");qApp->installTranslator(trans);ui->retranslateUi(this);QSettings   settings("WWB-Qt","samp16_1"); //注册表键组settings.setValue("Language","EN"); //界面语言,英语
}

一个应用程序只能加载一个翻译器,因为在 main()函数里已经加载了一个翻译器,所以需要先移除当前的翻译器,才能重新创建新的翻译器,加载翻译文件,并为应用程序重新加载新翻译器。
完成这些后还必须调用 UI的 retranslateUi()函数来刷新界面。

retranslateUi()函数是在窗口的“ui_”头文件中自动生成的,如 mainwindow.ui 主窗口对应的头文件 ui_mainwindow.h 里就有函数 retranslateUi(),这个函数使用 QApplication::translate()函数将所有界面字符串进行翻译,类似于 tr()函数的功能。

窗口在被创建时会自动调用此 retranslateUi()函数,在程序运行中动态切换界面语言时,必须手工调用此retranslateUi()函数,才可以立即更新界面语言。

若不是用 UI Designer 设计的窗口,而是完全由代码实现的窗口界面,需要专门设计一个retranslateUi()函数,将所有界面字符串用 tr()函数进行翻译,并在动态切换语言时调用此函数。很显然,这样做比较麻烦,特别是当软件比较大,窗口非常多时。所以,大型的软件在重新设置语言版本后,一般要求重新启动软件才生效,在程序启动时根据上次的设置加载一次翻译器即可。

按钮响应代码的最后是将设置的语言版本写入注册表,以便下次程序启动时自动加载相应的语言。

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

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

相关文章

自动化测试框架?数据驱动vs关键字驱动,该怎么做?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 对于自动化测试框…

BI报表工具有哪些作用?奥威BI全面剖析数据

BI报表工具有哪些作用&#xff1f;主要的作用是通过整合多业务来源数据&#xff0c;全面分析挖掘数据&#xff0c;来帮助企业实现数据化运营、支持智能决策、实现数据资产沉淀和增值、进行数据挖掘和预测分析、提高数据可读性和数据可视化程度等&#xff0c;从而提高企业的竞争…

【C++学习】STL容器——list

目录 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list 迭代器失效 二、list的模拟实现 2.1 模拟实现list 三、list和vector的对比…

Java版知识付费平台免费搭建 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台qt

&#xfeff;Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含&#xff1a;录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署&#xff0c;免费售…

CNN成长路:从AlexNet到EfficientNet(01)

一、说明 在 10年的深度学习中&#xff0c;进步是多么迅速&#xff01;早在 2012 年&#xff0c;Alexnet 在 ImageNet 上的准确率就达到了 63.3% 的 Top-1。现在&#xff0c;我们超过90%的EfficientNet架构和师生训练&#xff08;teacher-student&#xff09;。 如果我们在 Ima…

【Kubernetes部署篇】基于Ubuntu20.04操作系统搭建K8S1.23版本集群

文章目录 一、集群架构规划信息二、系统初始化准备(所有节点同步操作)三、安装kubeadm(所有节点同步操作)四、初始化K8S集群(master节点操作)五、添加Node节点到K8S集群中六、安装Calico网络插件七、测试CoreDNS可用性 一、集群架构规划信息 pod网段&#xff1a;10.244.0.0/16…

HTTP——九、基于HTTP的功能追加协议

HTTP 一、基于HTTP的协议二、消除HTTP瓶颈的SPDY1、HTTP的瓶颈Ajax 的解决方法Comet 的解决方法SPDY的目标 2、SPDY的设计与功能3、SPDY消除 Web 瓶颈了吗 三、使用浏览器进行全双工通信的WebSocket1、WebSocket 的设计与功能2、WebSocket协议 四、期盼已久的 HTTP/2.01、HTTP/…

卡尔曼滤波 | Matlab实现无迹kalman滤波仿真

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 卡尔曼滤波 | Matlab实现无迹kalman滤波仿真 研究内容 无迹kalman滤波(UKF)不是采用的将非线性函数线性化的做法。无迹kalman仍然采用的是线性kalman滤波的架构,对于一步预测方程,使用无迹变换(UT)来…

visio,word添加缺少字体,仿宋_GB2312、楷体_GB2312、方正小标宋简体等字体下载

一. 内容简介 visio,word添加缺少字体,仿宋_GB2312、楷体_GB2312、方正小标宋简体等字体下载 二. 软件环境 2.1 visio 三.主要流程 3.1 下载字体 http://www.downza.cn/ 微软官方给的链接好多字体没有&#xff0c;其他好多字体网站&#xff0c;就是给你看个样式&#xff…

vue3中CompositionApi理解与使用

CompositionApi&#xff0c;组合式API&#xff0c;相当于react中hooks&#xff0c;函数式。 优势&#xff1a;1&#xff0c;增加了代码的复用性&#xff08;类似mixin&#xff0c;slot&#xff0c;高阶组件功能&#xff09; 2&#xff0c;代码可读性更好。可以将处理逻辑和视图…

Elasticsearch:语义搜索 - Semantic Search in python

当 OpenAI 于 2022 年 11 月发布 ChatGPT 时&#xff0c;引发了人们对人工智能和机器学习的新一波兴趣。 尽管必要的技术创新已经出现了近十年&#xff0c;而且基本原理的历史甚至更早&#xff0c;但这种巨大的转变引发了各种发展的“寒武纪大爆炸”&#xff0c;特别是在大型语…

数字孪生的「三张皮」问题:数据隐私、安全与伦理挑战

引言 随着数字化时代的来临&#xff0c;数据成为了当今社会的宝贵资源。然而&#xff0c;数据的广泛使用也带来了一系列隐私、安全与伦理挑战。数字孪生作为一种虚拟的数字化实体&#xff0c;通过收集和分析大量数据&#xff0c;模拟和预测现实世界中的各种情境&#xff0c;为…

【云原生|Docker系列第3篇】Docker镜像的入门实践

欢迎来到Docker入门系列的第三篇博客&#xff01;在前两篇博客中&#xff0c;我们已经了解了什么是Docker以及如何安装和配置它。本篇博客将重点介绍Docker镜像的概念&#xff0c;以及它们之间的关系。我们还将学习如何拉取、创建、管理和分享Docker镜像&#xff0c;这是使用Do…

循环结构进阶

二重循环 import java.util.Scanner;public class Demo01 {public static void main(String[] args) {Scanner scanner new Scanner(System.in);// 二重循环 外循环班级 内循环学生for (int i1; i<3; i) { // 外循环班级System.out.println("请输入第" i "…

Leetcode-每日一题【剑指 Offer 17. 打印从1到最大的n位数】

题目 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。 答案需要取模 1e97&#xff08;1000000007&#xff09;&#xff0c;如计算初始结果为&#xff1a;1000000008&#xff0c;请返回 1。 示例 1&#xff1a; 输…

机器学习、人工智能、深度学习三者的区别

目录 1、三者的关系 2、能做些什么 3、阶段性目标 1、三者的关系 机器学习、人工智能&#xff08;AI&#xff09;和深度学习之间有密切的关系&#xff0c;它们可以被看作是一种从不同层面理解和实现智能的方法。 人工智能&#xff08;AI&#xff09;&#xff1a;人工智能是一…

什么是serialVersionUID?

serialVersionUID是干啥的&#xff1f; Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。 在进行反序列化时&#xff0c;JVM会把传来的字节流中的serialVersionUID与本地相应实体&#xff08;类&#xff09;的serialVersionUID进行比较&#xff0…

结构体和 Json 相互转换(序列化反序列化)

关于 JSON 数据 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也 易于机器解析和生成。RESTfull Api 接口中返回的数据都是 json 数据。 Json 的基本格式如下&#xff1a; { "a": "Hello", "b": "…

如何申请中国境内提供金融信息服务业务许可

依据《外国机构在中国境内提供金融信息服务管理规定》《外国机构在中国境内提供金融信息服务申请许可说明》等政策&#xff0c;外国机构在中国境内提供金融信息服务业务许可要求如下&#xff1a; 金融信息服务定义 所称的外国机构&#xff0c;是指外国金融信息服务提供者。 …

java环境搭建 Ubuntu Linux

jdk的安装和配置环境变量 使用apt sudo apt install default-jdk若是安装成功了在终端输入java -version来查看是否安装成功 使用官网下载的jdk包 直接在百度上搜索jdk&#xff0c;选择图片这个 网址:jdk下载网址 若是arm就选择带有arm的&#xff0c;反之选择x64的&#…