版权声明:本文系作者原创。未经许可,不得转载。
本文以skytree-compositor程序为例,讲解如何将程序翻译为多种语言。
在界面中,点击“设置”,更改“语言”时,dbus会向上层发送一个信号valueChanged,上层应用响应该信号,就可以实时更改语言。
1、从dbus读取语言改变的信号和系统使用的语言名称。类CmosTranslate使用了Qt自带的QTranslator类,并添加了读取dbus的功能。实现了封装,供其他程序使用。一共两个文件。代码如下:
CmosTranslate.h文件
#ifndef CmosTranslate_H
#define CmosTranslate_H
#include <QObject>
#include <QDBusVariant>
#include <QTranslator>
/**
这个类根据dbus发出的信号,从dbus读取当前语言名称,实时改变程序的语言
*/
-
CmosTranslate : public QObject
{Q_OBJECT Q_DISABLE_COPY(CmosTranslate) Q_PROPERTY(QString name READ name WRITE setname NOTIFY nameChanged) Q_PROPERTY(QString path READ path WRITE setpath NOTIFY pathChanged) Q_PROPERTY(QString transflag READ transflag NOTIFY transflagChanged)
public:
CmosTranslate(QObject *parent = 0); ~CmosTranslate(); //获取程序名称 QString name() { return m_name; } //设置程序名称 void setname(QString value) { m_name = value; emit nameChanged(m_name); } //获取多语言文件存放的路径 QString path() { return m_path; } //获取多语言文件存放的路径 void setpath(QString value) { m_path = value; emit pathChanged(m_path); } QString transflag() { return ""; }
-
slots:
void readData(const QString &domain, const QString &key, const QDBusVariant &value); //根据读取的语言名称,载入相应的翻译文件 void trans(QString names=""); bool appQuit();
Q_SIGNALS:
void nameChanged(const QString &); void pathChanged(const QString &); void langChanged(const QString &); void transflagChanged();
private:
//程序名称 QString m_name; //翻译文件存放路径 QString m_path; QString m_selfcmd; QTranslator m_translator; // 静态方法
public:
/**
获取单实例
*@return 指向单实例的指针
*/
CmosTranslate *instance();
};QString SETTING_SERVICE_NAME = "cn.cmos.settings.Database";
QString SETTING_OBJECT_PATH = "/";
QString SETTING_INTERFACE_NAME= "cn.cmos.settings.Database";
QString APP_PATH = qgetenv("APPDIR_SYSTEM");
QString LIBRARY_PATH = "/usr/share/library/";
//如果没有设置路径,则默认为qm路径QString TRANSLATIONS_PATH = "qm";
QString DOMAIN_VALUE = "cn.cmos.settings.Locale";
QString KEY_VALUE = "SYSTEM_LANGUAGE";
//设置该程序的默认的翻译文件存放路径-
QString QM_FILE_PATH = "/usr/share/translations";
CmosTranslate::CmosTranslate(QObject *parent):QObject(parent)
{
QFile file("/proc/self/cmdline"); file.open(QIODevice::ReadOnly | QIODevice::Text); m_selfcmd = file.readAll(); m_selfcmd= m_selfcmd.left(m_selfcmd.lastIndexOf( QDir::separator() ) ); m_selfcmd= m_selfcmd.left(m_selfcmd.lastIndexOf( QDir::separator() ) ); m_name = QApplication::applicationName(); m_path = QM_FILE_PATH; //将dbus的信号与程序连接 QDBusConnection::sessionBus().connect(SETTING_SERVICE_NAME, SETTING_OBJECT_PATH, SETTING_INTERFACE_NAME, "valueChanged" ,this, SLOT(readData(QString, QString, QDBusVariant)));
}
CmosTranslate::~CmosTranslate()
{
} -
CmosTranslate::trans(QString names)
{QString name =names; if(name.isEmpty()) { //调用dbus的相应方法,读取当前语言名称 QDBusMessage m = QDBusMessage::createMethodCall(SETTING_SERVICE_NAME, SETTING_OBJECT_PATH, SETTING_INTERFACE_NAME, "value"); m << "cn.cmos.settings.Locale" << "SYSTEM_LANGUAGE" << QVariant::fromValue(QDBusVariant("zh_CN")) ; QDBusReply<QDBusVariant> value = QDBusConnection::sessionBus().call(m); name = value.value().variant().toString(); } if(name.isEmpty()) { name = "zh_CN"; } QString fileName = m_name + "." + name; QString path = m_path; /**如果系统和程序都没有设置,则到默认路径下寻找翻译文件
-
如果应用程序存在,则默认路径为/usr/qm;
-
否则默认路径为/usr/share/library
*/ if(path.isEmpty()) { if(m_name == QApplication::applicationName()) { path = m_selfcmd + QDir::separator()
-
TRANSLATIONS_PATH + QDir::separator();
}
-
-
{
path = LIBRARY_PATH; } } qDebug()<<"当前语言名称:"<<name; qDebug()<<"翻译文件存放路径:"<<path; qDebug() << "翻译文件名称:"<<fileName; //安装翻译组件 m_translator.load(fileName , path); QApplication::installTranslator(&m_translator); //若系统没有设置语言,缺省为英文 if(name.isEmpty()) {
-
= "en_US";
} //向程序发出语言改变的信号,这是对dbus信号的封装
langChanged(name);
transflagChanged();
}-
CmosTranslate::readData(const QString &domain, const QString &key, const QDBusVariant &value)
{if(domain == DOMAIN_VALUE && key == KEY_VALUE){ QString name = value.variant().toString(); trans(name); }
}
-
CmosTranslate::appQuit()
{QDBusMessage m = QDBusMessage::createMethodCall("com.nomovok.skytree.compositor", "/Compositor", "com.nomovok.skytree.CompositorInterface", "appQuit"); m <<QVariant::fromValue<pid_t>(QCoreApplication::applicationPid()); QDBusReply<bool> back = QDBusConnection::systemBus().call(m); return back.value();
}
/静态方法
/
/**获取单实例
*@return 指向单实例的指针
*/
CmosTranslate *CmosTranslate::instance()
{
static CmosTranslate *instance = 0; if (!instance) { instance = new CmosTranslate; } return instance;
}
2、在主程序中增加组件
main.cpp文件
#include "CmosTranslate.h"
…… -
main(int argc, char *argv[]) {
……
QQmlEngine engine;
……
//向QML端添加组件engine.rootContext()->setContextProperty("cmostranslate", CmosTranslate::instance());
……
}3、在qml文件中响应该组件发出的信号
CancelButton.qml文件
-
QtQuick 2.0
//定义关机界面底部的“取消”按钮
Rectangle {id: cancelButton anchors.fill: parent Text { id:cancelLabel anchors.centerIn: parent font.pixelSize : 30 } //该控件的信号 signal languageChanged(string name) //该控件的相应信号的响应函数 onLanguageChanged: { translator() } //构造函数 Component.onCompleted: { // 连接组件信号和控件的槽 cmostranslate.langChanged.connect(cancelButton.languageChanged) // 调用组件函数初始化语言名称 cmostranslate.trans(); } //析构函数 Component.onDestruction: { //断开组件信号和控件槽 cmostranslate.langChanged.disconnect(cancelButton.languageChanged); } //翻译 function translator() { cancelLabel.text = qsTr("CANCEL") } }
4、修改pro文件,将CmosTranslate.h和CmosTranslate.cpp加入到编译选项中,以及设置qm文件的路径。此路径必须与CmosTranslate.cpp中设置的路径一致。为了防止修改时出现不一致的情况,可以略作改进。如:可以在某个配置文件中统一设置,其他文件获取该配置。
skytree-compositor.pro文件
……
HEADERS += CmosTranslate.h
SOURCES += CmosTranslate.cpp
……# translate
TARGET_DIR = /usr/share/translations
qm.path = $$TARGET_DIR
qm.files = *.qm
INSTALLS += qm5、修改spec文件。在spec文件中,将qm文件配置成安装时装载到指定路径。
此路径必须与CmosTranslate.cpp中设置的路径一致。为了防止修改时出现不一致的情况,可以略作改进。如:可以在某个配置文件中统一设置,其他文件获取该配置。skytree-compositor.spec文件
……
%files
/usr/share/translations/%{name}.zh_CN.qm
……6、生成qm文件。在应用程序根目录,即pro文件和spec文件所在的目录。用Qt的工具lupdate、linguist、lrelease 生成ts文件和qm文件。ts文件和qm文件的命名规则必须和CmosTranslate.cpp中设定的一致,否则会找不到文件,无法载入。本程序中命名规则为:程序名.语言名.后缀名。
$ lupdate . -ts skytree-compositor.zh_CN.ts
递归抓取程序中所有需要翻译的字符串。Ts文件内容:skytree-compositor.zh_CN.ts文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="zh_CN">
<context><name>CancelButton</name> <message> <location filename="shutdownscreen/CancelButton.qml" line="67"/> <source>CANCEL</source> <translation type="unfinished"></translation> </message>
</context>
</TS>$ linguist skytree-compositor.zh_CN.ts
将字符串翻译完成,保存退出。此时,ts文件内容有改变:skytree-compositor.zh_CN.ts文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="zh_CN">
<context><name>CancelButton</name> <message> <location filename="shutdownscreen/CancelButton.qml" line="67"/> <source>CANCEL</source> <translation type="unfinished">取消</translation> </message>
</context>
</TS>$ lrelease skytree-compositor.zh_CN.ts
将翻译好的ts文件生成qm文件。qm文件不是文本格式。
#endif // CmosTranslate_H
CmosTranslate.cpp文件
#include "CmosTranslate.h"
#include <QtDBus/QtDBus>
#include <QApplication>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。