常见流程
- 将需要翻译的字符串加上
tr( )
。若没有在QObject
子类的成员函数中,那么可以直接使用QCorerApplication::translate( )
函数亦或QT_TR_NOOP( )
宏和QT_TAANSLATE_NOOP( )
宏。这两个宏仅对文本进行标记来方便lupdate工具
提取。 - 通过
Qt Linguist
翻译应用程序运行ludata工具
,提取要翻译的文本,生成.ts
文件,这个文件是XML
格式的。 - 打开
Qt Linguist
进行翻译。 - 运行
lrelease工具
,生成.qm
文件,这个一个根据.ts
生成的文件,供我们翻译时使用。这里的.ts
和.qm
均与平台无关。
DEMO
.pro
TRANSLATIONS += cn.ts
TRANSLATIONS += en.ts
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTranslator>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void changeEvent(QEvent* event);
private slots:
void on_comboBox_activated(int index);
private:
Ui::MainWindow *ui;
QTranslator translator;
};
#endif // MAINWINDOW_H
.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeEvent(QEvent* event){
if (event->type() == QEvent::LanguageChange){
ui->retranslateUi(this);
}
//
QWidget::changeEvent(event);
}
void MainWindow::on_comboBox_activated(int index)
{
if(index == 0){
//English
translator.load(":/en.qm");
qApp->installTranslator( &translator );
}if(index == 1){
translator.load(":/cn.qm");
qApp->installTranslator( &translator );
}
}
主要逻辑如下:
- 翻译时使用
translator.load("xxx.qm");
qApp->installTranslator( &translator );
- 随后会触发
changeEvent
事件,我们重写changeEvent
槽函数,在这里调用retranslateUi()
更新ui
ui->retranslateUi(this);
combox刷新问题
若存在待翻译的 combox
,很快我们就发现,原先选择的内容在翻译后又变成了首项。
问题出现在 retranslateUi()
中,上文我们使用的是 ui->retranslateUi(this)
;它位于 ui_mainwindow.h
中,关于 Combox
的翻译其实现如下:
comboBox->clear();
comboBox->insertItems(0, QStringList()
<< QApplication::translate("MainWindow", "English", Q_NULLPTR)
<< QApplication::translate("MainWindow", "\344\270\255\346\226\207", Q_NULLPTR)
);
原来默认使用的是将 Combox
清空再添加可选项的做法。怪不得每次 currindex
都会丢失。
解决的方法也很简单,我们自己实现 retranslateUi()
,增加 currentIndex
变量保存 combox
当前选中的状态。
void MainWindow::retranslateUi()
{
//...
int curreindex = ui->comboBox->currentIndex();
ui->comboBox->clear();
ui->comboBox->insertItems(0, QStringList()
<< QApplication::translate("MainWindow", "English", Q_NULLPTR)
<< QApplication::translate("MainWindow", "\344\270\255\346\226\207", Q_NULLPTR)
);
ui->comboBox->setCurrentIndex(curreindex);
//...
}
持久化
软件中通常会将语言作为持久化信息,在下一次打开软件时,恢复上一次的语言选择。
毫无疑问这必须将语言信息保存到本地。本处采用 QSetting。
扫描二维码关注公众号,回复:
12046620 查看本文章
void MainWindow::closeEvent(QCloseEvent *event){
//退出前保存语言习惯
QSettings settings("FSF", "TEST");
settings.beginGroup("MainWindows");
settings.setValue("language",QVariant(ui->comboBox->currentIndex()));
settings.endGroup();
}
//读取语言设置
int index;
QSettings settings("FSF", "TEST");
settings.beginGroup("MainWindows");
index = settings.value("language",0).toInt();
settings.endGroup();
if(index == 0){
translator.load(":/en.qm");
qApp->installTranslator( &translator );
}if(index == 1){
translator.load(":/cn.qm");
qApp->installTranslator( &translator );
}
题外话
也可以根据系统环境来进行语言设置;获取本地语言环境的方法如下:
QLocale::system().name()
其他
加速键值翻译
对于类似 Ctrl+Q
之类的加速键,如果采用硬编码 Qt::CTRL
+ Qt::Key_Q
,那么翻译无法将它们覆盖。正确的习惯用法为:
//创建动作
exitAct = new QACtion(tr("E&xit").this);
//设置快捷键
exitAct->setShortcuts(QkeySequence::Quit);
动态文本
对于有些待翻译的字符串,若其中含有变量不需要翻译则需要使用该方式:
QMessageBox::information(NULL, tr("Path"), tr("You selected\n%1").arg(path));
QMessageBox::information(NULL, tr("Path"), "You selected\n" + path);
翻译非Qt类
需要在类定义时使用 Q_DECLARE_TR_FUNCTIONS
宏:
class MyClass{
Q_DECLARE_TR_FUNCTIONS(ClassName)
public:
MyClass();
//...
}
多界面
仅需在其他界面中重写changeEvent,调用retranslateUi更新文本即可。