mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 04:34:38 +08:00
Add language-keyed i18n string initializers
This commit is contained in:
parent
57d0f931b5
commit
d893351c5a
4 changed files with 25 additions and 2 deletions
|
|
@ -113,6 +113,9 @@
|
|||
the packaged systemd unit, and release preflight checks that metadata.
|
||||
- The Homebrew formula draft now defines a `brew services` entry that runs the
|
||||
installed `tnt` binary with state under `var/tnt`.
|
||||
- The i18n helper now supports language-keyed string initializers through
|
||||
`I18N_STRING_MAP`, so future languages can be added incrementally without
|
||||
changing every existing two-language string initializer.
|
||||
- Split UI-language parsing from localized text lookup: `src/i18n.c` now owns
|
||||
locale/code parsing, while `src/i18n_text.c` owns the table-driven text
|
||||
catalog with coverage checks for every message ID.
|
||||
|
|
|
|||
|
|
@ -480,6 +480,10 @@ keys.
|
|||
fragments.
|
||||
- Keep placeholders visible and stable, for example `%s`, `%d`,
|
||||
`<user>`, and `<message>`.
|
||||
- Use `I18N_STRING(en, zh)` for ordinary two-language entries. Use
|
||||
`I18N_STRING_MAP(I18N_EN(...), I18N_ZH(...))` when an entry needs
|
||||
language-keyed initialization so future languages can be added without
|
||||
changing every existing initializer.
|
||||
- Every new user-facing string needs tests for at least English fallback
|
||||
and Chinese output while this project has two UI languages.
|
||||
|
||||
|
|
@ -488,7 +492,8 @@ keys.
|
|||
The current `src/i18n_text.c` implementation is a small-project translation
|
||||
table implemented in C, not a full gettext catalog. It is acceptable for two
|
||||
languages because message lookup is already split from language parsing in
|
||||
`src/i18n.c`, but adding more languages should move toward catalog-like
|
||||
`src/i18n.c`, and localized strings can now be initialized by language key.
|
||||
Adding many more languages should still move toward external catalog-like
|
||||
storage instead of adding ad hoc branches for every locale.
|
||||
|
||||
Relevant conventions:
|
||||
|
|
|
|||
|
|
@ -7,8 +7,12 @@ typedef struct {
|
|||
const char *text[UI_LANG_COUNT];
|
||||
} i18n_string_t;
|
||||
|
||||
#define I18N_LANG_TEXT(lang, value) [lang] = (value)
|
||||
#define I18N_EN(value) I18N_LANG_TEXT(UI_LANG_EN, value)
|
||||
#define I18N_ZH(value) I18N_LANG_TEXT(UI_LANG_ZH, value)
|
||||
#define I18N_STRING_MAP(...) {{ __VA_ARGS__ }}
|
||||
#define I18N_STRING(en_text, zh_text) \
|
||||
{{ [UI_LANG_EN] = (en_text), [UI_LANG_ZH] = (zh_text) }}
|
||||
I18N_STRING_MAP(I18N_EN(en_text), I18N_ZH(zh_text))
|
||||
|
||||
typedef enum {
|
||||
I18N_USERNAME_PROMPT,
|
||||
|
|
|
|||
|
|
@ -80,10 +80,21 @@ TEST(default_uses_locale_when_no_tnt_lang) {
|
|||
|
||||
TEST(text_lookup_matches_language) {
|
||||
i18n_string_t sample = I18N_STRING("fallback", "替代");
|
||||
i18n_string_t mapped = I18N_STRING_MAP(
|
||||
I18N_EN("mapped fallback"),
|
||||
I18N_ZH("映射替代")
|
||||
);
|
||||
i18n_string_t english_only = I18N_STRING_MAP(
|
||||
I18N_EN("english only")
|
||||
);
|
||||
|
||||
assert(strcmp(i18n_string(sample, UI_LANG_EN), "fallback") == 0);
|
||||
assert(strcmp(i18n_string(sample, UI_LANG_ZH), "替代") == 0);
|
||||
assert(strcmp(i18n_string(sample, (ui_lang_t)99), "fallback") == 0);
|
||||
assert(strcmp(i18n_string(mapped, UI_LANG_EN), "mapped fallback") == 0);
|
||||
assert(strcmp(i18n_string(mapped, UI_LANG_ZH), "映射替代") == 0);
|
||||
assert(strcmp(i18n_string(english_only, UI_LANG_ZH),
|
||||
"english only") == 0);
|
||||
|
||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_USERNAME_PROMPT),
|
||||
"display name") != NULL);
|
||||
|
|
|
|||
Loading…
Reference in a new issue