# 8. 多国语言互译

本章导读:

一款应用可能会有不同国家的人使用,为了让应用走向国际化的平台,一个框架可以提供多国语言互译就显得非常重要了。同一个应用要想在不同的国家显示该地的语言,只需要一个配置文件就可以完成,AWTK就提供了这样的功能。

# 8.1 简介

支持多国语言的存储(Unicode)和显示(字体)是GUI必需要做的,但字符串的翻译完全可以用gettext等第三方库函数来实现。AWTK之所以选择自己实现,主要出于以下几点考虑:

  • 减少不必要的第三方库的依赖。运行时需要的代码也就几十行,自己实现更简单代码更少
  • 方便支持实时切换当前语言。自己实现字符串的翻译,不要应用程序做额外的工作,即可实现实时切换当前语言

# 8.2 语言文件介绍

采用XML文件(UTF-8)保存字符串的各个语言的对应关系,方便程序员和翻译人员进行编辑,在AWTK中要实现多国语言互译需要编写strings.xml文件,并将该文件放到assets/default/raw/strings目录下,代码如下:

<!-- 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 文本翻译

要实现多国语言互译,其步骤如下:

  1. 在应用程序中设置要翻译的文本。
  2. 编写strings.xml文件。
  3. C代码中调用locale_info_change函数实时切换语言。
  4. 调用脚本重新生成资源文件和重新编译应用程序。

具体的说明,请看以下章节。

# 8.3.1 设置需要翻译的文本

在AWTK中,有两种方式可以设置需要翻译的文本:XML方式和C代码方式,用户可以任选其中的一种,推荐使用XML方式。

1. XML方式

采用XML方式时,在编写UI界面时使用tr_text表示要翻译的文本。

下面以awtk-examples/Chart-Demo/bin/demo.exe中的主页面为例。例如,点击下图中右上角的"中"按钮,实现中英文切换。

图8.1 Chart-Demo
图8.1 Chart-Demo

在以下代码中 tr_text="main_title" 表示要翻译的文本:

<!-- 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"字符串表示要翻译的文本。

/* 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")函数中的传参是重新生成资源后的多国语言文件名,具体详见下文。示例代码如下:

/* 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目录下打开终端,执行以下命令:

assets_gen.bat

资源生成成功后,将会根据strings.xml文件生成对应的语言文件:en_US.bin和zh_CN.bin,如下图所示:

图8.2 多国语言文件
图8.2 多国语言文件

重新生成资源后,就可以调用scons命令,编译应用程序了,在Chart-Demo目录下打开终端,执行以下命令:

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",代码如下:

/* 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这样写:

<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_