From cbfaf46cad6052f73d9d0701d7592acecf03a98d Mon Sep 17 00:00:00 2001 From: fz999999 <62800289+fz999999@users.noreply.github.com> Date: Sun, 15 Mar 2026 18:27:11 +0800 Subject: [PATCH 1/2] feat: add Simplified Chinese UI localization --- index.html | 4 +- src-tauri/src/commands/account.rs | 11 ++- src-tauri/src/lib.rs | 7 +- src-tauri/tauri.conf.json | 4 +- src/App.tsx | 126 ++++++++++++++--------------- src/components/AccountCard.tsx | 43 ++++++---- src/components/AddAccountModal.tsx | 49 +++++------ src/components/UsageBar.tsx | 42 +++++----- 8 files changed, 152 insertions(+), 134 deletions(-) diff --git a/index.html b/index.html index 90be5fb..6010460 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - + - Codex Switcher + Codex 多账号切换 diff --git a/src-tauri/src/commands/account.rs b/src-tauri/src/commands/account.rs index 6743d7f..37cf766 100644 --- a/src-tauri/src/commands/account.rs +++ b/src-tauri/src/commands/account.rs @@ -3,7 +3,7 @@ use crate::auth::{ add_account, create_chatgpt_account_from_refresh_token, get_active_account, import_from_auth_json, load_accounts, remove_account, save_accounts, set_active_account, - switch_to_account, touch_account, + switch_to_account, touch_account, get_codex_auth_file, }; use crate::types::{AccountInfo, AccountsStore, AuthData, ImportAccountsSummary, StoredAccount}; @@ -109,6 +109,15 @@ pub async fn add_account_from_file(path: String, name: String) -> Result Result { + let path = get_codex_auth_file().map_err(|e| e.to_string())?; + path.to_str() + .map(str::to_owned) + .ok_or_else(|| "Failed to resolve auth.json path".to_string()) +} + /// Switch to a different account #[tauri::command] pub async fn switch_account(account_id: String) -> Result<(), String> { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 075cb3a..9e02702 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -8,9 +8,9 @@ pub mod types; use commands::{ add_account_from_file, cancel_login, check_codex_processes, complete_login, delete_account, export_accounts_full_encrypted_file, export_accounts_slim_text, get_active_account_info, - get_usage, import_accounts_full_encrypted_file, import_accounts_slim_text, list_accounts, - refresh_all_accounts_usage, rename_account, start_login, switch_account, warmup_account, - warmup_all_accounts, + get_default_auth_json_path, get_usage, import_accounts_full_encrypted_file, + import_accounts_slim_text, list_accounts, refresh_all_accounts_usage, rename_account, + start_login, switch_account, warmup_account, warmup_all_accounts, }; #[cfg_attr(mobile, tauri::mobile_entry_point)] @@ -23,6 +23,7 @@ pub fn run() { list_accounts, get_active_account_info, add_account_from_file, + get_default_auth_json_path, switch_account, delete_account, rename_account, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d775937..36742de 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "productName": "Codex Switcher", + "productName": "Codex 多账号切换", "version": "0.1.1", "identifier": "com.lampese.codex-switcher", "build": { @@ -12,7 +12,7 @@ "app": { "windows": [ { - "title": "Codex Switcher", + "title": "Codex 多账号切换", "width": 900, "height": 700, "minWidth": 600, diff --git a/src/App.tsx b/src/App.tsx index 5ac8f87..1a00e9a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -163,13 +163,13 @@ function App() { }; const formatWarmupError = (err: unknown) => { - if (!err) return "Unknown error"; + if (!err) return "未知错误"; if (err instanceof Error && err.message) return err.message; if (typeof err === "string") return err; try { return JSON.stringify(err); } catch { - return "Unknown error"; + return "未知错误"; } }; @@ -177,11 +177,11 @@ function App() { try { setWarmingUpId(accountId); await warmupAccount(accountId); - showWarmupToast(`Warm-up sent for ${accountName}`); + showWarmupToast(`已向 ${accountName} 发送保活请求`); } catch (err) { console.error("Failed to warm up account:", err); showWarmupToast( - `Warm-up failed for ${accountName}: ${formatWarmupError(err)}`, + `${accountName} 保活失败:${formatWarmupError(err)}`, true ); } finally { @@ -194,25 +194,21 @@ function App() { setIsWarmingAll(true); const summary = await warmupAllAccounts(); if (summary.total_accounts === 0) { - showWarmupToast("No accounts available for warm-up", true); + showWarmupToast("当前没有可保活的账号", true); return; } if (summary.failed_account_ids.length === 0) { - showWarmupToast( - `Warm-up sent for all ${summary.warmed_accounts} account${ - summary.warmed_accounts === 1 ? "" : "s" - }` - ); + showWarmupToast(`已向全部 ${summary.warmed_accounts} 个账号发送保活请求`); } else { showWarmupToast( - `Warmed ${summary.warmed_accounts}/${summary.total_accounts}. Failed: ${summary.failed_account_ids.length}`, + `保活完成 ${summary.warmed_accounts}/${summary.total_accounts},失败 ${summary.failed_account_ids.length} 个`, true ); } } catch (err) { console.error("Failed to warm up all accounts:", err); - showWarmupToast(`Warm-up all failed: ${formatWarmupError(err)}`, true); + showWarmupToast(`全部保活失败:${formatWarmupError(err)}`, true); } finally { setIsWarmingAll(false); } @@ -229,12 +225,12 @@ function App() { setIsExportingSlim(true); const payload = await exportAccountsSlimText(); setConfigPayload(payload); - showWarmupToast(`Slim text exported (${accounts.length} accounts).`); + showWarmupToast(`已导出精简配置(共 ${accounts.length} 个账号)`); } catch (err) { console.error("Failed to export slim text:", err); const message = err instanceof Error ? err.message : String(err); setConfigModalError(message); - showWarmupToast("Slim export failed", true); + showWarmupToast("精简配置导出失败", true); } finally { setIsExportingSlim(false); } @@ -250,7 +246,7 @@ function App() { const handleImportSlimText = async () => { if (!configPayload.trim()) { - setConfigModalError("Please paste the slim text string first."); + setConfigModalError("请先粘贴精简配置。"); return; } @@ -261,13 +257,13 @@ function App() { setMaskedAccounts(new Set()); setIsConfigModalOpen(false); showWarmupToast( - `Imported ${summary.imported_count}, skipped ${summary.skipped_count} (total ${summary.total_in_payload})` + `已导入 ${summary.imported_count} 个,跳过 ${summary.skipped_count} 个(共 ${summary.total_in_payload} 个)` ); } catch (err) { console.error("Failed to import slim text:", err); const message = err instanceof Error ? err.message : String(err); setConfigModalError(message); - showWarmupToast("Slim import failed", true); + showWarmupToast("精简配置导入失败", true); } finally { setIsImportingSlim(false); } @@ -277,11 +273,11 @@ function App() { try { setIsExportingFull(true); const selected = await save({ - title: "Export Full Encrypted Account Config", + title: "导出完整加密备份", defaultPath: "codex-switcher-full.cswf", filters: [ { - name: "Codex Switcher Full Backup", + name: "Codex 完整加密备份", extensions: ["cswf"], }, ], @@ -290,10 +286,10 @@ function App() { if (!selected) return; await exportAccountsFullEncryptedFile(selected); - showWarmupToast("Full encrypted file exported."); + showWarmupToast("完整加密备份已导出。"); } catch (err) { console.error("Failed to export full encrypted file:", err); - showWarmupToast("Full export failed", true); + showWarmupToast("完整加密备份导出失败", true); } finally { setIsExportingFull(false); } @@ -304,10 +300,10 @@ function App() { setIsImportingFull(true); const selected = await open({ multiple: false, - title: "Import Full Encrypted Account Config", + title: "导入完整加密备份", filters: [ { - name: "Codex Switcher Full Backup", + name: "Codex 完整加密备份", extensions: ["cswf"], }, ], @@ -318,11 +314,11 @@ function App() { const summary = await importAccountsFullEncryptedFile(selected); setMaskedAccounts(new Set()); showWarmupToast( - `Imported ${summary.imported_count}, skipped ${summary.skipped_count} (total ${summary.total_in_payload})` + `已导入 ${summary.imported_count} 个,跳过 ${summary.skipped_count} 个(共 ${summary.total_in_payload} 个)` ); } catch (err) { console.error("Failed to import full encrypted file:", err); - showWarmupToast("Full import failed", true); + showWarmupToast("完整加密备份导入失败", true); } finally { setIsImportingFull(false); } @@ -388,7 +384,7 @@ function App() {

- Codex Switcher + Codex 多账号切换

{processInfo && ( {hasRunningProcesses - ? `${processInfo.count} Codex running` - : "0 Codex running"} + ? `检测到 ${processInfo.count} 个 Codex 进程` + : "未检测到 Codex 进程"} )}

- Multi-account manager for Codex CLI + Codex CLI 多账号与配额管理

@@ -419,7 +415,7 @@ function App() { @@ -469,7 +465,7 @@ function App() { onClick={() => setIsActionsMenuOpen((prev) => !prev)} className="h-10 px-4 py-2 text-sm font-medium rounded-lg bg-gray-900 hover:bg-gray-800 text-white transition-colors shrink-0 whitespace-nowrap" > - Account ▾ + 账号操作 ▾ {isActionsMenuOpen && (
@@ -480,7 +476,7 @@ function App() { }} className="w-full text-left px-3 py-2 text-sm rounded-lg hover:bg-gray-100 text-gray-700" > - + Add Account + + 添加账号
)} @@ -535,11 +531,11 @@ function App() { {loading && accounts.length === 0 ? (
-

Loading accounts...

+

正在加载账号列表...

) : error ? (
-
Failed to load accounts
+
加载账号失败

{error}

) : accounts.length === 0 ? ( @@ -548,16 +544,16 @@ function App() { 👤

- No accounts yet + 还没有账号

- Add your first Codex account to get started + 添加第一个 Codex 账号后即可开始使用

) : ( @@ -566,7 +562,7 @@ function App() { {activeAccount && (

- Active Account + 当前账号

- Other Accounts ({otherAccounts.length}) + 其他账号({otherAccounts.length})

@@ -662,7 +658,7 @@ function App() { {/* Refresh Success Toast */} {refreshSuccess && (
- Usage refreshed successfully + 配额已刷新
)} @@ -682,7 +678,7 @@ function App() { {/* Delete Confirmation Toast */} {deleteConfirmId && (
- Click delete again to confirm removal + 再次点击删除以确认
)} @@ -702,7 +698,7 @@ function App() {

- {configModalMode === "slim_export" ? "Export Slim Text" : "Import Slim Text"} + {configModalMode === "slim_export" ? "导出精简配置" : "导入精简配置"}