Qt、QML動態語言切換功能的實現
本例jic+介紹了qml混合程式設計的du執行多語言翻譯,工程目錄及執行效果如下圖:
一、生成資原始檔
1.在pro中ti新增需要多語言翻譯所需要的檔案,這樣編譯工程時會自動生成這兩個ts檔案。
TRANSLATIONS = language_zh_cn.ts \
language_en_us.ts
2.使用Qt Creator自帶的工具生成ts檔案
3.開啟Qt Linguist工具(該工具在裝Qt Creator一般預設是安裝的),分別開啟兩個檔案,進行翻譯,儲存(英文也可以不翻譯)。
4.翻譯完畢,執行步驟2中的第二個工具,將會由ts檔案生成qm檔案,這就是動態語言翻譯所需要的資原始檔。
二、動態載入資原始檔
在下面這個例子中,Translator作為一個語言翻譯類以單例的形式存在。
1.初始化
Translator.h
#ifndef TRANSLATOR_H #define TRANSLATOR_H #include <QObject> class QTranslator; class Translator : public QObject { Q_OBJECT public: static Translator* getInstance(); private: explicit Translator(QObject *parent = 0); ~Translator(); signals: void languageChanged(); public slots: void loadLanguage(QString lang); private: QTranslator* m_translator; }; #endif // TRANSLATOR_H
Translator.cpp
#include "Translator.h" #include <QTranslator> #include <QApplication> #include <QDebug> Translator *Translator::getInstance() { static Translator transInstance; return &transInstance; } Translator::Translator(QObject *parent) : QObject(parent) { m_translator = new QTranslator; } Translator::~Translator() { delete m_translator; } void Translator::loadLanguage(QString lang) { qDebug()<<"load"<<lang; if(NULL == m_translator) { return; } if(lang.contains("English")) { if(m_translator->load(":/language_en_us.qm")) { QApplication::installTranslator(m_translator); emit languageChanged(); } else { qDebug()<<"load en error"; } } else { if(m_translator->load(":/language_zh_cn.qm")) { QApplication::installTranslator(m_translator); emit languageChanged(); } else { qDebug()<<"load cn error"; } } }
main.c
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
Translator::getInstance()->loadLanguage("Chinese");//初始化為中文
MainWindow w;
w.show();
return a.exec();
}
2.QWidget新增動態翻譯支援
步驟1只能支援靜態設定,要想實現動態切換,需要在每個類中加入兩個函式changEvent(QEvent *event)和translateUI(),
具體解釋見程式碼標註:
maindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void changeEvent(QEvent* event);//用於動態翻譯
void translateUI();//執行動態翻譯
signals:
void sigSendPowerInitData(QString str);
void sigSendTimeInitData(QString str);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
void MainWindow::changeEvent(QEvent *event)
{
switch (event->type()) {
case QEvent::LanguageChange:
translateUI();
break;
default:
QMainWindow::changeEvent(event);
break;
}
}
void MainWindow::translateUI()
{
ui->retranslateUi(this);
/*跳轉到retranslateUi()函式,實際它執行了以下操作:重新設定了需要翻譯的文字。
*在這個例子中ui是通過Qt Designer實現的,如果是自己new的部件也是同樣的處理方法,重新設定本類中需要翻譯的文字,qml檔案中也是類似的處理
*
void retranslateUi(QMainWindow *MainWindow)
{
label->setText(QApplication::translate("MainWindow", "This is a label", Q_NULLPTR));
pushButton->setText(QApplication::translate("MainWindow", "Switch Language", Q_NULLPTR));
pushButton_2->setText(QApplication::translate("MainWindow", "Show QML Page", Q_NULLPTR));
}
*/
}
3.QML中新增動態翻譯支援
類似c++中的做法,qml動態翻譯的處理也是重新設定需要翻譯的文字。
如上所述,Translator::loadLanguage()被呼叫時執行動態語言的載入,同時發出一個languageChanged()訊號,該訊號在下面被接收處理,從而完成動態載入。關於Connections以及混合程式設計的知識參考:
Connections
{
target: translator
onLanguageChanged:{
initTranslator();
}
}
function initTranslator(){
m_txt.text = qsTr("Power/w");
textChinese.text = qsTr("Chinese");
textEnglish.text = qsTr("English");
}
4.我們也可以在qml頁面完成語言切換
這裡是通過translator來呼叫loadLanguage(),載入語言檔案後發出languageChanged()訊號,從而觸發qml頁面的重新翻譯。
Button{
id:btnEnglish
anchors.left: scaleLayout.right
anchors.leftMargin: 40
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -50
Text {
id : textEnglish
anchors.centerIn : btnEnglish
text: qsTr("English")
color: "white"
font.pointSize: fontButtonSize
}
onClicked: {
translator.loadLanguage("English");
}
style: buttonStyle
}
三、需要注意的幾個點
1.QML上下文屬性設定
//點選按鈕彈出qml頁面的操作
void MainWindow::on_pushButton_2_clicked()
{
QQuickWidget *quickWidget = new QQuickWidget();
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
quickWidget->setAttribute(Qt::WA_DeleteOnClose);
quickWidget->setClearColor(QColor(Qt::transparent));
//這裡要注意:下面這個語句必須要在quickWidget->setSource()執行前執行,否則qml在載入的時候無法識別“translator”
quickWidget->rootContext()->setContextProperty("translator", Translator::getInstance());
quickWidget->setSource(QUrl(QStringLiteral("qrc:/PowerSetting.qml")));
//quickWidget->setWindowFlags(Qt::FramelessWindowHint);
quickWidget->show();
QQuickItem *item = quickWidget->rootObject();
//quickWidget->rootContext()->setContextProperty("translator", Translator::getInstance());//如果放在這裡程式也能執行,但是會報錯
//...
}
2.注意是每個需要翻譯的頁面都要新增changEvent(QEvent *event)和translateUI()函式處理。
3.每次改動文字後,需要重新生成ts和qm檔案。
原始碼下載: