黑暗模式
8. 多国语言互译
本章导读:
一款应用可能会有不同国家的人使用,为了让应用走向国际化的平台,一个框架可以提供多国语言互译就显得非常重要了。同一个应用要想在不同的国家显示该地的语言,只需要一个配置文件就可以完成,AWTK就提供了这样的功能。
8.1 简介
支持多国语言的存储(Unicode)和显示(字体)是GUI必需要做的,但字符串的翻译完全可以用gettext等第三方库函数来实现。AWTK之所以选择自己实现,主要出于以下几点考虑:
- 减少不必要的第三方库的依赖。运行时需要的代码也就几十行,自己实现更简单代码更少
- 方便支持实时切换当前语言。自己实现字符串的翻译,不要应用程序做额外的工作,即可实现实时切换当前语言
8.2 语言文件介绍
采用XML文件(UTF-8)保存字符串的各个语言的对应关系,方便程序员和翻译人员进行编辑,在AWTK中要实现多国语言互译需要编写strings.xml文件,并将该文件放到assets/default/raw/strings目录下,代码如下:
xml
<!-- awtk-examples/Chart-Demo/res_800_480/assets/default/raw/strings/strings.xml -->
...
<string name="main_title">
<language name="en_US">Chart Demo</language>
<language name="zh_CN">AWTK功能演示</language>
</string>
...
8.3 文本翻译
要实现多国语言互译,其步骤如下:
- 在应用程序中设置要翻译的文本。
- 编写strings.xml文件。
- C代码中调用locale_info_change函数实时切换语言。
- 调用脚本重新生成资源文件和重新编译应用程序。
具体的说明,请看以下章节。
8.3.1 设置需要翻译的文本
在AWTK中,有两种方式可以设置需要翻译的文本:XML方式和C代码方式,用户可以任选其中的一种,推荐使用XML方式。
1. XML方式
采用XML方式时,在编写UI界面时使用tr_text表示要翻译的文本。
下面以awtk-examples/Chart-Demo/bin/demo.exe中的主页面为例。例如,点击下图中右上角的"中"按钮,实现中英文切换。
在以下代码中 tr_text="main_title" 表示要翻译的文本:
xml
<!-- awtk-examples/Chart-Demo/res_800_480/assets/default/raw/ui/main.xml -->
<window anim_hint="htranslate" tr_text="main_title" style="main" x="0%" y="50" w="800" h="430" >
<image name="meter_image" x="30" y="57" w="180" h="318" clickable="true" />
<image name="pie_image" x="218" y="57" w="180" h="318" clickable="true" />
<image name="graph_image" x="406" y="57" w="180" h="318" clickable="true" />
<image name="histogram_image" x="594" y="57" w="180" h="318" clickable="true" />
<button name="meter" x="58" y="275" w="126" h="41" text="" style="main_meter"/>
<button name="pie" x="244" y="275" w="126" h="41" text="" style="main_pie"/>
<button name="window_line_series" x="433" y="275" w="126" h="41" text="" style="main_graph"/>
<button name="window_bar_series" x="620" y="275" w="126" h="41" text="" style="main_histogram"/>
</window>
2. C代码方式
采用C代码方式时,可以在应用程序的C代码中调用widget_set_tr_text函数设置要翻译的文本。
下面以awt/bin/demotr.exe为例,在以下代码中"ok"字符串表示要翻译的文本。
c
/* awtk/demos/demo_tr_app.c */
ret_t application_init() {
...
ok = button_create(win, 10, 5, 80, 30);
widget_set_tr_text(ok, "ok");
cancel = button_create(win, 100, 5, 80, 30);
widget_set_tr_text(cancel, "cancel");
...
return RET_OK;
}
8.3.2 编写strings.xml文件
要实现点击Chart-Demo界面右上角的"中"按钮,将中文 "AWTK功能演示" 翻译为 "Chart Demo",需要编写对应的strings.xml文件,代码详见8.3.1章节的第一小节。
8.3.3 实时切换语言
在应用程序中设置好了要翻译的文本后,需要在C代码中使用locale_info_change函数设置当前的国家和语言来实现实时切换语言,其中change_locale("zh_CN")函数中的传参是重新生成资源后的多国语言文件名,具体详见下文。示例代码如下:
c
/* awtk-examples/Chart-Demo/src/window_main.c */
static ret_t change_locale(const char* str) {
char country[3];
char language[3];
strncpy(language, str, 2);
strncpy(country, str + 3, 2);
locale_info_change(locale_info(), language, country);
return RET_OK;
}
static ret_t on_language(void* ctx, event_t* e) {
...
if (strstr(style, "zh") != NULL) {
widget_use_style(lang_btn, "language_en");
change_locale("en_US");
change_func(lang_btn, TRUE);
} else {
widget_use_style(lang_btn, "language_zh");
change_locale("zh_CN");
change_func(lang_btn, FALSE);
}
return RET_OK;
}
ret_t application_init(void) {
...
widget_t* sys_bar = window_open("system_bar");
if (sys_bar) {
change_locale("zh_CN");
widget_t* lang_btn = widget_lookup(sys_bar, "language_btn", TRUE);
widget_on(lang_btn, EVT_CLICK, on_language, sys_bar);
}
...
}
8.3.4 重新生成资源和编译应用程序
完成了上面步骤后,需要执行脚本重新生成资源,Windows平台执行assets_gen.bat脚本(Ubuntu平台执行assets_gen.sh),此处以Windows平台为例,在Chart-Demo目录下打开终端,执行以下命令:
bash
assets_gen.bat
资源生成成功后,将会根据strings.xml文件生成对应的语言文件:en_US.bin和zh_CN.bin,如下图所示:
重新生成资源后,就可以调用scons命令,编译应用程序了,在Chart-Demo目录下打开终端,执行以下命令:
bash
scons
8.3.5 重新设置缺省字体
此步骤非实现多国语言互译的必要步骤,只有出现下文提到的场景,才需要重新设置AWTK的缺省字体(AWTK中默认的缺省字体是default.ttf)。
在做切换多国语言的时候,在应用程序的界面上可能会出现不能正常显示某国语言的文字。上面提到Chart-Demo示例做中英文切换时候,在应用程序界面上能正常显示中文和英文。是因为res_xxx/assets/default/raw/fonts目录下的default.ttf字库中包含了中文和英文。如果default.ttf字库只包含中文,那么在切换为英文的时候,在Chart-Demo示例的界面上将不能正常显示英文,如果需要正常显示英文,其步骤如下:
步骤一:在res_xxx/assets/default/raw/fonts目录添加包含英文的字库文件(如:english.ttf)。
步骤二:重新生成资源文件。
步骤三:在切换英文时,在C代码中调用system_info_set_default_font()函数设置缺省字体为"english",代码如下:
c
/* Chart-Demo/src/window_main.c */
static ret_t on_language(void* ctx, event_t* e) {
...
if (strstr(style, "zh") != NULL) {
system_info_set_default_font(system_info(), "english");
widget_use_style(lang_btn, "language_en");
change_locale("en_US");
change_func(lang_btn, TRUE);
}
...
return RET_OK;
}
在多国语言互译中,调用system_info_set_default_font()函数设置缺省字体后,不要在控件的样式中设置font_name属性。如果设置了font_name属性,AWTK会根据font_name设置的值,寻找对应的字库,对于该控件调用system_info_set_default_font()函数就不会生效了。
8.4 图片翻译
在一些应用程序中,有些文字是直接绘制在图片上的。所以在切换到不同的语言时,需要加载不同的图片。这时只要在图片名称中包含"$locale$"即可,加载时自动替换成当前的语言。如:有两张图片language_en.png和language_zh.png分别用在英文和中文环境下,那么可以将在样式文件default.xml这样写:
xml
<button>
...
<style name="language_btn" >
<normal icon="language_$locale$" />
<pressed icon="language_$locale$"/>
<over icon="language_$locale$" />
<disable />
</style>
</button>
在英文环境下,加载图片时会按下列顺序查找(中文环境下也类似):
- flag_en_US
- flag_en
- flag_