QT-自定义本地翻译模块,简单实用

news2024/12/25 1:55:41

QT-自定义本地翻译模块,简单实用

  • 前言
  • 一、演示效果
  • 二、核心模块
    • 1.本地xml的操作过程
    • 2、翻译模块
  • 三、程序链接


前言

QT的国际语言每次如果有字符串变动,都需要重新再编译一下,真的是顶不住,说实话,用起来真的是不习惯。
为了解决这个问题,我们设计基本的逻辑:

1、将控件名称保存到本地xml,也就是先初始化一个需要我们要翻译的文本。
2、在xml填入翻译的内容。
3、软件显示我们翻译的内容,这里就是有技巧,我们希望是自动去翻译这些控件,而不是程序四处都看到我们翻译的过程。

一、演示效果

1、本地xml格式内容如下,启动source的属性是我们程序自动生成的,我们当然是希望没翻译之前,这些需要我们翻译的字段先填好。
在这里插入图片描述

2、界面显示效果如下:
在这里插入图片描述
在这里插入图片描述

二、核心模块

1.本地xml的操作过程

代码如下:

#include "LanguageXml.h"
#include <QMutex>
#include <QFile>

LanguageXml::LanguageXml(QObject *parent)
	: QObject(parent)
{
	
}

LanguageXml::~LanguageXml()
{
}

//插入链表
void LanguageXml::insertItem(QString strSource, QString strTranslate)
{
	m_itemsHash.insert(strSource,strTranslate);
}

//读取本地链表
bool LanguageXml::readItems(QString strFilePath)
{
	if (strFilePath.isEmpty())
		return false;

	QMutex mutex;
	mutex.lock();
	QFile file(strFilePath);
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		mutex.unlock();
		return false;
	}

	QXmlStreamReader reader(&file);
	while (!reader.atEnd())
	{
		reader.readNext();
		QString strElementName = reader.name().toString();
		if (reader.isStartElement() && strElementName == QString("Item"))
		{
			QString strSource;
			QString strTranslation;
			auto attr = reader.attributes();

			if (attr.hasAttribute("Source"))
				strSource = attr.value("Source").toString();

			if (attr.hasAttribute("Translation"))
				strTranslation = attr.value("Translation").toString();

			m_itemsHash[strSource] = strTranslation;
		}
	}

	file.close();
	mutex.unlock();

	return true;
}

//保存本地
bool LanguageXml::saveItems(QString strFilePath)
{
	if (strFilePath.isEmpty())
		return false;

	static QMutex mutex;
	mutex.lock();
	QFile file(strFilePath);
	file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
	QXmlStreamWriter writer(&file);

	writer.setAutoFormatting(true);
	writer.writeStartDocument();

	if (true)
	{
		writer.writeStartElement("LanguageItems");  

		auto keys = m_itemsHash.keys();
		for (int j = 0; j < keys.size(); j++)
		{
			if (true)
			{
				writer.writeStartElement("Item"); 
				writer.writeAttribute("Source", keys[j]);
				writer.writeAttribute("Translation", m_itemsHash[keys[j]]);

				writer.writeEndElement();   
			}
		}

		writer.writeEndElement();  
	}

	writer.writeEndDocument();

	file.close();

	mutex.unlock();

	return true;
}

//返回链表
QHash<QString, QString> LanguageXml::getItemsHash()
{
	return m_itemsHash;
}

2、翻译模块

代码如下:

#include "ControlsTranslate.h"
#include "LanguageXml.h"
#include <QPushButton>
#include <QToolButton>
#include <QGroupBox>
#include <QCheckBox>
#include <QRadioButton>
#include <QLineEdit>
#include <QDateTimeEdit>
#include <QLocale>
#include <QTableWidget>
#include <QTreeWidget>
#include <QLabel>
#include <QComboBox>
#include <QApplication>
#include <QFile>
#include <QMainWindow>

ControlsTranslate::ControlsTranslate(QObject *parent)
	: QObject(parent)
{
	m_pLanguageXml = new LanguageXml(parent);
	m_objectList = getAllObject(parent);
	initialTranslateFile();

}

ControlsTranslate::~ControlsTranslate()
{
}

//获取所有控件
QObjectList ControlsTranslate::getAllObject(QObject * parent)
{
	QObjectList childrenList, tempList;
	if (parent)
		childrenList = parent->children();

	if (childrenList.isEmpty())
		return childrenList;

	tempList = childrenList;
	foreach(QObject* obj, tempList)
	{
		QObjectList lst = getAllObject(obj);
		if (!lst.isEmpty())
			childrenList.append(lst);
	}

	return childrenList;
}

//翻译控件
void ControlsTranslate::translateAllControls(const QString &strLanguage)
{
	if (!m_objectList.isEmpty())
	{
		foreach(QObject *obj, m_objectList)
		{

			auto pPushButton = qobject_cast<QPushButton *>(obj);
			if (pPushButton != nullptr)
				pPushButton->setText(translate(pPushButton->text()));

			auto pToolButton = qobject_cast<QToolButton *>(obj);
			if (pToolButton != nullptr)
				pToolButton->setText(translate(pToolButton->text()));

			auto pWidget = qobject_cast<QWidget *>(obj);
			if (pWidget != nullptr)
				pWidget->setWindowTitle(translate(pWidget->windowTitle()));

			auto pGroupBox = qobject_cast<QGroupBox *>(obj);
			if (pGroupBox != nullptr)
				pGroupBox->setTitle(translate(pGroupBox->title()));

			auto pLabel = qobject_cast<QLabel *>(obj);
			if (pLabel != nullptr)
				pLabel->setText(translate(pLabel->text()));

			auto pCheckBox = qobject_cast<QCheckBox *>(obj);
			if (pCheckBox != nullptr)
				pCheckBox->setText(translate(pCheckBox->text()));

			auto pRadioButton = qobject_cast<QRadioButton *>(obj);
			if (pRadioButton != nullptr)
				pRadioButton->setText(translate(pRadioButton->text()));

			auto pLineEdit = qobject_cast<QLineEdit *>(obj);
			if (pLineEdit != nullptr)
			{
				pLineEdit->setText(translate(pLineEdit->text()));
				pLineEdit->setPlaceholderText(translate(pLineEdit->placeholderText()));
			}

			auto pDateTimeEdit = qobject_cast<QDateTimeEdit *>(obj);
			if (pDateTimeEdit != nullptr)
			{
				if (strLanguage.compare("ChineseT") == 0)
					pDateTimeEdit->setLocale(QLocale(QLocale::Chinese, QLocale::Taiwan));  
				else if (strLanguage.compare("English") == 0)
					pDateTimeEdit->setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
				else if (strLanguage.compare("Korea") == 0)
					pDateTimeEdit->setLocale(QLocale(QLocale::Korean, QLocale::SouthKorea));
			}

			auto pDateEdit = qobject_cast<QDateEdit *>(obj);
			if (pDateEdit != nullptr)
			{
				if (strLanguage.compare("ChineseT") == 0)
					pDateEdit->setLocale(QLocale(QLocale::Chinese, QLocale::Taiwan));
				else if (strLanguage.compare("English") == 0)
					pDateEdit->setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
				else if (strLanguage.compare("Korea") == 0)
					pDateEdit->setLocale(QLocale(QLocale::Korean, QLocale::SouthKorea));
			}

			auto pTableWidget = qobject_cast<QTableWidget *>(obj);
			if (pTableWidget != nullptr)
			{
				for (int i = 0; i < pTableWidget->columnCount(); i++)
				{
					if (pTableWidget->horizontalHeaderItem(i))
						pTableWidget->horizontalHeaderItem(i)->setText(translate(pTableWidget->horizontalHeaderItem(i)->text()));
				}
			}

			auto pTabWidget = qobject_cast<QTabWidget *>(obj);
			if (pTabWidget != nullptr)
			{
				for (int i = 0; i < pTabWidget->count(); i++)
					pTabWidget->setTabText(i, translate(pTabWidget->tabText(i)));
			}

			auto pTreeWidget = qobject_cast<QTreeWidget *>(obj);
			if (pTreeWidget != nullptr)
			{
				QTreeWidgetItemIterator item(pTreeWidget);
				while (*item)
				{
					(*item)->setText(0, translate((*item)->text(0)));

					QTreeWidgetItem *parent = (*item)->parent();
					if (NULL == parent)
						(*item)->setHidden(true);

					++item;
				}
			}

			auto pComboBox = qobject_cast<QComboBox *>(obj);
			if (pComboBox != nullptr)
			{
				for (int i = 0; i < pComboBox->count(); i++)
					pComboBox->setItemText(i, translate(pComboBox->itemText(i)));
			}
		}
	}

}

//翻译
QString ControlsTranslate::translate(QString strName)
{
	auto hash = m_pLanguageXml->getItemsHash();
	auto itFind = hash.find(strName);
	if (itFind != hash.end())
		return hash[strName];
	else
		return strName;

	return "";
}

//初始化
void ControlsTranslate::initialTranslateFile()
{
	QString strFilePath = QApplication::applicationDirPath() + "/transalte.xml";

	// 先初始化
	if (!m_objectList.isEmpty())
	{
		foreach(QObject *obj, m_objectList)
		{
			
			auto pPushButton = qobject_cast<QPushButton *>(obj);
			if (pPushButton != nullptr)
				m_pLanguageXml->insertItem(pPushButton->text(), "");

			auto pToolButton = qobject_cast<QToolButton *>(obj);
			if (pToolButton != nullptr)
				m_pLanguageXml->insertItem(pToolButton->text(), "");

			auto pWidget = qobject_cast<QWidget *>(obj);
			if (pWidget != nullptr)
				m_pLanguageXml->insertItem(pWidget->windowTitle(), "");

			auto pGroupBox = qobject_cast<QGroupBox *>(obj);
			if (pGroupBox != nullptr)
				m_pLanguageXml->insertItem(pGroupBox->title(), "");

			auto pLabel = qobject_cast<QLabel *>(obj);
			if (pLabel != nullptr)
				m_pLanguageXml->insertItem(pLabel->text(), "");

			auto pCheckBox = qobject_cast<QCheckBox *>(obj);
			if (pCheckBox != nullptr)
				m_pLanguageXml->insertItem(pCheckBox->text(), "");

			auto pRadioButton = qobject_cast<QRadioButton *>(obj);
			if (pRadioButton != nullptr)
				m_pLanguageXml->insertItem(pRadioButton->text(), "");

			auto pLineEdit = qobject_cast<QLineEdit *>(obj);
			if (pLineEdit != nullptr)
			{
				m_pLanguageXml->insertItem(pLineEdit->text(), "");
				m_pLanguageXml->insertItem(pLineEdit->placeholderText(), "");
			}

			auto pTableWidget = qobject_cast<QTableWidget *>(obj);
			if (pTableWidget != nullptr)
			{
				for (int i = 0; i < pTableWidget->columnCount(); i++)
				{
					if (pTableWidget->horizontalHeaderItem(i))
						m_pLanguageXml->insertItem(pTableWidget->horizontalHeaderItem(i)->text(), "");
				}
			}

			auto pTabWidget = qobject_cast<QTabWidget *>(obj);
			if (pTabWidget != nullptr)
			{
				for (int i = 0; i < pTabWidget->count(); i++)
					m_pLanguageXml->insertItem(pTabWidget->tabText(i), "");
			}

			auto pTreeWidget = qobject_cast<QTreeWidget *>(obj);
			if (pTreeWidget != nullptr)
			{
				QTreeWidgetItemIterator item(pTreeWidget);
				while (*item)
				{
					m_pLanguageXml->insertItem((*item)->text(0), "");

					QTreeWidgetItem *parent = (*item)->parent();
					if (NULL == parent)
						(*item)->setHidden(true);

					++item;
				}
			}

			auto pComboBox = qobject_cast<QComboBox *>(obj);
			if (pComboBox != nullptr)
			{
				for (int i = 0; i < pComboBox->count(); i++)
					m_pLanguageXml->insertItem(pComboBox->itemText(i), "");
			}
		}
	}

	// 再赋值
	m_pLanguageXml->readItems(strFilePath);

	if (m_objectList.size() > 0)
		m_pLanguageXml->saveItems(strFilePath);
}

三、程序链接

https://download.csdn.net/download/u013083044/87262164

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

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

相关文章

DataX-Web 源码调试及打包

文章目录1、还原 dataxweb 数据库2、修改配置文件3、打包前文回顾&#xff1a; 《DataX 及 DataX-Web 安装使用详解》 《DataX 源码调试及打包》 源码地址&#xff1a;https://github.com/WeiYe-Jing/datax-web 1、还原 dataxweb 数据库 sql 脚本在目录 /bin/db/datax-web.sq…

Keycloak之17.0.1 版本与Jenkins安装与集成-yellowcong

jekins和keycloak的认证,是依赖于 Keycloak Authentication Plugin 插件,进行认证处理,这个配置还是相对比较简单的,最坑的一点就是如果配置错误了,如何恢复的问题。 keycloak 应用集成 Keycloak之安装与启动-yellowcong Keycloak之功能介绍与简单使用-yellowcong Keyc…

BW取月底月初日期函数

BW取月底内置的函数与SAP有差异&#xff0c;为 SN_LAST_DAY_OF_MONTH&#xff0c;如下 很简单的逻辑&#xff0c;主要通过2月的日期进行判断为平年还是闰年&#xff0c;其他月末日期固定 取月底函数&#xff1a; call function SN_LAST_DAY_OF_MONTH EXPORTING DAY_IN …

如何下载不同格式的卫星地图

如何下载不同格式的卫星地图 发布时间&#xff1a;2018-01-17 版权&#xff1a; 务名称&#xff1a;下载任务的名称&#xff0c;可重命名 经纬度范围当前下载区域所在的经纬度范围&#xff0c;不可更改 保存路径&#xff1a;下载你选择区域的文件保存的地方&#xff0c;可更…

基于jsp+mysql+ssm在线培训教育平台-计算机毕业设计

项目介绍 本在线培训教育课程平台系统主要包括系统用户管理模块、课程类别管理模块、课程信息管理、站内新闻管理、登录模块、和退出模块等多个模块。它帮助在线教育平台实现了信息化、网络化&#xff0c;通过测试&#xff0c;实现了系统设计目标,系统采用了jsp的mvc框架,SSM(…

Allegro如何检查过孔类型是否使用正确操作指导

Allegro如何检查过孔类型是否使用正确操作指导 Allegro可以检查PCB上过孔类型是否使用正确,让使用错误的过孔以DRC的形式报出来,具体操作如下 选择setup-Constraint-modes 出现Analysis mode的窗口,选择Physical Modes,Vialist DRC选择on开关,并且保证On-line DRC是勾选…

【数据结构】堆的实现(向上、下调整比较,复杂度,堆排序,Top-K问题)

文章目录一、堆的实现1、堆的概念2、堆的性质3、堆的实现堆的创建&#xff08;向上、下调整比较&#xff09;堆排序Top-K&#xff08;读取文件当中的数据&#xff09;一、堆的实现 1、堆的概念 如果有一个关键码的集合K {k0&#xff0c;k1&#xff0c; k2&#xff0c;…&…

餐饮行业的成本率与毛利率

1、成本率与毛利率 成本率是指成本量与营业额&#xff08;销售额&#xff09;之间的比率&#xff0c;表示实现一定量的销售额需要多少比例的成本资源消耗。 成本率越低&#xff0c;表示企业实现单位业绩付出的资源代价越小&#xff0c;释放出的收益空间越大&#xff1b;相反&a…

docker安装nginx以及(nginxWebUI和nginx-gui图形化界面的使用)

一、docker安装nginx 1、拉取镜像 docker pull nginx2、创建挂载目录 mkdir -vp /usr/local/docker/nginx cd /usr/local/docker/nginx #创建用户挂在的目录 mkdir -vp logs html conf3、启动镜像 1、方式一(推荐) 1、启动 docker run -d --name nginx -p 80:80 nginx2、…

vue实现企业微信扫码登录后台管理系统

大致流程 在登录页面构建内嵌式登录二维码&#xff08;这种方式好处&#xff1a;无需跳转到企业微信域下登录后再返回&#xff0c;提升企业微信登录的流畅性与成功率&#xff09;扫二维码之后&#xff0c;微信那边会跳转到redirect_uri你重定向的地址&#xff0c;后面会拼接co…

医疗器械网络安全漏洞自评报告模板

提示&#xff1a;编制医疗器械网络安全漏洞自评报告要点解析 文章目录1. 目的2. 引用文件3. CVSS漏洞等级3.1 概述3.1.1 适用范围说明3.1.2 CNNVD-ID定义3.1.3 编码原则3.1.4 CNNVD-ID语法介绍3.2 指标分析3.2.1 基本指标3.2.1.1可用性指标1)攻击向量2)攻击复杂性3)所需权限4)用…

二、基础平滑、面积折线图与折线堆叠、面积堆叠《手把手教你 ECharts 数据可视化详解》

注&#xff1a;本系列教程需要对应 JavaScript 、html、css 基础&#xff0c;否则将会导致阅读时困难&#xff0c;本教程将会从 ECharts 的官方示例出发&#xff0c;详解每一个示例实现&#xff0c;从中学习 ECharts 。 ECharts 官方示例&#xff1a;https://echarts.apache.o…

蚁剑v4.0流量分析

​ 目录 0x01声明&#xff1a; 0x02简介&#xff1a; 0x03环境搭建&#xff1a; 下载&#xff1a; 初始化项目&#xff1a; 0x04流量分析&#xff1a; 解密&#xff1a; 0x05总结&#xff1a; 0x01声明&#xff1a; 仅供学习参考使用&#xff0c;请勿用作违法用途&…

2023年天津天狮学院专升本专业课如何线上考试考前准备的要求

天津天狮学院2023年高职升本科专业课线上考试要求根据目前疫情防控形势&#xff0c;为保障广大考生身体健康及安全&#xff0c;我校 2023 年高职升本科专业课考试拟采取在线考试形式。为保证此次考试顺利进行&#xff0c;特对报考我校专业课考生提出以下参加考试要求&#xff0…

Ansible自动化运维工具之playbook剧本编写

一.playbook的相关知识 1.1 playbook 的简介 playbook是 一个不同于使用Ansible命令行执行方式的模式&#xff0c;其功能更强大灵活。简单来说&#xff0c;playbook是一个非常简单的配置管理和多主机部署系统&#xff0c;不同于任何已经存在的模式&#xff0c;可作为一个适合…

【MAUI】为 Label、Image 等控件添加点击事件

一、前言 已经习惯了 WPF、WinForm 中“万物皆可点击”的方式。 但是在 MAUI 中却不行了。 在 MAUI 中&#xff0c;点击、双击的效果&#xff0c;是需要通过“手势识别器”来实现。 本篇文章&#xff0c;我们就通过“手势识别器”来为 Label、Image等控件实现点击事件。 相信…

若依微服务版登录流程源码分析1

若依微服务版登录流程涉及到很多模块&#xff0c;本章先从网关讲起 验证码 验证码配置 先来看配置中心的网关配置文件ruoyi-gateway-dev.yml&#xff0c;其中有这么一段 # 安全配置 security:# 验证码captcha:enabled: truetype: math这段配置什么作用呢&#xff0c;就是将…

牛客网刷题【BC7、BC8、BC9、 BC10、 BC11、 BC12】

目录 一 、BC12 字符圣诞树 二、BC7 缩短二进制 三、BC8 十六进制转十进制 四、BC9 printf的返回值 五、BC10 成绩输入输出 六、BC11 学生基本信息输入输出 一 、BC12 字符圣诞树 #include <stdio.h>int main() {char val0;//读入字符scanf("%c",&…

Git入门与进阶 - 总览

Git入门与进阶教程 欢迎加好友一起讨论问题 知识地图&#xff1a;入门Git简介https://blog.csdn.net/lili40342/article/details/128241047Git安装与配置https://blog.csdn.net/lili40342/article/details/128241144Git工作流程https://blog.csdn.net/lili40342/article/detail…

[附源码]计算机毕业设计的个人理财系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…