i18n: centralize language definitions

This commit is contained in:
m1ngsama 2026-05-24 15:10:54 +08:00
parent 155e535b8a
commit f99103ede6
3 changed files with 40 additions and 12 deletions

View file

@ -48,6 +48,8 @@
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.
- Language parsing, language-code output, and help-language cycling now share
one internal language registry.
- Documented i18n and user-facing text rules for English-first source text,
stable command syntax, concise help copy, and translation-only localization.

View file

@ -2,6 +2,17 @@
#include <ctype.h>
typedef struct {
ui_lang_t lang;
const char *code;
const char *prefixes[4];
} ui_lang_definition_t;
static const ui_lang_definition_t ui_lang_defs[] = {
{UI_LANG_EN, "en", {"en", "c", "posix", NULL}},
{UI_LANG_ZH, "zh", {"zh", NULL}}
};
static const char *skip_space(const char *value) {
while (value && *value &&
isspace((unsigned char)*value)) {
@ -41,16 +52,15 @@ bool i18n_try_parse_ui_lang(const char *value, ui_lang_t *lang) {
return false;
}
if (starts_with_lang(value, "zh")) {
if (lang) *lang = UI_LANG_ZH;
return true;
}
if (starts_with_lang(value, "en") ||
starts_with_lang(value, "c") ||
starts_with_lang(value, "posix")) {
if (lang) *lang = UI_LANG_EN;
return true;
for (size_t i = 0; i < sizeof(ui_lang_defs) / sizeof(ui_lang_defs[0]); i++) {
for (size_t j = 0; ui_lang_defs[i].prefixes[j]; j++) {
if (starts_with_lang(value, ui_lang_defs[i].prefixes[j])) {
if (lang) {
*lang = ui_lang_defs[i].lang;
}
return true;
}
}
}
return false;
@ -82,9 +92,23 @@ ui_lang_t i18n_default_ui_lang(void) {
}
ui_lang_t i18n_next_ui_lang(ui_lang_t lang) {
return lang == UI_LANG_EN ? UI_LANG_ZH : UI_LANG_EN;
size_t count = sizeof(ui_lang_defs) / sizeof(ui_lang_defs[0]);
for (size_t i = 0; i < count; i++) {
if (ui_lang_defs[i].lang == lang) {
return ui_lang_defs[(i + 1) % count].lang;
}
}
return ui_lang_defs[0].lang;
}
const char *i18n_ui_lang_code(ui_lang_t lang) {
return lang == UI_LANG_ZH ? "zh" : "en";
for (size_t i = 0; i < sizeof(ui_lang_defs) / sizeof(ui_lang_defs[0]); i++) {
if (ui_lang_defs[i].lang == lang) {
return ui_lang_defs[i].code;
}
}
return ui_lang_defs[0].code;
}

View file

@ -145,8 +145,10 @@ TEST(text_lookup_matches_language) {
"未知命令") != NULL);
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_t)99), "en") == 0);
assert(i18n_next_ui_lang(UI_LANG_EN) == UI_LANG_ZH);
assert(i18n_next_ui_lang(UI_LANG_ZH) == UI_LANG_EN);
assert(i18n_next_ui_lang((ui_lang_t)99) == UI_LANG_EN);
}
TEST(text_catalog_is_complete) {