feat(shortcuts): silently coerce legacy lang values to zh on read

After the 2026-05-28 catalog shrink to zh/en/ja, existing user configs
may still hold ko_kr / fr_fr / etc. RuntimeContext.Lang() now coerces
any non-empty unrecognized value to LangZhCN instead of returning
empty. Storage on disk is untouched — config.json keeps the legacy
value verbatim — so users can still see what was previously set via
'config show', but runtime behavior is uniformly zh.
This commit is contained in:
luozhixiong
2026-05-29 14:47:15 +08:00
parent 73294b298f
commit 5d63d1e2e7
2 changed files with 20 additions and 5 deletions

View File

@@ -73,11 +73,20 @@ func (ctx *RuntimeContext) IsBot() bool {
// UserOpenId returns the current user's open_id from config.
func (ctx *RuntimeContext) UserOpenId() string { return ctx.Config.UserOpenId }
// Lang returns the user's preference as a canonical locale, or "" if unset or
// unrecognized; callers choose their own fallback.
// Lang returns the user's preference as a canonical locale.
// Empty stays empty (unset). Any non-empty stored value that does not resolve
// via i18n.Parse (e.g. legacy ko_kr / fr_fr from before the catalog was
// shrunk to zh/en/ja) is silently coerced to LangZhCN — existing configs
// stay readable, just behave as zh.
func (ctx *RuntimeContext) Lang() i18n.Lang {
lang, _ := i18n.Parse(string(ctx.Config.Lang))
return lang
raw := string(ctx.Config.Lang)
if raw == "" {
return ""
}
if lang, ok := i18n.Parse(raw); ok {
return lang
}
return i18n.LangZhCN
}
// BotInfo holds bot identity metadata fetched lazily from /bot/v3/info.

View File

@@ -20,7 +20,13 @@ func TestRuntimeContext_Lang(t *testing.T) {
{"legacy short value normalizes", "ja", i18n.LangJaJP},
{"legacy short zh normalizes", "zh", i18n.LangZhCN},
{"unset stays empty", "", ""},
{"unrecognized stays empty", "klingon", ""},
// Flipped semantics: unrecognized non-empty values are now treated
// as legacy storage from the pre-2026-05-28 14-language catalog
// and silently coerced to LangZhCN, not left empty.
{"unrecognized garbage coerces to zh", "klingon", i18n.LangZhCN},
{"legacy ko_kr coerces to zh", "ko_kr", i18n.LangZhCN},
{"legacy fr_fr coerces to zh", "fr_fr", i18n.LangZhCN},
{"legacy short ko coerces to zh", "ko", i18n.LangZhCN},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {