Qt国际化
来源:互联网 发布:淘宝店铺如何更换客服 编辑:程序博客网 时间:2024/05/01 04:58
嘿嘿,本文只是试图从纯C++的角度告诉你 Qt 的国际化是到底是怎么一回事(注:本文只看一个点,不看面)。而不会一步一步告诉你Qt的国际化/本地化怎么用(这些东西在Qt Manual、论坛 以及 相关书籍中介绍的够多了)。
Qt 国际化所做的就是这点东西:
- 首先,提取要翻译的字符串,手动翻译,生成一个qm文件,以备使用
- 其次,程序中使用QTranslator安装翻译文件
- 最后,tr函数去查找有没有对应的字符串,有则使用,
没有怎么办,就按照某种编码将参数窄字符串变成QString呗
至于动态翻译:点一下菜单,界面文字全改变,这在Qt中是相当容易实现的东西。
其实,根本就没有动态这回事。所谓的动态翻译,就是我们加载了一个新的翻译文件,然后将界面的文字用新的重新设置了一遍。
我们找个超简单的C++的小例子看看,并一步一步让它变的复杂一点点。
例子一
看一个 hello world 的例子:
- 为了稍后国际化,我们先用一个 tr 宏包住了所有要显示的字符串。
- 同样为了程序可以在所有平台下运行,我们的输出使用的是宽字符wchar_t
#include <iostream>#include <string>#include <locale.h>#define tr(X) L##Xint main(){ setlocale(LC_ALL, ""); std::wcout<<tr("hello")<<tr(" ")<<tr("world")<<std::endl; return 0;}
恩,编译运行,看到结果
hello world
例子二
如何翻译这个程序呢?
- 要有 翻译后的文字 吧
- 要使用 翻译后的文字 吧
- 要处理 没有翻译的文字 吧
词典?
源单词和目标单词的对应关系,我们就叫它词典好了。
- 创建3个全局的map,分别用来存在中文、日文、挪威文的翻译
- 创建一个辅助函数create_map和辅助变量dummy用来初始化这3个map
typedef std::map<std::string, std::wstring> Map;Map chinese;Map japanese;Map norwegian;int create_maps(){ chinese["hello"] = L"你好"; chinese["world"] = L"世界"; japanese["hello"] = L"こんにちは"; japanese["world"] = L"世界"; norwegian["hello"] = L"hallo"; norwegian["world"] = L"verden"; return 0;}int dummy = create_maps();
关联
有了翻译的内容,需要安装一下,让我们的程序知道翻译内容的存在吧?
Map * globalMap = 0;int main(){ setlocale(LC_ALL, ""); globalMap = & chinese; //install std::wcout<<tr("hello")<<tr(" ")<<tr("world")<<std::endl; return 0;}
使用
第一个例子中的宏可以丢掉了,我们写一个函数:
- 如果安装了词典,且存在翻译的内容,使用之
- 其他,将窄字符串用某种规则直接转成宽字符串
std::wstring tr(const char * text){ if (globalMap && globalMap->count(text)) { return (*globalMap)[text]; } wchar_t wcs[100]; mbstowcs(wcs, text, 99); return std::wstring(wcs);}
拼盘
将3部分合到一块:
#include <iostream>#include <string>#include <cstdlib>#include <map>#include <locale.h>typedef std::map<std::string, std::wstring> Map;Map chinese;Map japanese;Map norwegian;int create_maps(){ chinese["hello"] = L"你好"; chinese["world"] = L"世界"; japanese["hello"] = L"こんにちは"; japanese["world"] = L"世界"; norwegian["hello"] = L"hallo"; norwegian["world"] = L"verden"; return 0;}int dummy = create_maps();Map * globalMap = 0;std::wstring tr(const char * text){ if (globalMap && globalMap->count(text)) { return (*globalMap)[text]; } wchar_t wcs[100]; mbstowcs(wcs, text, 99); return std::wstring(wcs);}//#define tr(X) L##Xint main(){ setlocale(LC_ALL, ""); globalMap = & chinese; std::wcout<<tr("hello")<<tr(" ")<<tr("world")<<std::endl; return 0;}
看看运行结果:
你好 世界
对比Qt
Qt 又做了什么呢?
Qt
我们的例子
lupdate/lrelease/...
Map/Map/Map
生成翻译/词典文件
QTranslator
globalMap
安装翻译文件
QObject::tr()
QCoreApplication::translate()
tr()
使用翻译文件
从根本上说,Qt 国际化所做的就是这点东西:
- 首先,提取要翻译的字符串,手动翻译,生成一个qm文件,以备使用
- 其次,程序中使用QTranslator安装翻译文件
- 最后,tr函数去查找有没有对应的字符串,有则使用,
没有怎么办,就按照某种编码将参数窄字符串变成QString呗?
注意,tr就是一个将 const char * 变成 QString 的函数:
QString QObject::tr ( const char * sourceText,...)
对于tr,我们在Qt中translate、tr关系 与中文问题 有了比较详细的讨论,此处就不重复了。
Qt动态翻译
点一下菜单,界面文字全改变,这在Qt中是相当容易实现的东西。也就是大家所说的动态翻译。
其实,根本就没有动态这回事。所谓的动态翻译,就是我们加载了一个新的翻译文件,然后将界面的文字用新的重新设置了一遍。
考虑我们前面的例子,稍微改改:
int main(){ setlocale(LC_ALL, ""); std::wstring welcome = tr("hello"); //1st globalMap = & chinese; welcome = tr("hello"); //2nd globalMap = & japanese; welcome = tr("hello"); //3rd return 0;}
尽管都是用tr,但3处 welcome 的内容却不相同,动态翻译也就是这回事。
- 一个button的文字如何改变? 通过 setText
在button上,"hello" ==> "你好" 是改变么? 显然,于是这个过程需要setText
这也是为什么,uic生成的代码 ui_xxx.h 中始终有:
void retranslateUi(QDialog *Dialog) { Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", 0, QApplication::UnicodeUTF8)); groupBox->setTitle(QApplication::translate("Dialog", "GroupBox", 0, QApplication::UnicodeUTF8)); } // retranslateUi
这种函数存在的原因。
当你安装了新的翻译文件以后,只需要重新调用一遍这个函数就行了。
但你安装新的翻译文件后,应用程序会给各个窗口发送一个事件,此时,是调用上述函数的最佳时机
void MainWindow::changeEvent(QEvent *e){ QMainWindow::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; }}
大家对这个函数应该都不陌生,毕竟,Qt Creator会自动为你生成它。不管你到底用还是不用。
- qt国际化
- Qt 国际化
- qt国际化
- Qt国际化
- Qt国际化
- QT国际化
- QT国际化
- Qt国际化
- Qt国际化
- QT国际化
- qt国际化
- QT 国际化
- Qt国际化
- qt 国际化
- qt 国际化
- Qt 国际化
- Qt国际化
- QT 国际化
- 智能交易的特性
- 关于面向对象编程
- JdbcTemplate - 查询
- 多线程环境下当心C#的匿名委托
- 利用javascript写一个简单的计算器
- Qt国际化
- 活动图(Activity Diagram)—UML图(四)
- android Activity类的runOnUiThread
- 敏捷开发绩效管理之四:为团队设立外部绩效目标(目标管理,外向型绩效)
- copy详细讲解
- linux下history命令的使用方法
- DotSpatial初步
- 解题笔记(26)——排队问题
- loadrunner结果分析中的指标解释