MaixCDK 国际化(i18n)与多语言支持

你可以使用任何喜欢的国际化库,例如 gettext,它支持 Python 和 C++。

此外,我们还提供了一个简单的 i18n 库,适用于简单的使用场景。

针对 MaixPy

请参阅 MaixPy 国际化文档

针对 MaixCDK

与 MaixPy 相同,有两种方法可以使用:

简单的翻译字典

首先确保你的源文件编码为 UTF-8

#include "maix_i18n.hpp"

const std::map<string, string> locale_zh_dict = {
    {"out", "输出"},
    {"hello", "你好"}
};

const std::map<string, string> locale_ja_dict = {
    // {"out", "出力"},
    {"hello", "こんにちは"}
};

const std::map<string, const std::map<string, string>> locales_dict = {
    {"zh", locale_zh_dict},
    {"ja", locale_ja_dict}
};

i18n::Trans trans(locales_dict);

int main()
{
    log::info("系统语言: %s\n", i18n::get_locale().c_str());
    log::info("%s: %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

    trans.set_locale("zh");
    printf("%s: %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

    trans.set_locale("en");
    printf("%s: %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

    trans.set_locale("ja");
    printf("%s: %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

    return 0;
}

分离的翻译文件

上面的示例适用于少量翻译字符串。如果需要翻译大量字符串,推荐使用此方法:

  • 不需要修改源代码即可更换翻译内容,翻译字符串保存在独立的 yaml 文件中。
  • 更容易定位翻译字符串,支持自动扫描需要翻译的字符串,并自动生成 yaml 文件。
err::Err e = trans.load("locales"); // 从 locales 目录加载翻译文件
err::check_raise(e, "加载翻译 yaml 文件失败");

log::info("系统语言: %s\n", i18n::get_locale().c_str());
log::info("%s: %s, %s\n", i18n::get_locale().c_str(), trans.tr("out").c_str(), trans.tr("hello").c_str());

trans.set_locale("zh");
log::info("zh: %s, %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

trans.set_locale("en");
log::info("en: %s, %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

trans.set_locale("ja");
log::info("ja: %s, %s\n", trans.tr("out").c_str(), trans.tr("hello").c_str());

完整示例请参见 examples/i18n

然后执行 maixtool i18n -d . r,这将扫描所有使用 tr()_() 的翻译字符串,生成 locales 目录和翻译文件。手动翻译 locales 中的 yaml 文件后,将其放置在程序旁边并运行。

在 LVGL 应用中显示国际化字体

查看如何显示自定义字体:https://neucrack.com/p/514

使用以下代码:

LV_FONT_DECLARE(zh_fonts);

static const std::map<string, void*> fonts = {
    {"zh", (void*)&zh_fonts}
};

const lv_font_t *get_font_by_locale(const string &locale)
{
    const std::map<string, void*>::const_iterator iter = fonts.find(locale);
    if (iter == fonts.end())
    {
        return &zh_fonts;
    }
    return (lv_font_t *)iter->second;
}

最后,使用国际化字体:

std::string locale = i18n::get_locale();

lv_obj_set_style_text_font(lv_scr_act(), get_font_by_locale(locale), LV_PART_MAIN);

lv_obj_t *label = lv_label_create(lv_scr_act());
lv_label_set_text(label, trans.tr("hello").c_str());