QT 国际化(翻译)

        QT国际化(Internationalization,简称I18N)是指将一个软件应用程序的界面、文本、日期、数字等元素转化为不同的语言和文化习惯的过程。这使得软件能够在不同的国家和地区使用,并且可以根据用户的语言和地区提供本地化的使用体验。

        QT是一种跨平台的应用程序开发框架,提供了很多工具和功能来支持国际化。下面将介绍QT国际化的一些基本概念和示例代码。

一、QT国际化三部曲

        lupdate(更新),linguist(编辑),lrelease(发布)

1、lupdate

         lupdate是一个命令行工具,随Qt框架一起提供,它的主要作用是从源代码中提取出所有的可翻译字符串,并更新.ts文件(Translation Source文件)。.ts文件是XML格式的,包含了源代码中出现的所有可翻译字符串及其对应的翻译。


lupdate的工作原理大致如下:

(1)解析源代码:lupdate遍历指定的源文件或源代码目录,解析C++、QML或JavaScript文件,寻找所有的可翻译字符串。在C++中,这通常是通过tr()函数、QT_TR_NOOP()宏、QObject::tr()方法或者其他相关的Qt翻译宏来标识的。

(2)提取字符串:当lupdate找到一个可翻译的字符串时,它会提取出字符串及其上下文信息。上下文通常是包含该字符串的类名,这有助于翻译人员了解字符串在应用程序中的用途。

(3)更新.ts文件:lupdate然后将这些字符串添加到对应的.ts文件中。如果字符串已经存在,它会保留现有的翻译并标记任何更改。如果字符串是新的,它将被添加,等待翻译。

(4)处理旧字符串:对于在源代码中不再出现的字符串,lupdate可以标记它们为“obsolete”(过时的),或者根据命令行参数的不同,直接从.ts文件中删除。

(5)保存.ts文件:更新后的.ts文件将包含所有从源代码中提取的字符串,以及任何现有的翻译和新的、未翻译的或标记为过时的条目。

 

选项和参数
lupdate 提供了一些选项来控制其行为:
-pro filename :指定 Qt 项目的 Pro 文件,lupdate 将自动从 Pro 文件配置中查找源文件。
-ts filename [filename …] :指定输出的翻译文件,可以是多个文件。
-recursive :递归地扫描目录及其子目录中的源文件。
-no-obsolete :移除翻译文件中不再存在于源代码中的条目。
-extensions extensions :指定源文件的扩展名,例如 .cpp, .h, .qml。

 2、linguist

         Linguist 是 Qt 提供的一个用于翻译和本地化的工具套件,它包括三个关键的命令行工具:lupdate、lrelease 和 linguist 主程序。

        这些工具分别用于提取可翻译字符串、生成可执行的翻译文件以及编辑翻译文件。这里主要介绍 linguist 主程序的工作原理和使用方法。

Linguist 主程序的工作原理: 

(1)打开翻译文件:Linguist 打开以 .ts 为扩展名的 Qt 翻译文件。这些文件通常由 lupdate 工具生成,其中包含待翻译的字符串、上下文及其在源代码中的定位信息。


(2)编辑翻译条目:

翻译人员可以使用 Linguist 编辑每个翻译条目的翻译内容。界面显示原始字符串和待翻译的字符串,翻译人员可以直接输入相应的翻译。


(3)翻译状态管理:Linguist 支持不同的翻译状态,如“未翻译”、“已翻译”、“已校对”等,帮助翻译人员和项目管理人员跟踪翻译进度和质量。


(4)术语库和建议:Linguist 能够使用术语库和以前的翻译建议,提高翻译的一致性和效率。这些建议可以从已翻译的字符串和外部的术语库文件中获得。


(5)语法和拼写检查:Linguist 提供内置的语法和拼写检查功能,提醒翻译人员可能的拼写错误或常见语法问题。


(6)生成二进制翻译文件:翻译完成后,可以通过 lrelease 工具将 .ts 文件编译成 .qm 文件,供应用程序在运行时加载。

3、lrelease

         lrelease 是 Qt 工具链的一部分,用于将 .ts (Qt 翻译源文件) 编译为 .qm (Qt 翻译二进制文件) 文件。.qm 文件用于在运行时加载翻译内容,从而实现多语言支持。

lrelease 的工作原理和使用方法如下:

(1)读取 .ts 文件:lrelease 读取一个或多个 .ts 文件,这些文件包含源语言字符串及其翻译内容。
(2)解析 XML 数据:.ts 文件是基于 XML 格式的文本文件,lrelease 解析这些 XML 数据,提取所有翻译条目信息。
(3)生成二进制文件:lrelease 将这些解析后的数据编译成高效的二进制格式 .qm 文件,这些文件可以在运行时被 Qt 应用程序加载。

 二、应用

         Qt开发中的构建工具常用qmake和cmake。

1、使用qmake进行国际化 

 .pro文件中添加支持的语言

TRANSLATIONS = lanague_cn.ts\lanague_en.ts

在Qt Creator中调用lupdate导出ts文件 

或在命令行输入命令:lupdate trans.pro -ts lanague_en.ts 

 然后用语言家(linguist)打开要翻译的ts文件进行编辑翻译

 

编辑完发布(调用lrelease)生成qm文件 (Qt 翻译二进制文件)

 

使用qm文件

 QTranslator translator;translator.load("D:/QTDemo/trans/lanague_en.qm");a.installTranslator(&translator);
 2、使用cmake进行国际化 

 在CMakeLists.txt文件中添加下列代码

set(TS_FILES"${CMAKE_SOURCE_DIR}/zh_CN.ts""${CMAKE_SOURCE_DIR}/en_US.ts"
)find_program(LUPDATE_EXECUTABLE lupdate)
find_program(LRELEASE_EXECUTABLE lrelease)foreach(_ts_file ${TS_FILES})execute_process(COMMAND ${LUPDATE_EXECUTABLE} -recursive ${CMAKE_SOURCE_DIR} -ts ${_ts_file})execute_process(COMMAND ${LRELEASE_EXECUTABLE} ${_ts_file})
endforeach()

执行CMake 

三、切换语言 

1、重启程序 

使用QProcess类静态方法

// program, 要启动的程序名称
// arguments, 启动参数
bool startDetached(const QString &program, const QStringList &arguments);

示例代码: 

ui

MainWindow.h 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void slotCurrentTextChanged(const QString &str);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

MainWindow.cpp 

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSettings>
#include <QProcess>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->comboBox->addItem("简体中文");ui->comboBox->addItem("English");QSettings settings(QCoreApplication::applicationDirPath()+"/config.ini", QSettings::IniFormat);QString str = settings.value("Set/Language").toString();if(!str.isEmpty())ui->comboBox->setCurrentText(str);connect(ui->comboBox,&QComboBox::currentTextChanged,this,&MainWindow::slotCurrentTextChanged);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::slotCurrentTextChanged(const QString &str)
{QSettings settings(QCoreApplication::applicationDirPath()+"/config.ini", QSettings::IniFormat);settings.setValue("Set/Language", str);//    qApp->quit();
//    QProcess::startDetached(qApp->applicationFilePath(), QStringList());qApp->exit(777);
}

main.cpp

#include "mainwindow.h"#include <QApplication>
#include <QTranslator>
#include <QSettings>
#include <QProcess>int main(int argc, char *argv[])
{QApplication a(argc, argv);QSettings settings(QCoreApplication::applicationDirPath()+"/config.ini", QSettings::IniFormat);QString str = settings.value("Set/Language").toString();QTranslator translator;if(str == "English"){translator.load("D:/QTDemo/trans/lanague_en.qm");a.installTranslator(&translator);}MainWindow w;w.show();//  return a.exec();int e = a.exec();if(e == 777){QProcess::startDetached(qApp->applicationFilePath(), QStringList());return 0;}return e;
}
2、不重启程序 

        监听QEvent::LanguageChange事件,当切换翻译器时会在底层发出一个LanguageChange事件,所有的需要改变文本的窗口都监听这个事件。

示例代码:

在窗口中重写 bool event(QEvent *event)

bool MainWindow::event(QEvent *event)
{if(event->type() == QEvent::LanguageChange){ui->retranslateUi(this); //重新翻译UI界面}return QWidget::event(event);
}

需要注意:在加载新的语言时,需要先将已绑定的语言移除。 

void MainWindow::slotCurrentTextChanged(const QString &str)
{static QTranslator* translator;if (translator != NULL){//先将已绑定的语言移除qApp->removeTranslator(translator);delete translator;translator = NULL;}translator = new QTranslator;if(str == "English"){translator->load("D:/QTDemo/trans/lanague_en.qm");qApp->installTranslator(translator);}
}

四、注意事项

        不能直接翻译全局变量、静态变量、符号常量字符串 

        因为全局变量、静态变量初始化发生在QTranslator::installTranslator之前,Qt无法替换(翻译)这些变量。而通过QT_TR_NOOP宏可以标识出静态生存期变量,让Qt可以晚一些再翻译这些变量,称为delayed translation 

         对于常量字符串、符号常量字符串,它们甚至在编译时就被编译器替换好了,就更不可能经QCoreApplication::translate翻译了。像下面的做法都是徒劳:

#define DEFINE_MESSAGE_ QT_TR_NOOP("Failed to 1")
const char *kConstMessage = QT_TR_NOOP("Failed to 2");
static const char *kStaticConstMessage = QT_TR_NOOP("Failed to 3");
...QMessageBox::critical(nullptr, tr("Error"), tr(DEFINE_MESSAGE_);QMessageBox::critical(nullptr, tr("Error"), tr(kConstMessage);QMessageBox::critical(nullptr, tr("Error"), tr(kStaticConstMessage);
...

 一种替代方案是通过一个类封装全局变量,并将类声明Q_DECLARE_TR_FUNCTIONS宏或者继承QObject

//GlobalMessageWarpper.h
class GlobalMessageWarpper
{Q_DECLARE_TR_FUNCTIONS(GlobalMessageWarpper)
public:static QString message() { return tr(kMessage); }static const char* kMessage;
};//GlobalMessageWarpper.cpp
const char* GlobalMessageWarpper::kMessage = QT_TR_NOOP("Failed to ...");...
QMessageBox::critical(nullptr, tr("Error"), GlobalMessageWarpper::message());
...

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

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

相关文章

3D 生成重建034-NerfDiff借助扩散模型直接生成nerf

3D 生成重建034-NerfDiff借助扩散模型直接生成nerf 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 感觉这个论文可能能shapE差不多同时期工作&#xff0c;但是shapE是生成任意种类。 本文提出了一种新颖的单图像视图合成方法NerfDiff&#xff0c;该方法利用神经辐射场 …

【CNN卷积神经网络算法】卷积神经网络

卷积神经网络整体架构 总结 输入层&#xff1a;原始数据&#xff08;图像&#xff09; 例如可以输入一张RGB图像&#xff0c;其可以标示为一个三维矩阵&#xff0c;宽W高H和通道数C3对应着RGB卷积层&#xff1a;提取局部特征&#xff0c;变换输入数据为丰富的特征图 网络使用多…

HarmonyOS Next 元服务新建到上架全流程

HarmonyOS Next 元服务新建到上架全流程 接上篇 这篇文章的主要目的是介绍元服务从新建到上家的完整流程 在AGC平台上新建一个项目 链接 一个项目可以多个应用 AGC新建一个元服务应用 新建一个本地元服务项目 如果成功在AGC平台上新建过元服务&#xff0c;那么这里会自动显…

Mac/Windows端长期破解myBase8方法(无需安装火绒)

提醒 不管哪个端&#xff0c;都需要先退出myBase。 Mac 进入用户根目录/Users/c0ny100&#xff0c;即下边是Macintosh HD > 用户 > [你的用户名]这个界面然后按ShiftCommond.&#xff0c;显示隐藏文件。找到.Mybase8.ini文件 打开.Mybase8.ini文件&#xff0c;删除Fir…

【网络安全】【Kali Linux】简单ICMP主机探测

一、参考资料 《Python安全攻防——渗透测试实战指南》&#xff0c;吴涛 等编著&#xff0c;机械工业出版社&#xff0c;2021年10月 二、探测原理 ICMP&#xff08;ping命令&#xff09; 三、脚本编写 1、导入所需的库&#xff1a; 2、扫描功能函数&#xff1a; 3、主函数…

Oracle进行exp导出密码中有特殊字符报EXP-00056和ORA-12154错处理

今天&#xff0c;业务人员反馈&#xff0c;在本地进行exp导出时报错&#xff0c;报错内容如下&#xff1a; 在Oracle密码中有特殊字符时&#xff0c;需要加引号&#xff0c;但引号怎么加呢&#xff1f;总结如下&#xff1a; 1、在windows系统中 exp 用户名/“““密码”””n…

MVC流程分析

DisaptcherServlet本质是servlet&#xff0c;执行init()方法&#xff0c;自启动底层执行代码&#xff0c; 作用&#xff1a; 1、读取springmvc配置文件&#xff0c;创建Controller对象&#xff0c;放入容器中&#xff0c;map<"id",对象> 2、接收用户请求&#…

fiddler设置抓取https,还抓取不到https如何解决?

一、清楚 C:\Users\Admin\AppData\Roaming\Microsoft\Crypto\RSA 目录下所有文件&#xff08;首次安装fiddler请忽略&#xff09; 二、清除电脑上的根证书&#xff0c;WINR快捷键&#xff0c;输入&#xff1a;certmgr.msc&#xff0c; 然后回车&#xff0c;查找所有fiddler证书…

【知识】总体标准差和样本标准差有什么区别

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 总体标准差和样本标准差之间的区别主要在于它们的计算方式&#xff0c;特别是在分母的选择上。这种差异是因为我们通常在实际应用中并不总是能够得到整…

.NET 9 已发布,您可以这样升级或更新

.NET 9 已经发布&#xff0c;您可能正在考虑更新您的 ASP.NET Core 应用程序。 我们将介绍更新应用程序所需的内容。从更新 Visual Studio 和下载 .NET SDK 到找出可能破坏应用程序的任何重大更改。 下载 .NET 9 SDK 这些是下载 .NET 9 SDK 所需的步骤。 更新 Visual Studi…

【Iot】前端串口serialport.js串口通信库快速入门(附经验总结)

前端串口serialport.js串口通信库快速入门(附经验总结) 一、serialport简介1.1 安装1.2 基本用法1.3 完整示例代码二、问题2.1 数据包被拆分(已解决)2.2 串口返回的多种数据,如何区分类别(待解决)公司项目需要开发一个windows客户端,提供串口modbusRTU数据读取、处理、显…

前端报错npm ERR cb() never called问题

环境使用node版本v14.21.3&#xff0c;npm版本6.14.18 1.问题描述 1.1使用npm install后报错 npm ERR! cb() never called!npm ERR! This is an error with npm itself. Please report this error at: npm ERR! ? ? <https://npm.community>npm ERR! A complete log…

【下】王树森《小红书推荐系统公开课》- 课程笔记(特征交叉、行为序列、重排/推荐系统多样性、物品冷启动、涨指标的方法)

写在前面 本文为王树森老师《小红书推荐系统公开课》的课程笔记 课程来源&#xff1a;ShusenWang的个人空间-ShusenWang个人主页-哔哩哔哩视频 (bilibili.com)课程资料&#xff1a;GitHub - wangshusen/RecommenderSystem 由于篇幅较长&#xff0c;分为【上】【下】两篇文章…

[C++]C++工具之对异常情况的处理(throw、catch、try)以及用命名空间避免同名冲突

一、C 异常处理&#x1f60a; 1.1 定义 C 中的异常处理用于应对程序运行中的异常情况&#xff08;如除零、数组越界等&#xff09;&#xff0c;通过 try-catch 机制捕获和处理错误&#xff0c;防止程序崩溃。 异常是程序运行时意外发生的事件&#xff0c;可以通过抛出&#xf…

Dynamics 365 CRM- 后端

Dynamics 365 CRM 后端插件语法示例 public IPluginExecutionContext context null;//上下文 public IOrganizationServiceFactory serviceFactory null;//组织服务工厂对象 public IOrganizationService service null;//Org服务对象//创建执行上下文 context (IPluginExe…

C语言——实现并求出两个数的最大公约数

问题描述&#xff1a;求出两个数的最大公约数 //求两个数的最大公约数 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h>int main() {int a,b;printf("请您输入两个数 a 和 b\n");scanf…

采用qL-MPC技术进行小型固定翼无人机的路径跟随控制

来自论文"Predictive Path-Following Control for Fixed-Wing UAVs Using the qLMPC Framework in the Presence of Wind Disturbances" 控制架构 采用的是 ULTRA-Extra无人机&#xff0c;相关参数如下&#xff1a; 这里用于guidance law的无人机运动学模型为&#…

三维无人机航迹算法的目标函数如何确定

一、定义目标函数 在三维无人机航迹算法中,目标函数的确定通常基于具体的任务需求和飞行约束。以下是一个简单的例子,展示了如何为三维无人机航迹规划定义一个目标函数。 例子:最小化飞行时间和避障的三维无人机航迹规划 1.任务描述:无人机需要从起点飞到终点,同时避开一些…

《Java核心技术I》Swing用户界面组件

Swing和模型-视图-控制器设计模式 用户界面组件各个组成部分&#xff0c;如按钮&#xff0c;复选框&#xff0c;文本框或复杂的树控件&#xff0c;每个组件都有三个特征&#xff1a; 内容&#xff0c;如按钮的状态&#xff0c;文本域中的文本。外观&#xff0c;颜色&#xff0c…

【Office】Office实现shift+鼠标滚轮左右滑动

Office实现shift鼠标滚轮左右滑动 windows系统安装office之后发现&#xff0c;使用shift鼠标滚轮不能够实现左右滑动&#xff0c;我记得以前的office好像是可以的&#xff0c;然后在网上找了一下&#xff0c;找到了一个插件可以实现这个功能 OfficeScroll插件 下载地址&…