分享我在编程中的设计观念,遇到的技术点,让我们在工作和生活中一起追求自由
这几年,自由的概念让我印象深刻,前不久看到一个词叫辞职自由。
别人在实现财务自由的时候,我在追求加班自由,架构让我们自由。
软件开发中的多语言
多语言也称作国际化支持,在企业级软件中,多国语言支持是必不可少的部分,我们的Qt项目,使用Qt Linguist实现多国语言显示。
我将从多语言Key定义、上下文、多语言Key收集、生成翻译文件几个方面,给大家介绍项目中Qt Linguist的工程化实现,它包含的组件如下图。
多语言Key定义
多语言Key是多种语言的标识,软件中通过此Key,转换成目标语言,通常多语言Key定义使用英文字符串表示。
项目中,首先需要在源码或ui等配置文件中,按照规则增加多语言Key。
源码中用tr定义多语言Key,也可以使用宏定义QT_TR_NOOP / QT_TRANSLATE_NOOP做前置标记。源码中,如果类不是QObject派生,可以使用QObject::tr静态函数,或Q_DECLARE_TR_FUNCTIONS()宏。
ui文件中,控件的caption会作为多语言Key,不需要额外处理。同时注意:ui中不要使用中文。
xml中不支持配置多语言Key,但测量、功能项等配置文件,涉及定义多语言Key的需求,后续我们会通过ScriptTool自定义规则,将xml中caption解析到h/cpp源码文件中,以支持多语言Key标记。
多语言上下文
源码中多语言Key定义时,当前的类名称作上下文;比如QObject::tr(“name”), QObject就是name的上下文。
在Qt中,同一个Key在不同上下文中翻译可以不同。
我们的软件超声软件项目中,定义了全局上下文,为“LTranslatorsDefine”;某些解析不到的Key,和配置文件解析的Key,我们使用LTranslatorsDefine作为上下文。
针对全局上下文的场景,我们做了特殊处理。
定义了从QObject派生的LTranslatorsDefine类,类中可以使用QT_TR_NOOP宏标记多语言Key,解析不到的Key,我们可以定义在此类中。同时,在系统初始化时,注册了自定义的QTranslator对象。
boolLLanguageManagerPrivate::loadLanguageMap(){ QCoreApplication::processEvents(); //多语言数据加载 QTranslator* qtTranslator = new QTranslator(q); LTranslatorDecorator* lmTranslator = new LTranslatorDecorator(qtTranslator, qtTranslator); boolb_ret = qtTranslator->load(currentLanguage, g_ufConfig->languagePath()); b_ret = b_ret&&QCoreApplication::installTranslator(lmTranslator); return b_ret;}
LTranslatorDecorator是系统默认QTranslator对象的“装饰者”,它的功能就是在系统默认QTranslator查找不到当前上下文时,去全局上下文LTranslatorsDefine中查找Key,像这样。
LTranslatorDecorator::LTranslatorDecorator(QTranslator* component, QObject *parent) : QTranslator(parent) , m_pComponent(component){ if(m_pComponent.isNull()) { qFatal("LTranslatorDecorator component is null."); }}QString LTranslatorDecorator::translate(const char *context, const char *sourceText, const char *disambiguation, int n) const{ QByteArrayList vContect = { context, "LTranslatorsDefine", }; QString transStr; for (auto con : vContect) { transStr = m_pComponent->translate(con.data(), sourceText, disambiguation, n); if (!transStr.isNull()) { break; } } return transStr;}
如果当前上下文、全局上下文都没有查询到翻译,则返回Key字符串作为显示字符。
多语言Key收集
多语言Key定义在ts文件中,项目时,通常需要同时收集多个工程的源码,使用lupdate可以满足这个需求。
我们写了个批处理脚本,调用Qt的lupdate生成ts文件,像这样。
set scan_path= ^ ./resource/ui ^ ./src/ultrasonicbusiness/src ^ ./src/ultrasonicui/src ^ ./src/base/src ^ ./src/product/srclupdate -disable-heuristic number -no-obsolete -no-ui-lines -extensions ui,c,cpp,h,qs,qml %scan_path% -ts resource/language/zh_CN.ts -target-language zh_CNlupdate -disable-heuristic number -no-obsolete -no-ui-lines -extensions ui,c,cpp,h,qs,qml %scan_path% -ts resource/language/en.ts -target-language en
多语言翻译
使用Qt语言家(linguist.exe )打开收集脚本生成的ts文件。
从左侧上下文列表中选择上下文,然后在字符串子窗口中选中翻译的Key,输入或者选择已有翻译,翻译确定后点击字符Key左侧更改翻译状态,接受翻译。
翻译修改完成后,选择文件->发布,生成qm文件,qm文件是多语言资源文件,也就是系统初始化QTranslator需要load的文件。
Qt语言家的使用,在Qt助手中搜索关键字:
Qt Linguist Manual: Translators
原则
Qt助手关键字:Writing Source Code for Translation
1、字符使用QString类型,支持UTF-8编码;
2、所有可显示标题,使用tr。