From b8dec515659faf7d03b1088073f6d338a0ba5149 Mon Sep 17 00:00:00 2001 From: Zixu Date: Thu, 25 Jun 2026 15:38:05 +0800 Subject: [PATCH] Add Simplified Chinese localization Add a Simplified Chinese (zh-CN) translation alongside the existing Traditional Chinese, wired into the language enum, menu, settings code, and persistence. Map zh-CN, zh-SG, zh-Hans, and bare "zh" to Simplified Chinese in from_code, and route zh-MO to Traditional Chinese so Macau is no longer treated as Simplified. Co-Authored-By: Claude Opus 4.8 --- src/localization/mod.rs | 12 +++++-- src/localization/simplified_chinese.rs | 50 ++++++++++++++++++++++++++ src/window.rs | 4 +++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/localization/simplified_chinese.rs diff --git a/src/localization/mod.rs b/src/localization/mod.rs index 2a06b04..a11ba02 100644 --- a/src/localization/mod.rs +++ b/src/localization/mod.rs @@ -6,6 +6,7 @@ mod japanese; mod korean; mod portuguese_brazil; mod russian; +mod simplified_chinese; mod spanish; mod traditional_chinese; @@ -25,12 +26,13 @@ pub enum LanguageId { Japanese, Korean, TraditionalChinese, + SimplifiedChinese, Russian, PortugueseBrazil, } impl LanguageId { - pub const ALL: [LanguageId; 10] = [ + pub const ALL: [LanguageId; 11] = [ LanguageId::English, LanguageId::Dutch, LanguageId::Spanish, @@ -39,6 +41,7 @@ impl LanguageId { LanguageId::Japanese, LanguageId::Korean, LanguageId::TraditionalChinese, + LanguageId::SimplifiedChinese, LanguageId::Russian, LanguageId::PortugueseBrazil, ]; @@ -53,6 +56,7 @@ impl LanguageId { Self::Japanese => "ja", Self::Korean => "ko", Self::TraditionalChinese => "zh-TW", + Self::SimplifiedChinese => "zh-CN", Self::Russian => "ru", Self::PortugueseBrazil => "pt-BR", } @@ -68,6 +72,7 @@ impl LanguageId { Self::Japanese => "日本語", Self::Korean => "한국어", Self::TraditionalChinese => "繁體中文", + Self::SimplifiedChinese => "简体中文", Self::Russian => "Русский", Self::PortugueseBrazil => "Português (Brasil)", } @@ -83,6 +88,7 @@ impl LanguageId { Self::Japanese => japanese::STRINGS, Self::Korean => korean::STRINGS, Self::TraditionalChinese => traditional_chinese::STRINGS, + Self::SimplifiedChinese => simplified_chinese::STRINGS, Self::Russian => russian::STRINGS, Self::PortugueseBrazil => portuguese_brazil::STRINGS, } @@ -98,6 +104,7 @@ impl LanguageId { Self::Japanese => japanese::UPDATE_VIA_WINGET_LABEL, Self::Korean => korean::UPDATE_VIA_WINGET_LABEL, Self::TraditionalChinese => traditional_chinese::UPDATE_VIA_WINGET_LABEL, + Self::SimplifiedChinese => simplified_chinese::UPDATE_VIA_WINGET_LABEL, Self::Russian => russian::UPDATE_VIA_WINGET_LABEL, Self::PortugueseBrazil => portuguese_brazil::UPDATE_VIA_WINGET_LABEL, } @@ -121,11 +128,12 @@ impl LanguageId { "zh" => { if normalized.contains("tw") || normalized.contains("hk") + || normalized.contains("mo") || normalized.contains("hant") { Some(Self::TraditionalChinese) } else { - None + Some(Self::SimplifiedChinese) } } "ru" => Some(Self::Russian), diff --git a/src/localization/simplified_chinese.rs b/src/localization/simplified_chinese.rs new file mode 100644 index 0000000..8a62588 --- /dev/null +++ b/src/localization/simplified_chinese.rs @@ -0,0 +1,50 @@ +use super::Strings; + +pub(super) const UPDATE_VIA_WINGET_LABEL: &str = "通过 WinGet 更新"; + +pub(super) const STRINGS: Strings = Strings { + window_title: "Claude Code 使用量监控", + refresh: "刷新", + update_frequency: "更新频率", + one_minute: "1 分钟", + five_minutes: "5 分钟", + fifteen_minutes: "15 分钟", + one_hour: "1 小时", + models: "模型", + claude_code_model: "Claude Code", + codex_model: "Codex", + antigravity_model: "Antigravity", + settings: "设置", + start_with_windows: "开机时启动", + reset_position: "重置位置", + language: "语言", + system_default: "系统默认", + check_for_updates: "检查更新", + checking_for_updates: "正在检查更新...", + updates: "更新", + update_in_progress: "已有更新检查正在进行中。", + up_to_date: "您已使用最新版本。", + up_to_date_short: "已是最新", + update_failed: "无法自动更新", + applying_update: "正在应用更新...", + update_to: "更新至", + update_available: "有可用更新", + update_prompt_now: "版本 {version} 已可用。是否立即更新?", + exit: "退出", + show_widget: "显示小组件", + session_window: "5h", + weekly_window: "7d", + now: "现在", + day_suffix: "天", + hour_suffix: "时", + minute_suffix: "分", + token_expired_title: "验证错误", + token_expired_body: "请在终端中运行 'claude',然后使用 '/login' 并按照提示操作。完成后,请刷新或重新启动此应用程序。", + codex_token_expired_title: "Codex 验证错误", + codex_token_expired_body: "请在终端中运行 'codex',并按照登录提示操作。完成后,请刷新或重新启动此应用程序。", + antigravity_token_expired_title: "Antigravity 验证错误", + antigravity_token_expired_body: "请打开 Antigravity 并重新登录。完成后,请刷新或重新启动此应用程序。", + codex_window_title: "Codex 使用量监控", + antigravity_window_title: "Antigravity 使用量监控", + second_suffix: "秒", +}; diff --git a/src/window.rs b/src/window.rs index f6d261e..bf30f88 100644 --- a/src/window.rs +++ b/src/window.rs @@ -128,6 +128,7 @@ const IDM_LANG_KOREAN: u16 = 47; const IDM_LANG_TRADITIONAL_CHINESE: u16 = 48; const IDM_LANG_RUSSIAN: u16 = 49; const IDM_LANG_PORTUGUESE_BRAZIL: u16 = 50; +const IDM_LANG_SIMPLIFIED_CHINESE: u16 = 51; const IDM_MODEL_CLAUDE_CODE: u16 = 60; const IDM_MODEL_CODEX: u16 = 61; const IDM_MODEL_ANTIGRAVITY: u16 = 62; @@ -2642,6 +2643,7 @@ unsafe extern "system" fn wnd_proc( | IDM_LANG_JAPANESE | IDM_LANG_KOREAN | IDM_LANG_TRADITIONAL_CHINESE + | IDM_LANG_SIMPLIFIED_CHINESE | IDM_LANG_RUSSIAN | IDM_LANG_PORTUGUESE_BRAZIL => { let language_override = match id { @@ -2654,6 +2656,7 @@ unsafe extern "system" fn wnd_proc( IDM_LANG_JAPANESE => Some(LanguageId::Japanese), IDM_LANG_KOREAN => Some(LanguageId::Korean), IDM_LANG_TRADITIONAL_CHINESE => Some(LanguageId::TraditionalChinese), + IDM_LANG_SIMPLIFIED_CHINESE => Some(LanguageId::SimplifiedChinese), IDM_LANG_RUSSIAN => Some(LanguageId::Russian), IDM_LANG_PORTUGUESE_BRAZIL => Some(LanguageId::PortugueseBrazil), _ => None, @@ -2883,6 +2886,7 @@ fn show_context_menu(hwnd: HWND) { LanguageId::Japanese => IDM_LANG_JAPANESE, LanguageId::Korean => IDM_LANG_KOREAN, LanguageId::TraditionalChinese => IDM_LANG_TRADITIONAL_CHINESE, + LanguageId::SimplifiedChinese => IDM_LANG_SIMPLIFIED_CHINESE, LanguageId::Russian => IDM_LANG_RUSSIAN, LanguageId::PortugueseBrazil => IDM_LANG_PORTUGUESE_BRAZIL, };