From ea81c3d839dd7ec10a2984f65c60607f16d16d09 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 28 Sep 2025 20:35:14 +0800 Subject: [PATCH] feat: improve i18n implementation with better translations and accessibility - Add proper i18n keys for language switcher tooltips and aria-labels - Replace hardcoded Chinese console error messages with i18n keys - Add missing translation keys for new UI elements - Improve accessibility with proper aria-label attributes --- src/components/LanguageSwitcher.tsx | 10 ++++- src/components/SettingsModal.tsx | 65 ++++++++++++++++------------- src/i18n/locales/en.json | 4 +- src/i18n/locales/zh.json | 4 +- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index d8691f5..e20e137 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -4,18 +4,24 @@ import { Globe } from "lucide-react"; import { buttonStyles } from "../lib/styles"; const LanguageSwitcher: React.FC = () => { - const { i18n } = useTranslation(); + const { t, i18n } = useTranslation(); const toggleLanguage = () => { const newLang = i18n.language === "en" ? "zh" : "en"; i18n.changeLanguage(newLang); }; + const titleKey = + i18n.language === "en" + ? "header.switchToChinese" + : "header.switchToEnglish"; + return ( diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx index 54be860..08e7a93 100644 --- a/src/components/SettingsModal.tsx +++ b/src/components/SettingsModal.tsx @@ -86,7 +86,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { : undefined, }); } catch (error) { - console.error("加载设置失败:", error); + console.error(t("console.loadSettingsFailed"), error); } }; @@ -97,7 +97,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { setConfigPath(path); } } catch (error) { - console.error("获取配置路径失败:", error); + console.error(t("console.getConfigPathFailed"), error); } }; @@ -110,7 +110,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { setResolvedClaudeDir(claudeDir || ""); setResolvedCodexDir(codexDir || ""); } catch (error) { - console.error("获取配置目录失败:", error); + console.error(t("console.getConfigDirFailed"), error); } }; @@ -119,7 +119,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { const portable = await window.api.isPortable(); setIsPortable(portable); } catch (error) { - console.error("检测便携模式失败:", error); + console.error(t("console.detectPortableFailed"), error); } }; @@ -140,7 +140,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { setSettings(payload); onClose(); } catch (error) { - console.error("保存设置失败:", error); + console.error(t("console.saveSettingsFailed"), error); } }; @@ -157,7 +157,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { await updateHandle.downloadAndInstall(); await relaunchApp(); } catch (error) { - console.error("更新失败:", error); + console.error(t("console.updateFailed"), error); // 更新失败时回退到打开 Releases 页面 await window.api.checkForUpdates(); } finally { @@ -178,7 +178,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { }, 3000); } } catch (error) { - console.error("检查更新失败:", error); + console.error(t("console.checkUpdateFailed"), error); // 在开发模式下,模拟已是最新版本的响应 if (import.meta.env.DEV) { setShowUpToDate(true); @@ -199,7 +199,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { try { await window.api.openAppConfigFolder(); } catch (error) { - console.error("打开配置文件夹失败:", error); + console.error(t("console.openConfigFolderFailed"), error); } }; @@ -230,7 +230,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { setResolvedCodexDir(sanitized); } } catch (error) { - console.error("选择配置目录失败:", error); + console.error(t("console.selectConfigDirFailed"), error); } }; @@ -240,7 +240,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { const folder = app === "claude" ? ".claude" : ".codex"; return await join(home, folder); } catch (error) { - console.error("获取默认配置目录失败:", error); + console.error(t("console.getDefaultConfigDirFailed"), error); return ""; } }; @@ -268,8 +268,9 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { const handleOpenReleaseNotes = async () => { try { const targetVersion = updateInfo?.availableVersion || version; + const unknownLabel = t("common.unknown"); // 如果未知或为空,回退到 releases 首页 - if (!targetVersion || targetVersion === "未知") { + if (!targetVersion || targetVersion === unknownLabel) { await window.api.openExternal( "https://github.com/farion1231/cc-switch/releases" ); @@ -282,7 +283,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { `https://github.com/farion1231/cc-switch/releases/tag/${tag}` ); } catch (error) { - console.error("打开更新日志失败:", error); + console.error(t("console.openReleaseNotesFailed"), error); } }; @@ -393,14 +394,14 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { claudeConfigDir: e.target.value, }) } - placeholder="例如:/home/<你的用户名>/.claude" + placeholder={t("settings.browsePlaceholderClaude")} className="flex-1 px-3 py-2 text-xs font-mono bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/40" /> @@ -408,7 +409,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { type="button" onClick={() => handleResetConfigDir("claude")} className="px-2 py-2 text-xs text-gray-500 dark:text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors" - title="恢复默认目录(需保存后生效)" + title={t("settings.resetDefault")} > @@ -417,7 +418,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
@@ -444,7 +445,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { type="button" onClick={() => handleResetConfigDir("codex")} className="px-2 py-2 text-xs text-gray-500 dark:text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors" - title="恢复默认目录(需保存后生效)" + title={t("settings.resetDefault")} > @@ -456,7 +457,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { {/* 关于 */}

- 关于 + {t("common.about")}

@@ -466,7 +467,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { CC Switch

- 版本 {version} + {t("common.version")} {version}

@@ -475,12 +476,14 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { onClick={handleOpenReleaseNotes} className="px-2 py-1 text-xs font-medium text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 rounded-lg hover:bg-blue-500/10 transition-colors" title={ - hasUpdate ? "查看该版本更新日志" : "查看当前版本更新日志" + hasUpdate + ? t("settings.viewReleaseNotes") + : t("settings.viewCurrentReleaseNotes") } > - 更新日志 + {t("settings.releaseNotes")}
@@ -532,14 +537,14 @@ export default function SettingsModal({ onClose }: SettingsModalProps) { onClick={onClose} className="px-4 py-2 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors" > - 取消 + {t("common.cancel")}
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 5109b51..c7b6b29 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -23,7 +23,9 @@ "viewOnGithub": "View on GitHub", "toggleDarkMode": "Switch to Dark Mode", "toggleLightMode": "Switch to Light Mode", - "addProvider": "Add Provider" + "addProvider": "Add Provider", + "switchToChinese": "Switch to Chinese", + "switchToEnglish": "Switch to English" }, "provider": { "noProviders": "No providers added yet", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 81e80e4..8cf5767 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -23,7 +23,9 @@ "viewOnGithub": "在 GitHub 上查看", "toggleDarkMode": "切换到暗色模式", "toggleLightMode": "切换到亮色模式", - "addProvider": "添加供应商" + "addProvider": "添加供应商", + "switchToChinese": "切换到中文", + "switchToEnglish": "切换到英文" }, "provider": { "noProviders": "还没有添加任何供应商",