当前位置: 首页 > news >正文

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());
...

相关文章:

QT 国际化(翻译)

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

C 进阶 — 指针的使用

C 进阶 — 指针的使用 主要内容 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 6、函数指针数组 7、指向函数指针数组的指针 8、 回调函数 9、指针和数组练习题 前节回顾 1、指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一…...

【经验分享】容器云运维的知识点

最近忙于备考没关注&#xff0c;有次点进某小黄鱼发现首页出现了我的笔记还被人收费了 虽然我也卖了一些资源&#xff0c;但我以交流、交换为主&#xff0c;笔记都是免费给别人看的 由于当时刚刚接触写的并不成熟&#xff0c;为了避免更多人花没必要的钱&#xff0c;所以决定公…...

MFC学习笔记专栏开篇语

MFC&#xff0c;是一个英文简写&#xff0c;全称为 Microsoft Foundation Class Library&#xff0c;中文翻译为微软基础类库。它是微软开发的一套C类库&#xff0c;是面向对象的函数库。 微软开发它&#xff0c;是为了给程序员提供方便&#xff0c;减少程序员的工作量。如果没…...

电子科技大学《高级算法设计与分析》期末复习问题汇总(客观题-选择题、判断题)

电子科技大学《高级算法设计与分析》问题汇总_已知背包问题的动态规划算法时间复杂度为o(nw),其中n为物品数目,w为背包容量。请-CSDN博客 转载自上面这个链接&#xff0c;古希腊掌管成电专业课的神&#xff01;&#xff01;为了防止他的链接失效&#xff0c;自己也转存一份 &…...

GPTcelltype——scRNA-seq注释

#安装包 install.packages("openai") remotes::install_github("Winnie09/GPTCelltype") #填写API Sys.setenv(OPENAI_API_KEY your_openai_API_key) #加载包 #Load packages library(GPTCelltype) library(openai) #准备文件 #Assume you have already r…...

AI与大数据的深度结合:驱动决策的革命性力量

引言&#xff1a;数字时代的决策挑战 在这个信息爆炸的数字时代&#xff0c;数据早已渗透到我们生活的方方面面。全球每天产生的数据量呈指数级增长&#xff0c;无论是用户的消费行为、设备的运行状态&#xff0c;还是社会热点的实时动态&#xff0c;这些信息的规模和复杂性前所…...

Java多线程与线程池技术详解(九)

面对苦难的态度&#xff1a;《病隙碎笔》“不断的苦难才是不断地需要信心的原因&#xff0c;这是信心的原则&#xff0c;不可稍有更动。” 孤独与心灵的成长&#xff1a;《我与地坛》“孤独的心必是充盈的心&#xff0c;充盈得要流溢出来要冲涌出去&#xff0c;便渴望有人呼应他…...

【常考前端面试题总结】---2025

React fiber架构 1.为什么会出现 React fiber 架构? React 15 Stack Reconciler 是通过递归更新子组件 。由于递归执行&#xff0c;所以更新一旦开始&#xff0c;中途就无法中断。当层级很深时&#xff0c;递归更新时间超过了 16ms&#xff0c;用户交互就会卡顿。对于特别庞…...

什么是大语言模型(LLM)

1. 什么是大语言模型&#xff08;LLM&#xff09;&#xff1f; LLM 是一种基础模型&#xff08;Foundation Model&#xff09;的实例。 基础模型的特点&#xff1a; 使用大量未标注的自监督数据进行预训练。通过学习数据中的模式&#xff0c;生成具有普适性和可适应性的输出…...

柚坛工具箱Uotan Toolbox适配鸿蒙,刷机体验再升级

想要探索智能设备的无限可能&#xff1f;Uotan Toolbox&#xff08;柚坛工具箱&#xff09;将是您的得力助手。这款采用C#语言打造的创新型开源工具箱&#xff0c;以其独特的设计理念和全面的功能支持&#xff0c;正在改变着用户与移动设备互动的方式。 作为一款面向专业用户的…...

supervisor使用详解

参考文章&#xff1a; Supervisor使用详解 Supervisor 是一个用 Python 编写的客户端/服务器系统&#xff0c;它允许用户在类 UNIX 操作系统&#xff08;如 Linux&#xff09;上监控和控制进程。Supervisor 并不是一个分布式调度框架&#xff0c;而是一个进程管理工具&#x…...

win11电源设置在哪里?控制面板在哪里?如何关闭快速启动?

不知道微软咋想的&#xff0c;从win10&#xff08;win8&#xff09;开始搞事情&#xff0c;想把windows娱乐化。 娱乐化的特点就是只照顾傻子不考虑专家&#xff0c;系统设置统统藏起来&#xff0c;开机即用——也只能那么用。 搞两套界面做不到吗&#xff1f; win11非常头疼的…...

【论文阅读笔记】One Diffusion to Generate Them All

One Diffusion to Generate Them All 介绍理解 引言二、相关工作三、方法预备知识训练推理实现细节训练细节 数据集构建实验分结论附录 介绍 Paper&#xff1a;https://arxiv.org/abs/2411.16318 Code&#xff1a;https://github.com/lehduong/onediffusion Authors&#xff1…...

SpringCloud和Nacos的基础知识和使用

1.什么是SpringCloud ​ 什么是微服务&#xff1f; ​ 假如我们需要搭建一个网上购物系统&#xff0c;那么我们需要哪些功能呢&#xff1f;商品中心、订单中心和客户中心等。 ​ 当业务功能较少时&#xff0c;我们可以把这些功能塞到一个SpringBoot项目中来进行管理。但是随…...

人工智能技术的深度解析与推广【人工智能的应用场景】

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…...

md5sum -c

md5sum -c xxx 命令用于验证文件的 MD5 校验和是否匹配。具体来说&#xff0c;-c 选项告诉 md5sum 命令去读取指定文件&#xff08;通常是一个包含 MD5 校验和的文件&#xff09;&#xff0c;并与实际文件的 MD5 校验和进行比较。 工作原理&#xff1a; 生成校验和文件&#x…...

excel使用笔记

1.工作表1计算工作表2某列的和 假设我们有两个工作表&#xff0c;分别命名为“Sheet1”和“Sheet2”&#xff0c;我们想要求和这两个工作表中A1到A**单元格的数据&#xff0c;可以在任意一个工作表的单元格中输入以下公式&#xff1a; SUM(Sheet1!A1:A10, Sheet2!A1:A10) SUM…...

keepalived+nginx实现web高可用

目录 高可用集群搭建 Keepalived&#xff0b;nginx实现web高可用 一.节点规划 二.基础准备 1.修改主机名 2.关闭防火墙和selinux服务 三.用keepalived配置高可用 1.安装nginx服务 2.修改nginx配置文件 3.启动nginx 4.访问nginx 5.安装keepalived服务 6.编辑配置文件…...

边界层气象:脉动量预报方程展开 | 湍流脉动速度方差预报方程 | 平均湍流动能收支方程推导

写成分量形式 原始式子&#xff1a; ∂ u i ′ ∂ t u ‾ j ∂ u i ′ ∂ x j u j ′ ∂ u ‾ i ∂ x j u j ′ ∂ u i ′ ∂ x j − 1 ρ ‾ ⋅ ∂ p ′ ∂ x i g θ v ′ θ ‾ v δ i 3 f ϵ i j 3 u j ′ v ∂ 2 u i ′ ∂ x j 2 ∂ ( u i ′ u j ′ ‾ ) ∂ x j…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

Visual Studio Code 扩展

Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后&#xff0c;命令 changeCase.commands 可预览转换效果 EmmyLua…...

Python环境安装与虚拟环境配置详解

本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南&#xff0c;适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者&#xff0c;都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...

GeoServer发布PostgreSQL图层后WFS查询无主键字段

在使用 GeoServer&#xff08;版本 2.22.2&#xff09; 发布 PostgreSQL&#xff08;PostGIS&#xff09;中的表为地图服务时&#xff0c;常常会遇到一个小问题&#xff1a; WFS 查询中&#xff0c;主键字段&#xff08;如 id&#xff09;莫名其妙地消失了&#xff01; 即使你在…...