mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 21:44:39 +08:00
i18n: cycle help language with one key
This commit is contained in:
parent
f2942e9c9e
commit
155e535b8a
9 changed files with 31 additions and 12 deletions
|
|
@ -46,6 +46,8 @@
|
||||||
- Language selection is limited to stable codes (`en`, `zh`) and
|
- Language selection is limited to stable codes (`en`, `zh`) and
|
||||||
locale-shaped environment values; natural-language labels are not accepted
|
locale-shaped environment values; natural-language labels are not accepted
|
||||||
as command arguments.
|
as command arguments.
|
||||||
|
- Full-screen help now uses `l` to cycle the UI language through the i18n
|
||||||
|
module instead of hard-coding one key per language.
|
||||||
- Documented i18n and user-facing text rules for English-first source text,
|
- Documented i18n and user-facing text rules for English-first source text,
|
||||||
stable command syntax, concise help copy, and translation-only localization.
|
stable command syntax, concise help copy, and translation-only localization.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ typedef enum {
|
||||||
bool i18n_try_parse_ui_lang(const char *value, ui_lang_t *lang);
|
bool i18n_try_parse_ui_lang(const char *value, ui_lang_t *lang);
|
||||||
ui_lang_t i18n_parse_ui_lang(const char *value, ui_lang_t fallback);
|
ui_lang_t i18n_parse_ui_lang(const char *value, ui_lang_t fallback);
|
||||||
ui_lang_t i18n_default_ui_lang(void);
|
ui_lang_t i18n_default_ui_lang(void);
|
||||||
|
ui_lang_t i18n_next_ui_lang(ui_lang_t lang);
|
||||||
const char *i18n_ui_lang_code(ui_lang_t lang);
|
const char *i18n_ui_lang_code(ui_lang_t lang);
|
||||||
const char *i18n_text(ui_lang_t lang, i18n_text_id_t id);
|
const char *i18n_text(ui_lang_t lang, i18n_text_id_t id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ void help_text_append_full(char *buffer, size_t buf_size, size_t *pos,
|
||||||
" Ctrl+D/U - Scroll half page down/up\n"
|
" Ctrl+D/U - Scroll half page down/up\n"
|
||||||
" Ctrl+F/B - Scroll full page down/up\n"
|
" Ctrl+F/B - Scroll full page down/up\n"
|
||||||
" g/G - Jump to top/bottom\n"
|
" g/G - Jump to top/bottom\n"
|
||||||
" e/z - Switch English/Chinese\n");
|
" l - Cycle UI language\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,5 +111,5 @@ void help_text_append_full(char *buffer, size_t buf_size, size_t *pos,
|
||||||
" Ctrl+D/U - 向下/上滚动半页\n"
|
" Ctrl+D/U - 向下/上滚动半页\n"
|
||||||
" Ctrl+F/B - 向下/上滚动整页\n"
|
" Ctrl+F/B - 向下/上滚动整页\n"
|
||||||
" g/G - 跳到顶部/底部\n"
|
" g/G - 跳到顶部/底部\n"
|
||||||
" e/z - 切换英文/中文\n");
|
" l - 切换界面语言\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@ ui_lang_t i18n_default_ui_lang(void) {
|
||||||
return i18n_parse_ui_lang(locale, UI_LANG_EN);
|
return i18n_parse_ui_lang(locale, UI_LANG_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui_lang_t i18n_next_ui_lang(ui_lang_t lang) {
|
||||||
|
return lang == UI_LANG_EN ? UI_LANG_ZH : UI_LANG_EN;
|
||||||
|
}
|
||||||
|
|
||||||
const char *i18n_ui_lang_code(ui_lang_t lang) {
|
const char *i18n_ui_lang_code(ui_lang_t lang) {
|
||||||
return lang == UI_LANG_ZH ? "zh" : "en";
|
return lang == UI_LANG_ZH ? "zh" : "en";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ static const i18n_text_entry_t text_catalog[I18N_TEXT_COUNT] = {
|
||||||
" 按键 "
|
" 按键 "
|
||||||
},
|
},
|
||||||
[I18N_HELP_STATUS_FORMAT] = {
|
[I18N_HELP_STATUS_FORMAT] = {
|
||||||
"-- KEY REFERENCE -- (%d/%d) j/k:scroll g/G:top/bottom e/z:lang q:close",
|
"-- KEY REFERENCE -- (%d/%d) j/k:scroll g/G:top/bottom l:lang q:close",
|
||||||
"-- 按键参考 -- (%d/%d) j/k:滚动 g/G:首尾 e/z:语言 q:关闭"
|
"-- 按键参考 -- (%d/%d) j/k:滚动 g/G:首尾 l:语言 q:关闭"
|
||||||
},
|
},
|
||||||
[I18N_COMMAND_OUTPUT_TITLE] = {
|
[I18N_COMMAND_OUTPUT_TITLE] = {
|
||||||
" COMMAND OUTPUT ",
|
" COMMAND OUTPUT ",
|
||||||
|
|
|
||||||
|
|
@ -257,12 +257,8 @@ static bool handle_key(client_t *client, unsigned char key, char *input) {
|
||||||
if (key == 'q' || key == 27) {
|
if (key == 'q' || key == 27) {
|
||||||
client->show_help = false;
|
client->show_help = false;
|
||||||
tui_render_screen(client);
|
tui_render_screen(client);
|
||||||
} else if (key == 'e' || key == 'E') {
|
} else if (key == 'l' || key == 'L') {
|
||||||
client->ui_lang = UI_LANG_EN;
|
client->ui_lang = i18n_next_ui_lang(client->ui_lang);
|
||||||
client->help_scroll_pos = 0;
|
|
||||||
tui_render_help(client);
|
|
||||||
} else if (key == 'z' || key == 'Z') {
|
|
||||||
client->ui_lang = UI_LANG_ZH;
|
|
||||||
client->help_scroll_pos = 0;
|
client->help_scroll_pos = 0;
|
||||||
tui_render_help(client);
|
tui_render_help(client);
|
||||||
} else if (key == 'j') {
|
} else if (key == 'j') {
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,14 @@ expect "TNT\\(1\\) 帮助"
|
||||||
expect "q:关闭"
|
expect "q:关闭"
|
||||||
send -- "q"
|
send -- "q"
|
||||||
expect "NORMAL"
|
expect "NORMAL"
|
||||||
|
send -- "?"
|
||||||
|
expect "TNT 按键参考"
|
||||||
|
expect "l:语言"
|
||||||
|
send -- "l"
|
||||||
|
expect "TNT KEY REFERENCE"
|
||||||
|
expect "l:lang"
|
||||||
|
send -- "q"
|
||||||
|
expect "NORMAL"
|
||||||
send -- ":"
|
send -- ":"
|
||||||
expect ":"
|
expect ":"
|
||||||
send -- "lang en\r"
|
send -- "lang en\r"
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ TEST(full_help_matches_language) {
|
||||||
assert(strstr(en, ":inbox") != NULL);
|
assert(strstr(en, ":inbox") != NULL);
|
||||||
assert(strstr(en, ":support") == NULL);
|
assert(strstr(en, ":support") == NULL);
|
||||||
assert(strstr(en, ":commands") == NULL);
|
assert(strstr(en, ":commands") == NULL);
|
||||||
assert(strstr(en, "Switch English/Chinese") != NULL);
|
assert(strstr(en, "Cycle UI language") != NULL);
|
||||||
|
assert(strstr(en, "Switch English/Chinese") == NULL);
|
||||||
|
|
||||||
assert(strstr(zh, "TNT 按键参考") != NULL);
|
assert(strstr(zh, "TNT 按键参考") != NULL);
|
||||||
assert(strstr(zh, "可用命令") != NULL);
|
assert(strstr(zh, "可用命令") != NULL);
|
||||||
|
|
@ -43,7 +44,8 @@ TEST(full_help_matches_language) {
|
||||||
assert(strstr(zh, "@用户名") == NULL);
|
assert(strstr(zh, "@用户名") == NULL);
|
||||||
assert(strstr(zh, ":support") == NULL);
|
assert(strstr(zh, ":support") == NULL);
|
||||||
assert(strstr(zh, ":commands") == NULL);
|
assert(strstr(zh, ":commands") == NULL);
|
||||||
assert(strstr(zh, "切换英文/中文") != NULL);
|
assert(strstr(zh, "切换界面语言") != NULL);
|
||||||
|
assert(strstr(zh, "切换英文/中文") == NULL);
|
||||||
assert_ascii_angle_placeholders(zh);
|
assert_ascii_angle_placeholders(zh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,12 @@ TEST(text_lookup_matches_language) {
|
||||||
"匿名聊天室") != NULL);
|
"匿名聊天室") != NULL);
|
||||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_HELP_STATUS_FORMAT),
|
assert(strstr(i18n_text(UI_LANG_EN, I18N_HELP_STATUS_FORMAT),
|
||||||
"KEY REFERENCE") != NULL);
|
"KEY REFERENCE") != NULL);
|
||||||
|
assert(strstr(i18n_text(UI_LANG_EN, I18N_HELP_STATUS_FORMAT),
|
||||||
|
"l:lang") != NULL);
|
||||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_HELP_STATUS_FORMAT),
|
assert(strstr(i18n_text(UI_LANG_ZH, I18N_HELP_STATUS_FORMAT),
|
||||||
"按键参考") != NULL);
|
"按键参考") != NULL);
|
||||||
|
assert(strstr(i18n_text(UI_LANG_ZH, I18N_HELP_STATUS_FORMAT),
|
||||||
|
"l:语言") != NULL);
|
||||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_COMMAND_OUTPUT_TITLE),
|
assert(strstr(i18n_text(UI_LANG_EN, I18N_COMMAND_OUTPUT_TITLE),
|
||||||
"COMMAND") != NULL);
|
"COMMAND") != NULL);
|
||||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_COMMAND_OUTPUT_TITLE),
|
assert(strstr(i18n_text(UI_LANG_ZH, I18N_COMMAND_OUTPUT_TITLE),
|
||||||
|
|
@ -141,6 +145,8 @@ TEST(text_lookup_matches_language) {
|
||||||
"未知命令") != NULL);
|
"未知命令") != NULL);
|
||||||
assert(strcmp(i18n_ui_lang_code(UI_LANG_EN), "en") == 0);
|
assert(strcmp(i18n_ui_lang_code(UI_LANG_EN), "en") == 0);
|
||||||
assert(strcmp(i18n_ui_lang_code(UI_LANG_ZH), "zh") == 0);
|
assert(strcmp(i18n_ui_lang_code(UI_LANG_ZH), "zh") == 0);
|
||||||
|
assert(i18n_next_ui_lang(UI_LANG_EN) == UI_LANG_ZH);
|
||||||
|
assert(i18n_next_ui_lang(UI_LANG_ZH) == UI_LANG_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(text_catalog_is_complete) {
|
TEST(text_catalog_is_complete) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue