Chapter 194 · XUI 高级机制

国际化

XUI 多语言支持:Language 创建、text_id 映射、运行时切换、Fallback 链。

194

概念

XUI 国际化(i18n)系统:
• Language:语言对象,包含语言代码/名称/Fallback
• text_id:预定义文本 ID 枚举(按钮确定/取消/菜单项等)
• SetText:为指定语言设置 text_id 对应的翻译文本
• SetLanguage:运行时切换当前语言,所有控件自动更新
• Fallback:缺失翻译时回退到父语言(通常英语)

API 速查

函数说明
int xuiSetLanguage(pCtx, iLanguageId)切换当前语言
xui_language xuiCreateLanguage(pCtx, sCode, sName, iFallback)创建语言
int xuiLanguageSetText(pCtx, pLang, iTextId, sText)设置翻译
void xuiLanguageTouch(pCtx, pLang)标记语言已修改

编译本章示例

gcc -O2 -I. -o ch194.exe ch194_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch194.exe

示例:中英双语切换

// 创建中文语言(Fallback 到英语)
xui_language pZh = xuiCreateLanguage(pCtx,
    "zh-CN", "简体中文", XUI_LANGUAGE_EN);

// 设置翻译文本(文本槽 id 为应用自定义枚举)
enum { TXT_OK, TXT_CANCEL, TXT_YES, TXT_NO, TXT_CLOSE };
xuiLanguageSetText(pCtx, pZh,
    TXT_OK, "确定");
xuiLanguageSetText(pCtx, pZh,
    TXT_CANCEL, "取消");
xuiLanguageSetText(pCtx, pZh,
    TXT_YES, "是");
xuiLanguageSetText(pCtx, pZh,
    TXT_NO, "否");
xuiLanguageSetText(pCtx, pZh,
    TXT_CLOSE, "关闭");

// 标记语言数据已更新
xuiLanguageTouch(pCtx, pZh);

// 运行时切换到中文
xuiSetLanguage(pCtx, pZh);
// 所有使用 text_id 的控件自动显示中文

完整代码

将以下代码保存为 ch194_main.c,编译后运行即可看到中英双语实时切换效果:

#include "xge.h"
#include "xui.h"

static xui_context g_pCtx;
static xui_language g_pZh;
static int g_bZh = 0;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x1a1a2e);
    xui_vec2_t pos;
    xgeMouseGet(&pos.x, &pos.y);
    xuiInputPointerMove(g_pCtx, pos.x, pos.y);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
    else
        xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

static void onToggle(xui_widget pW, void* pUser) {
    (void)pW; (void)pUser;
    g_bZh = !g_bZh;
    if (g_bZh)
        xuiSetLanguage(g_pCtx, g_pZh);
    else
        xuiSetLanguage(g_pCtx, NULL); /* 回退默认英语 */
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth = 640; d.iHeight = 480;
    d.sTitle = "ch194 - i18n";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);
    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 640, 480);

    /* 创建中文语言 */
    g_pZh = xuiCreateLanguage(g_pCtx, "zh-CN", "\xe7\xae\x80\xe4\xbd\x93\xe4\xb8\xad\xe6\x96\x87", XUI_LANGUAGE_EN);
    xuiLanguageSetText(g_pCtx, g_pZh, TXT_OK, "\xe7\xa1\xae\xe5\xae\x9a");
    xuiLanguageSetText(g_pCtx, g_pZh, TXT_CANCEL, "\xe5\x8f\x96\xe6\xb6\x88");
    xuiLanguageSetText(g_pCtx, g_pZh, TXT_CLOSE, "\xe5\x85\xb3\xe9\x97\xad");
    xuiLanguageTouch(g_pCtx, g_pZh);

    xui_widget pRoot;
xuiPanelCreate(g_pCtx, &pRoot, NULL);
    xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 640, 480});

    xui_widget pBtn;
xuiButtonCreate(g_pCtx, &pBtn, NULL);
xuiWidgetAddChild(pRoot, pBtn);
    xuiLabelSetText(pBtn, "Toggle Language");
    xuiWidgetSetRect(pBtn, (xui_rect_t){240, 180, 160, 48});
    xuiWidgetSetRect(pBtn, (xui_rect_t){0, 0, 160, 48});
    xuiWidgetSetEventCallback(pBtn, onToggle, NULL);

    xui_widget pHint;
xuiLabelCreate(g_pCtx, &pHint, NULL);
xuiWidgetAddChild(pRoot, pHint);
    xuiLabelSetText(pHint, "Click to switch zh/en");
    xuiWidgetSetRect(pHint, (xui_rect_t){220, 260, 200, 32});
    xuiWidgetSetRect(pHint, (xui_rect_t){0, 0, 200, 32});

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • 创建语言:xuiCreateLanguage 注册 zh-CN 并指定 Fallback 为英语,未翻译项自动回退。
  • 设置翻译:xuiLanguageSetText 按 text_id 设置对应翻译文本。
  • Touch 标记:修改翻译后必须调用 xuiLanguageTouch,否则控件不会刷新。
  • 运行时切换:点击按钮调用 xuiSetLanguage 切换语言,所有控件自动更新显示。

要点与陷阱

  • text_id:使用预定义枚举(TXT_OK 等),不要硬编码字符串。
  • Fallback:未翻译的 text_id 自动回退到 Fallback 语言。
  • Touch:修改翻译后必须调用 Touch,否则控件不会刷新。
  • 切换:SetLanguage 触发全局脏标记,所有控件重新渲染。

进阶练习

  1. 三语切换:中/英/日 ComboBox 选择,实时切换界面语言。
  2. 外部翻译文件:从 JSON/CSV 加载翻译表批量 SetText。
国际化效果
图:国际化渲染效果