QT 国际化扩展所感 an extending QT Translator (自己实现翻译逻辑,编辑更方便)
来源:互联网 发布:亚投行 日本 知乎 编辑:程序博客网 时间:2024/06/06 08:24
QT中提供了支持国际化的QTranslator, 这一工具确实很方便实现简单而且功能丰富的国际化功能,但是如何自己实现自定义的国家化翻译工具呢,如何通过file-driven来实现翻译工具呢?
相比大家知道,我在上篇文章中提到了关于如何使用QTranslator的心得和建议。通过lupdate,linguist,lrelease来对代码中我们标定的tr()字符来进行翻译。
转载请注明出处: http://blog.csdn.net/elfprincexu
总结下来就是:
- surround all literal strings (the ones to be translated) with tr() functions, i.e. tr("This will be translated");
- use lupdate command to extract translatable text into translation files (.ts)
- translate the text files by means of Qt Linguist (since .ts files are actually XML files, they can even be edited with any text editor)
- use lrelease command to transform the translated .ts files (text) into a binary representation format (.qm) files
具体参考我的上一篇文章: 个人亲测: QT Translate 国际化和本地化的一些使用心得和注意点 http://blog.csdn.net/elfprincexu/article/details/37698129
我想大部分代码工作者都会这么做,确实,但是当你不断想增加一些翻译资料,你就不得不反复的重复上述的步骤。
这里我提供一个基于文件的翻译机制给大家分享一下:
首先,我们定义XML文件来用于存储或者编辑将来要用到的翻译资料:
文件名可以类似 translations_en_US.trn
<translations locale="es_ES"> <entry Id="save">Guardar</entry> <entry Id="save_as">Guardar como</entry> <entry Id="open">Abrir</entry> <entry Id="exit">Salir</entry> <entry Id="error_network">Error de la red</entry></translations>
其次,我们需要一个类来对这些文件进行阅读并且解析他们。
loadFile() 用来加载我们上面的翻译文件;
parseXml() 用来解析我们的翻译文件;
_mapDefaultLocal 默认的备用的翻译key-value信息。
_mapCurrentLocal 真正装载的本地化信息。
我们定义一个类,Mytranslator, 用来实现我们的功能,具体代码如下:
头文件:
typedef QMap<QString,QString> LocalMap; class MyTranslator //inner class { public : MyTranslator(); virtual ~MyTranslator(); QString translate(const QString &sourceText) const; bool loadFile(const QString &filename, const QString &locale, const QString &suffix=".trn"); bool parseXml(const QString&filename, const QString& locale, const QString& suffix, LocalMap &mapLocale); LocalMap _mapDefaultLocal; LocalMap _mapCurrentLocal; QString _sCurrentLocal; };
实现文件:
MyTranslator::MyTranslator() : _sCurrentLocal(""){ _mapCurrentLocal.clear(); //initialization empty _mapDefaultLocal.clear(); //initialization empty}MyTranslator::~MyTranslator(){}bool MyTranslator::loadFile(const QString &filename, const QString &locale, const QString &suffix){ bool bLoadOk = false; if (_sCurrentLocal != locale); { //while loading a new locale, clear the maps _mapCurrentLocal.clear(); _mapDefaultLocal.clear(); } // first , load default local en_us parseXml(filename,"en_US",suffix, _mapDefaultLocal); // as a backup data if _mapCurrentLocal not contains such data, double safe //second, parse the correct locale file bLoadOk = parseXml(filename,locale,suffix,_mapCurrentLocal); if (bLoadOk) { //we did it, so we change _sCurrentLocal = locale; qDebug()<<"UserLoginDlg::MyTranslator::loadFile: :"<< bLoadOk ; } return bLoadOk;}bool MyTranslator::parseXml(const QString &filename, const QString &locale, const QString &suffix, LocalMap &mapLocale){ QXmlStreamReader xml; QString realname = filename + locale + (suffix.isNull()? QString::fromLatin1(".trn"): suffix); Str completeFileName = SlxHomeDir().etcFile(qPrintable(realname)); //put them into etc folder; qDebug()<<"UserLoginDlg::MyTranslator::parseXml: completeFileName :"<< completeFileName.c_str() ; QFile file(completeFileName.c_str()); bool bSuccess = file.open(QFile::ReadOnly); if (bSuccess) { xml.addData(file.readAll()); QString key; while(!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (xml.name() == "translations") { if (xml.attributes().value("locale").toString() != locale) { qDebug()<<"UserLoginDlg::MyTranslator::parseXml: parse error :"<< xml.attributes().value("locale").toString() << "not match with "<< locale; bSuccess = false; break; } } else if (xml.name() == "entry") { key = xml.attributes().value("Id").toString(); mapLocale[key] = xml.readElementText(); } } if (xml.hasError()) // for some negative errors (like xml not well formed). need to carefully handle, remove the tmp file and return false { qDebug()<<"UserLoginDlg::MyTranslator::parseXml: file : "<< completeFileName.c_str() <<" ,read error: [erroString :"<< xml.errorString()<<"],[lineNumber :" << xml.lineNumber()<<"],[columNumber :"<<xml.columnNumber()<<"]"; file.close(); return false; } } } else { qDebug()<<"UserLoginDlg::MyTranslator::parseXml: Failed to open file"<< file.fileName() << file.errorString(); } return bSuccess;}QString UserLoginDlg::MyTranslator::translate(const QString &sourceText) const{ QString translation; //default empty translation = _mapCurrentLocal.value(sourceText); if (translation.isEmpty()) { //not found in the currrent language translation = _mapDefaultLocal.value(sourceText); if (translation.isEmpty()) { //still not found! show the sourceText translation = sourceText; } } //qDebug()<<"UserLoginDlg::MyTranslator::translate: return "<< translation; return translation;}
void UserLoginDlg::languageCBoxChange(){ qDebug()<<"UserLoginDlg::languageCBoxChange() : current language" << _userLoginUI._languageCBox->currentText(); if ((!_displayReasonsBox) || (!_translator)) { cerr<<"UserLoginDlg::languageCBoxChange() :_displayReasonsBox false or translator null, shouldn't happen"<<endl; return; } if (_userLoginUI._languageCBox->currentIndex() == 0 ) //english { bool loadResult = _translator->loadFile("translations_", "en_US"); this->translateLanguage(); cout<<"UserLoginDlg::languageCBoxChange() :loadResult : translations_en_US.trn " << loadResult <<endl; } else if (_userLoginUI._languageCBox->currentIndex() == 1) //chinese { bool loadResult = _translator->loadFile("translations_", "cn_CHN"); this->translateLanguage(); cout<<"UserLoginDlg::languageCBoxChange() :loadResult : translations_cn_CHN.trn " << loadResult <<endl; } else if (_userLoginUI._languageCBox->currentIndex() == 2) //korean { bool loadResult = _translator->loadFile("translations_", "kor_KOR"); this->translateLanguage(); cout<<"UserLoginDlg::languageCBoxChange() :loadResult : translations_kor_KOR.trn " << loadResult <<endl; } else if (_userLoginUI._languageCBox->currentIndex() == 3) // japnese { bool loadResult = _translator->loadFile("translations_", "jpn_JPN"); this->translateLanguage(); cout<<"UserLoginDlg::languageCBoxChange() :loadResult : translations_jpn_JPN.trn " << loadResult <<endl; } else // if above not satisfied, show english { bool loadResult = _translator->loadFile("translations_","en_US"); this->translateLanguage(); cout<<"UserLoginDlg::languageCBoxChange() :loadResult : translations_en_US.trn " << loadResult <<endl; }}
void UserLoginDlg::translateLanguage(){ if (_displayReasonsBox && _translator && !_totalReasonsList.isEmpty()) { qDebug()<<"UserLoginDlg::translateLanguage() entered"; for (int i=0; i<_totalReasonsList.size();i++) { _userLoginUI._reasonCombo->setItemText(i, _translator->translate(_totalReasonsList.at(i))); } }}
好吧,大家现学现用吧,具体逻辑是:
loadFile()你预先编辑好的xml文件。
对要翻译的地方,使用
_translator->translate(_totalReasonsList.at(i)) 来寻找对应的翻译结果进行显示。
编辑方便,只要往xml文件中增加相应的翻译key-value就可以了。程序中如果要添加翻译的组件显示,同样可以采用相同的逻辑。
0 0
- QT 国际化扩展所感 an extending QT Translator (自己实现翻译逻辑,编辑更方便)
- Qt 更新翻译(国际化)
- qt国际化翻译
- QT国际化翻译的使用
- Qt国际化翻译文件不起作用
- Qt国际化翻译小Demo
- Qt翻译文件结合VS实现语言切换(多语言国际化)
- Qt国际化之翻译(VS2013+Qt5.4.1)
- qt 翻译 语言家 国际化的使用
- Qt 国际化 (转)
- QT国际化(i18n)
- Qt国际化(3)——一些提示 Qt翻译问题
- qt国际化
- Qt 国际化
- qt国际化
- Qt国际化
- Qt国际化
- QT国际化
- PPTP、L2TP、IPSec和SSL VPN 的区别
- Edit Distance @leetcode
- CentOS x86_64上编译32位demo程序
- Linux字符设备与块设备的区别与比较
- 浙江一副县长辞官 辞职感言:可以长长地舒口气了
- QT 国际化扩展所感 an extending QT Translator (自己实现翻译逻辑,编辑更方便)
- wordpress作者的相关函数调用代码
- gdb: value optimized out
- java集合类HashMap获取键和值
- 拷贝构造函数和赋值函数
- hdu1754
- 只是来报个到
- JSTL 标签获得jsp页面上定义的变量
- Nandflash和norflash的区别