一文詳解如何實現(xiàn)QT的多語言切換(靜態(tài)+動態(tài))
背景:
1.項目開發(fā)上:多人多模塊同時開發(fā),需要考慮如何便于管理共同開發(fā)
2.文本有兩類:界面上固定不變的文本(靜態(tài));在程序運行時才能獲得的文本(動態(tài))
任務:
實現(xiàn)軟件的多語言切換功能。
接下來會介紹兩個實現(xiàn)途徑,分別是QT語言家工具,以及.ts文件的手動編寫(推薦第二種)。
一、QT語言家
Qt Linguist(Qt 語言家)是 Qt 開發(fā)環(huán)境中用于國際化和本地化的工具。它會提供翻譯支持,將應用程序的用戶界面和其他文本元素翻譯成不同的語言,是一種可視化工具。
如果安裝了的話,可以在這里找到:
1、.pro文件增加TRANSLATIONS
TRANSLATIONS += resource/language/lang_zh_CN.ts\ resource/language/lang_en.ts 說明: lang_zh_CN.ts為中文部分,lang_en.ts為英文部分, 此處我的這兩個.ts文件是放在resource/language目錄下,需要照自己的具體路徑進行更改
2、更新翻譯(lupdate)
之后出現(xiàn)信息:
3、通過QT語言家打開.ts文件
由于我使用的是MSVC 2017 64-bit,所以我是使用對應的Linguist打開兩個.ts文件:
在這兩項中分別寫入英文文本和中文文本,編輯完成后保存并發(fā)布(lrelease):
發(fā)布(lrelease)的目的是將.ts文件編譯為.qm文件,.qm文件是二進制文件,可以看到同目錄下已經(jīng)生成.qm文件:
4、代碼中使用.qm文件進行翻譯
將生成的.qm文件加入到資源文件中。
在啟動時根據(jù)不同的系統(tǒng)語言顯示不同的翻譯:
void MainWindow::initLanguage() { QTranslator translator; QLocale::Language lab = QLocale::system().language(); if(QLocale::Chinese == lab) { translator.load(":/language/lang_zh_CN.qm"); hApp->installTranslator(&translator); Q_EMIT hApp->m_sigmanager->translateLanguage(LANGUAGE::CHINESE); }else if(QLocale::English== lab){ translator.load(":/language/lang_en.qm"); hApp->installTranslator(&translator); Q_EMIT hApp->m_sigmanager->translateLanguage(LANGUAGE::ENGLISH); } } 說明: 注意.qm文件的路徑要寫對,不然無法翻譯,如果找不到可以在.pro文件中增加 INCLUDEPATH 這里我自定義了translateLanguage信號去觸發(fā)語言的切換,各個模塊負責分別連接該信號,編寫槽函數(shù),舉例: 某模塊: connect(hApp->m_sigmanager,&SignalManager::translateLanguage,this,&SampleMainWidget::retranslate); void SampleMainWidget::retranslate() { ui->retranslateUi(this); }
5、需要注意的問題
QT語言家不止可以展示.ui文件中我們給控件預先編輯的文本內(nèi)容,還有代碼中定義的文本內(nèi)容,只是需要在QT語言家展示代碼內(nèi)待翻譯文本,要使用宏 QT_TR_NOOP ,它通常用于標記那些在運行時不需要翻譯,但需要在翻譯文件中保留的字符串。
QString test = QT_TR_NOOP("test1") 說明: test的值仍然是原文本,而非翻譯后的文本
在需要翻譯時,使用以下方式(在retranslateui后需要重新設置控件文本):
void SampleMainWidget::retranslate() { ui->retranslateUi(this); QString text = ui->rackBtn->text(); ui->rackBtn->setText(hApp->translate("SampleApply",text.toStdString().c_str())); } 說明: hApp->translate中的第一個參數(shù),其實對應.ts文件中的<name>元素,和作用域的作用類似 如果使用QT語言家,一般是QT_TR_NOOP定義文本所在的類名 第二個參數(shù),其實對應.ts文件中的<source>元素,這里的類型是char*
二、.ts文件的手動編寫
首先需要簡單了解.ts文件和.qm文件:
.ts文件(翻譯源文件):.ts文件是Qt中的翻譯源文件,XML格式。它包含了源代碼中的所有可翻譯文本,以及它們的上下文信息。
.qm文件(翻譯目標文件):.qm文件是Qt中的翻譯目標文件,二進制格式。.qm文件包含了已經(jīng)翻譯好的文本,以及與之對應的源代碼中的文本。通過將.ts文件編譯成.qm文件,可以提高程序的執(zhí)行效率,因為程序在運行時直接加載.qm文件,而無需解析和處理XML格式的.ts文件。
1、.ts的格式說明
打開.ts文件:
如圖中標號所示:
1、文件頭部信息。指定了翻譯文件的版本(2.1),目標語言(zh_CN,即中文)等信息。
2、劃分的作用域名字。
3、每個待翻譯的字符串都有一個 message 元素,其中l(wèi)ocation元素指定了源代碼中字符串的位置;source 元素包含了原始的文本;translation元素用于存儲翻譯后的文本。
其中,location沒有也可以,只是QT語言家打開.ts文件時定位不到字符串位置而已,主要還是source 元素和translation元素,source元素相當于字符串的id,翻譯家通過source在lang_zh_CN.ts找中文文本,在lang_en.ts找英文文本。
2、多人管理開發(fā)
創(chuàng)建language.xlsx,language.xlsx中包含多個模塊sheet,每個sheet的表頭為 id Chinese English
其中id為文本項唯一標識符,Chinese為中文文本,English為英文文本。
使用python,將excel轉(zhuǎn)換為.ts文件,并編譯為.qm文件:
import openpyxl import subprocess from xml.dom.minidom import Document def read_excel(file_path): # 打開 Excel 文件 wb = openpyxl.load_workbook(file_path) # 讀取所有 sheet 的數(shù)據(jù) all_rows = [] for sheet_name in wb.sheetnames: sheet = wb[sheet_name] all_rows.extend([ tuple(sheet.cell(row=row, column=col).value for col in range(1, sheet.max_column + 1)) for row in range(2, sheet.max_row + 1) ]) return all_rows def create_ts_file(language, rows): # 創(chuàng)建 XML 文檔 doc = Document() ts = doc.createElement('TS') ts.setAttribute('version', '2.1') ts.setAttribute('language', language) doc.appendChild(ts) # 創(chuàng)建 <context> 元素 context = doc.createElement('context') ts.appendChild(context) for row in rows: source, chinese, english = row # 創(chuàng)建 <message> 元素 message = doc.createElement('message') # 創(chuàng)建 <source> 元素 source_element = doc.createElement('source') source_element.appendChild(doc.createTextNode(source)) message.appendChild(source_element) # 創(chuàng)建 <translation> 元素 translation_element = doc.createElement('translation') translation_element.appendChild(doc.createTextNode(chinese if language == 'zh_CN' else english)) message.appendChild(translation_element) context.appendChild(message) # 將 XML 寫入文件,設置縮進和換行 xml_str = doc.toprettyxml(indent=" ", encoding='utf-8').decode('utf-8') ts_file_path = f'lang_{language}.ts' with open(ts_file_path, 'w', encoding='utf-8') as file: file.write(xml_str) # 調(diào)用 lrelease 命令編譯 .ts 文件為 .qm 文件 subprocess.run(['lrelease', ts_file_path]) if __name__ == "__main__": # 讀取 Excel 文件數(shù)據(jù) excel_data = read_excel("language.xlsx") for language in ["zh_CN", "en"]: # 生成每個語言的 .ts 文件 create_ts_file(language, excel_data)
以下為生成的內(nèi)容格式:
思路:
將工程所有文本都集中在一個excel中,需要給專業(yè)翻譯人員翻譯時,只需要提供這樣一份excel,在指定位置補充翻譯后文本就可以。
這里是簡單通過id的數(shù)值范圍使各模塊獨立,即每個sheet的文本容量為1萬,從左到右:main(0到9999),scheme(10000到19999),sample(20000到29999)…以此類推。
也可以通過sheet名稱作為作用域名稱,在.ts文件中增加name元素,只要能保證source唯一不重復,這些方式都是可以的。
3、代碼中如何使用
在代碼中的使用(可以不使用ui->retranslateUi(this);了):
在連接語言切換信號的槽函數(shù)中設置待翻譯的文本信息,如:
void SampleMainWidget::retranslate() { ui->rackBtn->setText(hApp->translate(0,"0_main_voice")); }
translate參數(shù)中0代表全局范圍,"0_main_voice"即文本id。
總結(jié)
到此這篇關(guān)于如何實現(xiàn)QT的多語言切換(靜態(tài)+動態(tài))的文章就介紹到這了,更多相關(guān)QT多語言切換實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言通過深度優(yōu)先搜索來解電梯問題和N皇后問題的示例
深度優(yōu)先搜索即是對一個新發(fā)現(xiàn)的節(jié)點上如果還關(guān)聯(lián)未探測到的邊,就沿此邊探測下去,直到發(fā)現(xiàn)從原點可達的所有點為止,這里我們就來展示C語言通過深度優(yōu)先搜索來解電梯問題和N皇后問題的示例2016-06-06通過先序遍歷和中序遍歷后的序列還原二叉樹(實現(xiàn)方法)
下面小編就為大家?guī)硪黄ㄟ^先序遍歷和中序遍歷后的序列還原二叉樹(實現(xiàn)方法)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06C語言數(shù)據(jù)結(jié)構(gòu)之中綴樹轉(zhuǎn)后綴樹的實例
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之中綴樹轉(zhuǎn)后綴樹的實例的相關(guān)資料,需要的朋友可以參考下2017-08-08C++深入分析內(nèi)聯(lián)函數(shù)的使用
為了消除函數(shù)調(diào)用的時空開銷,C++ 提供一種提高效率的方法,即在編譯時將函數(shù)調(diào)用處用函數(shù)體替換,類似于C語言中的宏展開。這種在函數(shù)調(diào)用處直接嵌入函數(shù)體的函數(shù)稱為內(nèi)聯(lián)函數(shù)(Inline Function),又稱內(nèi)嵌函數(shù)或者內(nèi)置函數(shù)2022-04-04