最近又有朋友问我duilib多语言的支持,干脆做个demo,顺便简单写个介绍,仅供参考,有更好的方案也欢迎交流。
demo地址:https://github.com/juhuaguai/duilib/tree/master/MultiLanguagDemo
上图是demo的效果,不用重启应用程序,直接切换,界面直接就更新了。
原理就是依赖于duilib里PaintManager里面的多语言接口。核心是%{i},i是整型,可以认为是ID。
1.设置控件的文本内容为%{0};
2.通过CPaintManagerUI::AddMultiLanguageString(0,L"多语言演示")接口添加id为0时对应的字符串。
3.程序在DrawText的时候会通过CPaintManagerUI::ProcessMultiLanguageTokens将%{0}转换为多语言演示,然后进行绘制。这个过程在duilib的CRenderEngine和部分控件的paintText中自动进行了。
4.CPaintManagerUI::AddMultiLanguageString中会对同一个id进行覆盖。因此动态调用CPaintManagerUI::AddMultiLanguageString(0,L"MutilLanguage Demo"),就实现动态切换语言了。
5.在程序其他地方如果需要获取id对应的文本,可以直接调用CPaintManagerUI::GetMultiLanguageString函数,比如做个Messagebox,显示内容想动态根据语言去调整,那么可以wstring strValue = CPaintManagerUI::GetMultiLanguageString(0);然后Messagebox(Null,strValue.c_str());这样的。
实际上为了方便管理和使用,我们可以做一些整理。比如demo里面是这样做的
1.将id与文本的对应形成Json格式。想每种语言放一个文件,可以这样
[
{
"id":0,
"txt":"多语言演示"
},
{
"id":1,
"txt":"日语演示"
},
{
"id":2,
"txt":"这是个按钮"
}
]
命名为zh.json文件。
[
{
"id":0,
"txt":"多言語プレゼンテーション"
},
{
"id":1,
"txt":"日本語プレゼンテーション"
},
{
"id":2,
"txt":"これはボタンです"
}
]
命名为jp.json文件。
想所有语言放一个文件,可以这样
[
{
"id":0,
"zh":"多语言演示",
"en":"MutilLanguage Demo",
"jp":"多言語プレゼンテーション"
},
{
"id":1,
"zh":"日语演示",
"en":"Japanese presentation",
"jp":"日本語プレゼンテーション"
},
{
"id":2,
"zh":"这是个按钮",
"en":"This is a Button",
"jp":"これはボタンです"
}
]
2.动态切换语言时,对于每种语言一个json文件的,自然是根据目标语言找对应的json文件,然后解析Josn循环调用CPaintManagerUI::AddMultiLanguageString。
对于所有语言放一个json文件的,同样是解析json,然后去循环调用CPaintManagerUI::AddMultiLanguageString,添加对应的key的value。
demo演示的是每种语言一个文件,但更推荐所有语言放一个文件,更加方便增删改查。
3.循环调用CPaintManagerUI::AddMultiLanguageString更新完id对应的语言后,通常再调用一次m_PM.GetRoot()->NeedUpdate();来让界面刷新一下,这样文本在重新绘制的时候就变成id对应的新的字符串了。
控件文本是支持"程序:%{0}"这样的混用的,绘制时会自动变为"程序:多语言演示"。更多用法和玩法可以自行探索。原理就是这样。
demo是vs2017工程,主要是新的json库对vs版本有要求。代码比较简单,直接看源码不编译也行。其他文件比如stringtools.h这些,在这个仓库的其他位置,代码中都可以看到。