diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml
index ce3818db7..2d6cd9e5e 100644
--- a/.github/workflows/pr-build.yml
+++ b/.github/workflows/pr-build.yml
@@ -136,7 +136,7 @@ jobs:
set -euo pipefail
test -L "dist/macos/stage/Applications"
test "$(readlink "dist/macos/stage/Applications")" = "/Applications"
- for app in "dist/macos/stage/Codex++.app" "dist/macos/stage/Codex++ 管理工具.app"; do
+ for app in "dist/macos/stage/Codex++.app" "dist/macos/stage/Codex++ Manager.app"; do
test -f "$app/Contents/Info.plist"
test -f "$app/Contents/PkgInfo"
test -x "$app/Contents/MacOS/$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$app/Contents/Info.plist")"
diff --git a/.github/workflows/release-assets.yml b/.github/workflows/release-assets.yml
index 3fc0ad6a5..46e2afa06 100644
--- a/.github/workflows/release-assets.yml
+++ b/.github/workflows/release-assets.yml
@@ -133,7 +133,7 @@ jobs:
set -euo pipefail
test -L "dist/macos/stage/Applications"
test "$(readlink "dist/macos/stage/Applications")" = "/Applications"
- for app in "dist/macos/stage/Codex++.app" "dist/macos/stage/Codex++ 管理工具.app"; do
+ for app in "dist/macos/stage/Codex++.app" "dist/macos/stage/Codex++ Manager.app"; do
test -f "$app/Contents/Info.plist"
test -f "$app/Contents/PkgInfo"
test -x "$app/Contents/MacOS/$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$app/Contents/Info.plist")"
diff --git a/apps/codex-plus-manager/index.html b/apps/codex-plus-manager/index.html
index 0bfda5710..f0bce202d 100644
--- a/apps/codex-plus-manager/index.html
+++ b/apps/codex-plus-manager/index.html
@@ -3,7 +3,7 @@
- Codex++ 管理工具
+ Codex++ Manager
diff --git a/apps/codex-plus-manager/src-tauri/src/lib.rs b/apps/codex-plus-manager/src-tauri/src/lib.rs
index ae70cb725..1b1ab691c 100644
--- a/apps/codex-plus-manager/src-tauri/src/lib.rs
+++ b/apps/codex-plus-manager/src-tauri/src/lib.rs
@@ -35,7 +35,7 @@ pub fn run() {
};
let mut main_window_builder =
tauri::WebviewWindowBuilder::new(app, "main", tauri::WebviewUrl::App(url.into()))
- .title("Codex++ 管理工具")
+ .title("Codex++ Manager")
.inner_size(1180.0, 820.0)
.min_inner_size(960.0, 720.0);
if let Some(icon) = app.default_window_icon().cloned() {
diff --git a/apps/codex-plus-manager/src-tauri/tauri.conf.json b/apps/codex-plus-manager/src-tauri/tauri.conf.json
index d1540cf6e..6a13477dc 100644
--- a/apps/codex-plus-manager/src-tauri/tauri.conf.json
+++ b/apps/codex-plus-manager/src-tauri/tauri.conf.json
@@ -14,7 +14,7 @@
{
"create": false,
"label": "main",
- "title": "Codex++ 管理工具",
+ "title": "Codex++ Manager",
"width": 1180,
"height": 820,
"minWidth": 960,
diff --git a/apps/codex-plus-manager/src-tauri/tests/windows_subsystem.rs b/apps/codex-plus-manager/src-tauri/tests/windows_subsystem.rs
index 6ee1edf4e..fa114c379 100644
--- a/apps/codex-plus-manager/src-tauri/tests/windows_subsystem.rs
+++ b/apps/codex-plus-manager/src-tauri/tests/windows_subsystem.rs
@@ -110,6 +110,11 @@ fn windows_binaries_request_administrator_privileges() {
assert!(windows_manifest.contains("requireAdministrator"));
assert!(windows_manifest.contains("Microsoft.Windows.Common-Controls"));
assert!(windows_installer.contains("RequestExecutionLevel admin"));
+ assert!(windows_installer.contains("CreateShortcut \"$DESKTOP\\Codex++ Manager.lnk\""));
+ assert!(windows_installer.contains("CreateShortcut \"$SMPROGRAMS\\Codex++\\Codex++ Manager.lnk\""));
+ assert!(windows_installer.contains("CreateShortcut \"$SMPROGRAMS\\Codex++\\Uninstall Codex++.lnk\""));
+ assert!(!windows_installer.contains("CreateShortcut \"$DESKTOP\\Codex++ 管理工具.lnk\""));
+ assert!(!windows_installer.contains("CreateShortcut \"$SMPROGRAMS\\Codex++\\卸载 Codex++.lnk\""));
}
#[test]
@@ -159,8 +164,11 @@ fn macos_packager_hides_silent_launcher_but_not_manager() {
"create_app \"Codex++\" \"CodexPlusPlus\" \"$BINARY_DIR/codex-plus-plus\" \"com.bigpizzav3.codexplusplus\" \"true\""
));
assert!(script.contains(
- "create_app \"Codex++ 管理工具\" \"CodexPlusPlusManager\" \"$BINARY_DIR/codex-plus-plus-manager\" \"com.bigpizzav3.codexplusplus.manager\" \"false\""
+ "create_app \"Codex++ Manager\" \"CodexPlusPlusManager\" \"$BINARY_DIR/codex-plus-plus-manager\" \"com.bigpizzav3.codexplusplus.manager\" \"false\""
));
+ assert!(script.contains("sign_app \"$STAGE/Codex++ Manager.app\""));
+ assert!(script.contains("verify_app \"$STAGE/Codex++ Manager.app\""));
+ assert!(!script.contains("create_app \"Codex++ 管理工具\""));
}
#[test]
diff --git a/apps/codex-plus-manager/src/App.tsx b/apps/codex-plus-manager/src/App.tsx
index 11a2c709b..55d2b9df8 100644
--- a/apps/codex-plus-manager/src/App.tsx
+++ b/apps/codex-plus-manager/src/App.tsx
@@ -68,7 +68,7 @@ import {
serializeModelWindowRows,
type ModelWindowRow,
} from "./model-windows";
-import { getLanguage, t, tf, toggleLanguage } from "@/i18n";
+import { getLanguage, languageButtonTitle, t, tf, toggleLanguage } from "@/i18n";
type Status = "ok" | "failed" | "not_implemented" | "not_checked" | string;
@@ -730,6 +730,10 @@ const defaultSettings: BackendSettings = {
};
export function App() {
+ useEffect(() => {
+ document.title = t("Codex++ 管理工具");
+ }, []);
+
const [theme, setTheme] = useState(() => loadInitialTheme());
const [route, setRoute] = useState(() => loadInitialRoute());
const [notice, setNotice] = useState<{ title: string; message: string; status?: Status } | null>(null);
@@ -2070,7 +2074,7 @@ export function App() {
);
diff --git a/apps/codex-plus-manager/src/i18n-en.ts b/apps/codex-plus-manager/src/i18n-en.ts
index afcb02de2..4a9411fd0 100644
--- a/apps/codex-plus-manager/src/i18n-en.ts
+++ b/apps/codex-plus-manager/src/i18n-en.ts
@@ -5,6 +5,11 @@
// Plain strings: t("中文") -> EN_PLAIN["中文"].
export const EN_PLAIN: Record = {
+ "JOJO Code 包月": "JOJO Code Monthly",
+ "Codex++ 管理工具": "Codex++ Manager",
+ "小米 MiMo": "Xiaomi MiMo",
+ "百度千帆 Coding Plan": "Baidu Qianfan Coding Plan",
+ "火山引擎 Ark": "Volcengine Ark",
"API Key 模式下扩展插件市场请求,尽量显示完整插件列表;官方/混合模式通常不需要。":
"Expands plugin marketplace requests in API Key mode to show the full plugin list. Usually unnecessary in official/mixed mode.",
"API Key 环境变量": "API Key environment variable",
@@ -158,6 +163,7 @@ export const EN_PLAIN: Record = {
"切换到此供应商时会写入 ~/.codex/auth.json": "Switching to this provider writes ~/.codex/auth.json",
"切换到此供应商时会写入的预览;上下文开关变化会立即反映": "Preview of what gets written when switching to this provider; context toggles are reflected immediately",
"切换到中文": "Switch to Chinese",
+ "切换到越南语": "Switch to Vietnamese",
"切换到英文": "Switch to English",
"切换到浅色": "Switch to light",
"切换到深色": "Switch to dark",
diff --git a/apps/codex-plus-manager/src/i18n-vi.ts b/apps/codex-plus-manager/src/i18n-vi.ts
new file mode 100644
index 000000000..7536352d4
--- /dev/null
+++ b/apps/codex-plus-manager/src/i18n-vi.ts
@@ -0,0 +1,789 @@
+// Vietnamese translations for the Codex++ manager UI, keyed by original Chinese source text.
+
+
+export const VI_PLAIN: Record = {
+ "JOJO Code 包月": "JOJO Code theo tháng",
+ "Codex++ 管理工具": "Trình quản lý Codex++",
+ "小米 MiMo": "Xiaomi MiMo",
+ "百度千帆 Coding Plan": "Kế hoạch mã hóa Baidu Qianfan",
+ "火山引擎 Ark": "Hòm động cơ Volc",
+ "API Key 模式下扩展插件市场请求,尽量显示完整插件列表;官方/混合模式通常不需要。": "Mở rộng các yêu cầu về thị trường plugin trong chế độ Khóa API để hiển thị danh sách plugin đầy đủ. Thường không cần thiết ở chế độ chính thức/hỗn hợp.",
+ "API Key 环境变量": "Biến môi trường khóa API",
+ "Chat Completions 转 Responses": "Hoàn thành trò chuyện để phản hồi",
+ "Codex 启动参数": "Đối số khởi chạy Codex",
+ "Codex 工具与插件": "Công cụ và plugin Codex",
+ "Codex 应用": "ứng dụng Codex",
+ "Codex 应用路径": "Đường dẫn ứng dụng Codex",
+ "Codex 意外停止": "Codex dừng đột ngột",
+ "Codex 版本": "Phiên bản Codex",
+ "Codex 目标": "Mục tiêu Codex",
+ "Codex++ 官方中转站,主打稳定接入和划算价格,支持 GPT-5.5、GPT-5.4、Claude Opus 4.8、Claude Opus 4.7、gpt-image-2 等模型与图像能力。": "Rơle Codex++ chính thức, được thiết kế để truy cập ổn định và có giá trị tốt, hỗ trợ GPT-5.5, GPT-5.4, Claude Opus 4.8, Claude Opus 4.7, gpt-image-2 và các mẫu khác cùng với khả năng hình ảnh.",
+ "Codex++ 导入": "Nhập Codex++",
+ "Codex++ 版本": "Phiên bản Codex++",
+ "Codex增强": "Cải tiến Codex",
+ "Codex增强模式": "Chế độ nâng cao Codex",
+ "Debug 端口": "Cổng gỡ lỗi",
+ "Fast 按钮": "Nút nhanh",
+ "GitHub Release 更新": "Cập nhật phát hành GitHub",
+ "GitHub Release 检查": "Kiểm tra phát hành GitHub",
+ "Helper 端口": "Cổng trợ giúp",
+ "MCP、Skills、Plugins 作为全局配置独立管理,切换任意供应商都会合并。": "MCP, Kỹ năng và Plugin được quản lý độc lập dưới dạng cấu hình chung và được hợp nhất bất cứ khi nào bạn chuyển đổi nhà cung cấp.",
+ "Markdown 导出": "Xuất khẩu giảm giá",
+ "Provider 同步目标": "Mục tiêu đồng bộ hóa nhà cung cấp",
+ "Stepwise 直接发送": "Gửi trực tiếp từng bước",
+ "基于当前对话生成下一步建议,使用独立 API 配置。": "Tạo đề xuất bước tiếp theo từ cuộc trò chuyện hiện tại bằng cách sử dụng cấu hình API riêng.",
+ "插件与模型": "Plugin và mô hình",
+ "管理插件市场、模型列表和服务档位相关增强。": "Quản lý các cải tiến cho thị trường plugin, danh sách mô hình và cấp dịch vụ.",
+ "对话与输入": "Cuộc trò chuyện và đầu vào",
+ "调整会话管理、输入行为和对话阅读体验。": "Điều chỉnh quản lý phiên, hành vi đầu vào và trải nghiệm đọc hội thoại.",
+ "界面与启动": "Giao diện và khởi động",
+ "控制语言、启动速度和 Codex 原生界面调整。": "Kiểm soát ngôn ngữ, tốc độ khởi động và điều chỉnh giao diện người dùng gốc Codex.",
+ "远程项目": "Dự án từ xa",
+ "连接 Zed Remote 和 upstream worktree 辅助能力。": "Kết nối Zed Remote và các khả năng trợ giúp của cây công việc ngược dòng.",
+ "最多建议数": "Đề xuất tối đa",
+ "最大输入字符": "Ký tự đầu vào tối đa",
+ "最大输出 tokens": "Mã thông báo đầu ra tối đa",
+ "测试连接": "Kiểm tra kết nối",
+ "超时毫秒": "Hết thời gian tính bằng mili giây",
+ "连接": "Sự liên quan",
+ "高级参数": "Thông số nâng cao",
+ "TOML 配置体": "Nội dung cấu hình TOML",
+ "Watcher 操作": "Hành động của người theo dõi",
+ "Watcher 状态": "Trạng thái người theo dõi",
+ "Watcher 用于保持 Codex++ 接管状态": "Người theo dõi giữ quyền kiểm soát Codex++",
+ "Watcher 自动接管": "Watcher tự động tiếp quản",
+ "Zed 远程打开": "Zed mở remote",
+ "Zed 远程项目": "Dự án từ xa của Zed",
+ "Zed 项目记录": "Lịch sử dự án Zed",
+ "Zed 默认打开策略": "Chiến lược mở Zed mặc định",
+ "Zed 默认行为": "Hành vi mặc định của Zed",
+ "cc-switch 导入": "nhập cc-switch",
+ "config.toml 预览": "xem trước config.toml",
+ "provider 未记录": "nhà cung cấp không được ghi lại",
+ "ssh:// URL 已复制。": "ssh:// URL đã được sao chép.",
+ "、": ", ",
+ "」的供应商": "”",
+ "上一次切换还没有完成,请稍后再试。": "Việc chuyển đổi trước đó vẫn chưa kết thúc. Vui lòng thử lại trong thời gian ngắn.",
+ "上下文大小": "Kích thước ngữ cảnh",
+ "上下文窗口": "Cửa sổ ngữ cảnh",
+ "上次修复结果": "Kết quả sửa chữa cuối cùng",
+ "上次更新结果": "Kết quả cập nhật lần cuối",
+ "上游协议": "Giao thức ngược dòng",
+ "下载并运行安装包": "Tải xuống và chạy trình cài đặt",
+ "不写 API 文件": "Không ghi tệp API",
+ "与 Codex 内插件菜单使用同一个远端广告源": "Sử dụng nguồn quảng cáo từ xa giống như menu plugin trong Codex",
+ "个": "",
+ "个会话": "(các) phiên",
+ "中国官方": "quan chức trung quốc",
+ "主页": "Trang chủ",
+ "主题和启动参数": "Chủ đề và khởi động các đối số",
+ "从 GitHub 静态清单加载": "Được tải từ bảng kê khai GitHub tĩnh",
+ "从 Word 等富文本粘贴到 Codex composer 时只保留纯文本,避免被识别为图片/文件附件。需重启 Codex 才生效。": "Chỉ giữ lại văn bản thuần túy khi dán văn bản có định dạng (ví dụ: từ Word) vào trình soạn thảo Codex, tránh bị coi là văn bản đính kèm hình ảnh/tệp. Yêu cầu khởi động lại Codex.",
+ "从上游获取": "Tìm nạp từ thượng nguồn",
+ "从最新 upstream 分支创建 Git worktree。": "Tạo cây công việc Git từ nhánh ngược dòng mới nhất.",
+ "从环境变量和 config.toml 的 /v1/models 拉取模型并补进模型列表。": "Kéo các mô hình từ các biến môi trường và /v1/models của config.toml rồi thêm chúng vào danh sách mô hình.",
+ "从第三方导入": "Nhập khẩu từ bên thứ ba",
+ "从预设模板创建": "Tạo từ mẫu đặt trước",
+ "会话": "Phiên họp",
+ "会话 ID 标识": "Huy hiệu ID phiên",
+ "会话删除": "Xóa phiên",
+ "会话删除、导出、项目移动和用户脚本等界面能力": "Các khả năng của giao diện người dùng như xóa phiên, xuất, di chuyển dự án và tập lệnh người dùng",
+ "会话删除、导出、项目移动和脚本能力": "Khả năng xóa phiên, xuất, di chuyển dự án và tập lệnh",
+ "会话总数": "Tổng số phiên",
+ "会话管理": "Quản lý phiên",
+ "会话项目移动": "Phiên di chuyển dự án",
+ "使用": "Sử dụng",
+ "使用中": "Đang sử dụng",
+ "例如 C:\\Program Files\\WindowsApps\\OpenAI.Codex...\\app": "ví dụ. C:\\Tệp chương trình\\WindowsApps\\OpenAI.Codex...\\app",
+ "例如 context7": "ví dụ. bối cảnh7",
+ "例如 deepseek-v4-pro": "ví dụ. deepseek-v4-pro",
+ "例如 gpt-5.4-mini": "ví dụ. gpt-5.4-mini",
+ "例如 主力聚合池": "ví dụ. Nhóm tổng hợp chính",
+ "供": "P",
+ "供应商": "nhà cung cấp",
+ "供应商切换": "Chuyển đổi nhà cung cấp",
+ "供应商切换不可用": "Chuyển đổi nhà cung cấp không có sẵn",
+ "供应商切换中": "Chuyển đổi nhà cung cấp",
+ "供应商列表": "Danh sách nhà cung cấp",
+ "供应商测试": "Kiểm tra nhà cung cấp",
+ "供应商测试模型": "Mô hình thử nghiệm nhà cung cấp",
+ "供应商配置": "Cấu hình nhà cung cấp",
+ "供应商配置可能不正确": "Cấu hình nhà cung cấp có thể không chính xác",
+ "供应商配置已关闭": "Đã tắt cấu hình nhà cung cấp",
+ "供应商配置总开关已关闭": "Công tắc chính cấu hình nhà cung cấp đang tắt",
+ "供应商配置总开关已关闭;当前只保存配置,不写入 Codex live 文件": "Công tắc chính cấu hình nhà cung cấp bị tắt; các thay đổi chỉ được lưu, không được ghi vào tệp trực tiếp Codex",
+ "供应商预设列表": "Danh sách đặt trước của nhà cung cấp",
+ "保存": "Cứu",
+ "保存为默认路径": "Lưu làm đường dẫn mặc định",
+ "保存到 Codex++ state,不改写 Zed settings。": "Đã lưu vào trạng thái Codex++, không sửa đổi cài đặt Zed.",
+ "保存增强设置": "Lưu cài đặt nâng cao",
+ "保存扩展项": "Lưu mục nhập",
+ "保存的应用路径": "Đường dẫn ứng dụng đã lưu",
+ "保存策略": "Lưu chiến lược",
+ "保存自动修复设置": "Lưu cài đặt tự động sửa chữa",
+ "保存设置": "Lưu cài đặt",
+ "保存路径": "Đường dẫn đã lưu",
+ "修复入口": "Sửa chữa điểm vào",
+ "修复快捷方式": "Sửa chữa phím tắt",
+ "修复插件市场": "Thị trường plugin sửa chữa",
+ "健康检查": "Kiểm tra sức khỏe",
+ "先添加至少 1 个已填写 Base URL / Key 的 API 供应商,再创建聚合供应商。": "Thêm ít nhất 1 nhà cung cấp API có URL/Khóa cơ sở trước khi tạo nhà cung cấp tổng hợp.",
+ "免安装版或解包版只需要选择一次,之后静默启动会自动复用": "Các bản dựng di động hoặc đã giải nén chỉ cần được chọn một lần; khởi động im lặng sẽ tái sử dụng nó sau đó",
+ "入口卸载": "Gỡ cài đặt điểm đầu vào",
+ "入口安装": "Cài đặt điểm đầu vào",
+ "入口安装、修复、Watcher 与手动启动": "Cài đặt điểm truy cập, sửa chữa, theo dõi và khởi chạy thủ công",
+ "入口管理": "Quản lý điểm vào",
+ "全选当前列表": "Chọn tất cả trong danh sách hiện tại",
+ "关于": "Về",
+ "关于 Codex++": "Giới thiệu về Codex++",
+ "关闭": "Tắt",
+ "关闭后会停用删除、导出、项目移动、插件相关和菜单位置增强。": "Khi tắt, nó sẽ vô hiệu hóa tính năng xóa, xuất, di chuyển dự án, các cải tiến liên quan đến plugin và vị trí menu.",
+ "关闭后本工具不会在手动切换时写入 Codex 的 config.toml / auth.json;启动 Codex 时始终不会自动改这些文件。": "Khi tắt, công cụ này sẽ không ghi config.toml / auth.json của Codex trên các công tắc thủ công; nó không bao giờ tự động sửa đổi các tệp này khi khởi chạy Codex.",
+ "兼容增强": "Cải tiến tương thích",
+ "内容来自 BigPizzaV3/Ad-List,分为赞助商推荐和普通推荐。": "Nội dung đến từ BigPizzaV3/Ad-List, được chia thành đề xuất của nhà tài trợ và đề xuất thông thường.",
+ "内置": "Tích hợp sẵn",
+ "内置、手动和市场安装脚本;可在这里启停或删除用户脚本": "Các tập lệnh tích hợp, thủ công và được cài đặt trên thị trường; bật, tắt hoặc xóa tập lệnh người dùng tại đây",
+ "内置和用户自定义脚本清单": "Khoảng không quảng cáo tập lệnh tích hợp và do người dùng xác định",
+ "切换 thread 时恢复上一次浏览位置。": "Khôi phục vị trí cuộn cuối cùng khi chuyển chủ đề.",
+ "切换中": "Chuyển đổi",
+ "切换主题": "Chuyển đổi chủ đề",
+ "切换到此供应商时会写入 ~/.codex/auth.json": "Chuyển sang nhà cung cấp này ghi ~/.codex/auth.json",
+ "切换到此供应商时会写入的预览;上下文开关变化会立即反映": "Xem trước nội dung được viết khi chuyển sang nhà cung cấp này; chuyển đổi bối cảnh được phản ánh ngay lập tức",
+ "切换到中文": "Chuyển sang tiếng Trung",
+ "切换到越南语": "Chuyển sang tiếng Việt",
+ "切换到英文": "Chuyển sang tiếng Anh",
+ "切换到浅色": "Chuyển sang ánh sáng",
+ "切换到深色": "Chuyển sang màu tối",
+ "切换对话保留位置": "Giữ nguyên vị trí cuộn trên các chủ đề",
+ "点击建议后自动发送;关闭时只填入输入框。": "Tự động gửi sau khi nhấp vào gợi ý. Khi tắt, nó chỉ lấp đầy nhà soạn nhạc.",
+ "刚刚启动": "Vừa ra mắt",
+ "删除": "Xóa bỏ",
+ "删除会创建本地备份;如果 Codex App 正在使用该会话,建议先关闭对应会话窗口再操作。": "Việc xóa sẽ tạo bản sao lưu cục bộ; nếu ứng dụng Codex đang sử dụng phiên này, trước tiên hãy đóng cửa sổ phiên.",
+ "删除会话": "Xóa phiên",
+ "删除供应商": "Xóa nhà cung cấp",
+ "删除已选": "Xóa đã chọn",
+ "删除扩展项": "Xóa mục nhập",
+ "删除模型": "Xóa mô hình",
+ "刷新": "Làm cho khỏe lại",
+ "刷新会话": "Làm mới phiên",
+ "刷新列表": "Làm mới danh sách",
+ "刷新市场": "Làm mới thị trường",
+ "刷新当前页面": "Làm mới trang hiện tại",
+ "刷新推荐": "Làm mới đề xuất",
+ "刷新本地": "Làm mới cục bộ",
+ "刷新项目": "Làm mới dự án",
+ "加入当前工作区": "Thêm vào không gian làm việc hiện tại",
+ "包含版本、路径、设置和平台信息": "Bao gồm phiên bản, đường dẫn, cài đặt và thông tin nền tảng",
+ "协议": "Giao thức",
+ "卸载入口": "Gỡ cài đặt điểm vào",
+ "卸载时移除 Codex++ 托管数据": "Xóa dữ liệu được quản lý Codex++ khi gỡ cài đặt",
+ "历史会话修复": "Sửa chữa phiên lịch sử",
+ "历史会话修复失败,请查看错误提示后重试。": "Sửa chữa phiên lịch sử không thành công. Kiểm tra thông báo lỗi và thử lại.",
+ "历史会话修复进度": "Tiến trình sửa chữa phiên lịch sử",
+ "压缩上下文大小": "Kích thước bối cảnh nén",
+ "原生菜单栏位置": "Vị trí thanh menu gốc",
+ "原生菜单汉化": "Bản địa hóa menu gốc",
+ "反馈问题": "Báo cáo sự cố",
+ "发现": "Đã phát hiện",
+ "发送 hi 测试": "Gửi bài kiểm tra 'xin chào'",
+ "取消": "Hủy bỏ",
+ "只保留非 MCP、Skills、Plugins 的跨供应商配置;工具与插件在独立页面管理。": "Chỉ giữ cấu hình của nhiều nhà cung cấp không phải là MCP/Kỹ năng/Plugins; các công cụ và plugin được quản lý trên một trang riêng.",
+ "只填写表头下面的内容,例如:\ncommand = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]": "Chỉ điền nội dung dưới tiêu đề, ví dụ:\nlệnh = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]",
+ "只能勾选已填写 Base URL / Key 的 API 供应商,聚合供应商不会作为成员。": "Chỉ có thể chọn nhà cung cấp API có URL / Khóa cơ sở; nhà cung cấp tổng hợp không thể là thành viên.",
+ "可更新": "Đã có bản cập nhật",
+ "同一对话保持一个成员,不同对话依次分配。": "Giữ một thành viên cho mỗi cuộc trò chuyện; các cuộc trò chuyện khác nhau được chỉ định lần lượt.",
+ "同步 Zed settings": "Đồng bộ cài đặt Zed",
+ "同步目标": "Mục tiêu đồng bộ hóa",
+ "名称": "Tên",
+ "启动 Codex App 时追加到默认 CDP 参数后。留空则保持默认启动行为。": "Được thêm vào sau các đối số CDP mặc định khi khởi chạy ứng dụng Codex. Để trống để giữ hành vi khởi chạy mặc định.",
+ "启动 Codex++": "Khởi chạy Codex++",
+ "启动任务": "Khởi động nhiệm vụ",
+ "启动前自动修复历史会话": "Tự động sửa chữa các phiên lịch sử trước khi ra mắt",
+ "启动时通过本地主进程调试端口汉化 Codex 原生菜单;不修改安装包。需重启 Codex 才生效。": "Bản địa hóa menu gốc Codex thông qua cổng gỡ lỗi quy trình chính cục bộ khi khởi chạy; không sửa đổi gói cài đặt. Yêu cầu khởi động lại Codex.",
+ "启用": "Cho phép",
+ "启用 Codex 图片覆盖层": "Bật lớp phủ hình ảnh Codex",
+ "启用 Codex增强": "Kích hoạt các cải tiến của Codex",
+ "启用 Windows Computer Use Guard": "Kích hoạt tính năng bảo vệ sử dụng máy tính Windows",
+ "启用供应商配置切换": "Cho phép chuyển đổi cấu hình nhà cung cấp",
+ "启用此扩展项": "Kích hoạt mục này",
+ "启用目标功能": "Kích hoạt tính năng mục tiêu",
+ "图片": "Hình ảnh",
+ "图片覆盖层": "Lớp phủ hình ảnh",
+ "在会话列表悬停显示删除按钮,并支持撤销。": "Hiển thị nút xóa khi di chuột trong danh sách phiên, có hỗ trợ hoàn tác.",
+ "在会话列表显示导出按钮,导出带时间戳的 Markdown。": "Hiển thị nút xuất trong danh sách phiên để xuất Markdown có dấu thời gian.",
+ "在 Codex 页面显示可拖动的后续建议浮层;建议由单独配置的 Stepwise API 生成。": "Hiển thị lớp phủ đề xuất tiếp theo có thể kéo được trong trang Codex. Các đề xuất được tạo bởi API Stepwise riêng biệt.",
+ "在侧边栏会话标题前显示短 ID 和 UUIDv7 创建时间,方便定位历史会话。": "Hiển thị thời gian tạo ID và UUIDv7 ngắn trước tiêu đề phiên trong thanh bên để giúp xác định các phiên trước đây.",
+ "基础设置": "Cài đặt cơ bản",
+ "填写中转服务 Base URL": "Nhập URL cơ sở của dịch vụ chuyển tiếp",
+ "复制": "Sao chép",
+ "复制 ssh:// URL": "Sao chép URL ssh://",
+ "复制失败": "Sao chép không thành công",
+ "复制报告": "Sao chép báo cáo",
+ "复用窗口": "Cửa sổ tái sử dụng",
+ "多选": "Chọn nhiều lần",
+ "失败": "Thất bại",
+ "失败切换": "Chuyển đổi dự phòng",
+ "失败切换会保留成员顺序,优先使用第一个可用供应商。": "Chuyển đổi dự phòng duy trì trật tự thành viên, ưu tiên nhà cung cấp sẵn có đầu tiên.",
+ "如果使用官方模式或官方混入 API 模式,通常不需要开启插件市场解锁。": "Nếu bạn sử dụng chế độ chính thức hoặc chế độ API hỗn hợp chính thức, bạn thường không cần mở khóa thị trường plugin.",
+ "安装": "Cài đặt",
+ "安装 watcher": "cài đặt trình theo dõi",
+ "安装入口": "Cài đặt điểm vào",
+ "安装包更新失败,请查看错误提示后重试。": "Cập nhật trình cài đặt không thành công. Kiểm tra thông báo lỗi và thử lại.",
+ "安装包更新进度": "Tiến trình cập nhật trình cài đặt",
+ "安装维护": "Cài đặt & bảo trì",
+ "完整增强": "Nâng cao đầy đủ",
+ "官方": "Chính thức",
+ "官方中转站": "Tiếp sức chính thức",
+ "官方混入 API Key": "Khóa API hỗn hợp chính thức",
+ "官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的 auth.json 后再切换。": "API hỗn hợp chính thức không được lưu trữ OPENAI_API_KEY trong auth.json. Xóa auth.json của nhà cung cấp này trước khi chuyển đổi.",
+ "官方登录": "Đăng nhập chính thức",
+ "官方登录模式": "Chế độ đăng nhập chính thức",
+ "对话居中宽度": "Chiều rộng cuộc trò chuyện được căn giữa",
+ "导入 Codex++ 供应商": "Nhập nhà cung cấp Codex++",
+ "尚未刷新": "Chưa được làm mới",
+ "尚未加载推荐内容": "Đề xuất chưa được tải",
+ "尚未检查 Codex 应用路径。": "Đường dẫn ứng dụng Codex chưa được kiểm tra.",
+ "尚未检查 GitHub Release;更新会下载并启动安装包。": "Bản phát hành GitHub chưa được kiểm tra; cập nhật các bản tải xuống và khởi chạy trình cài đặt.",
+ "尚未生成诊断报告。": "Chưa có báo cáo chẩn đoán nào được tạo.",
+ "尚未运行安装包更新。": "Bản cập nhật trình cài đặt chưa chạy.",
+ "尚未运行历史会话修复。": "Sửa chữa phiên lịch sử chưa chạy.",
+ "尚未运行插件市场修复。": "Sửa chữa thị trường plugin chưa chạy.",
+ "尚未检查官方远端插件缓存。": "Bộ đệm plugin từ xa chính thức chưa được kiểm tra.",
+ "正在检查内置官方远端插件缓存…": "Đang kiểm tra bộ nhớ đệm của plugin từ xa chính thức được nhúng…",
+ "正在释放内置远端插件快照…": "Đang trích xuất ảnh chụp nhanh plugin từ xa được nhúng…",
+ "正在注册官方远端插件市场…": "Đăng ký thị trường plugin từ xa chính thức…",
+ "正在刷新官方远端插件缓存状态…": "Đang làm mới trạng thái bộ đệm của plugin từ xa chính thức…",
+ "正在处理…": "Xử lý…",
+ "工具与插件": "Công cụ & plugin",
+ "已切回官方登录;Codex增强已设为兼容增强。": "Chuyển về đăng nhập chính thức; Các cải tiến của Codex được đặt thành tương thích.",
+ "已切换到纯 API;Codex增强已设为完整增强。": "Đã chuyển sang API thuần túy; Các cải tiến của Codex được đặt ở mức đầy đủ.",
+ "已切换到聚合供应商;真实对话会按所选策略轮转成员。": "Chuyển sang nhà cung cấp tổng hợp; các cuộc trò chuyện thực sự xoay vòng thành viên theo chiến lược đã chọn.",
+ "已刷新 Codex 应用、入口和 Watcher 状态。": "Ứng dụng Codex, điểm truy cập và trạng thái người theo dõi được làm mới.",
+ "已受理": "Đã chấp nhận",
+ "已安装": "Đã cài đặt",
+ "已归档": "Đã lưu trữ",
+ "已打开聚合供应商详情;请先添加或完善至少 1 个普通 API 供应商的 Base URL / Key,再勾选为成员。": "Đã mở chi tiết nhà cung cấp tổng hợp; trước tiên hãy thêm hoặc hoàn thành URL cơ sở/Khóa của ít nhất 1 nhà cung cấp API thông thường, sau đó chọn nhà cung cấp đó làm thành viên.",
+ "已找到": "Thành lập",
+ "已按此供应商使用官方登录,并混入 API Key;Codex增强已设为兼容增强。": "Sử dụng thông tin đăng nhập chính thức cho nhà cung cấp này có kèm theo Khóa API; Các cải tiến của Codex được đặt thành tương thích.",
+ "已按此供应商切回官方登录;Codex增强已设为兼容增强。": "Chuyển về đăng nhập chính thức cho nhà cung cấp này; Các cải tiến của Codex được đặt thành tương thích.",
+ "已按此供应商切换到纯 API;Codex增强已设为完整增强。": "Đã chuyển sang API thuần túy cho nhà cung cấp này; Các cải tiến của Codex được đặt ở mức đầy đủ.",
+ "已检测": "Đã phát hiện",
+ "已注册": "Đăng ký",
+ "已缓存未注册": "Đã lưu vào bộ nhớ đệm, chưa được đăng ký",
+ "已清除保存路径,后续启动会回到自动探测。": "Đã xóa đường dẫn đã lưu; các lần phóng trong tương lai sẽ quay trở lại chế độ tự động phát hiện.",
+ "已登录": "Đã đăng nhập",
+ "已禁用": "Tàn tật",
+ "已选择": "Đã chọn",
+ "市场状态": "trạng thái thị trường",
+ "市场脚本": "Tập lệnh Marketplace",
+ "序列化字段": "Các trường được tuần tự hóa",
+ "应用路径已保存,之后启动会自动复用。": "Đã lưu đường dẫn ứng dụng; những lần ra mắt trong tương lai sẽ tự động tái sử dụng nó.",
+ "应用路径留空时使用已保存路径;没有保存路径时使用自动探测": "Khi đường dẫn ứng dụng trống, đường dẫn đã lưu sẽ được sử dụng; không có đường dẫn đã lưu, tính năng tự động phát hiện sẽ được sử dụng",
+ "应用路径覆盖": "Ghi đè đường dẫn ứng dụng",
+ "开启": "TRÊN",
+ "开启后,通过 Codex++ 启动 Codex 前自动整理一次旧对话的归属标记。": "Khi bật, hãy dọn dẹp các thẻ quyền sở hữu của các cuộc hội thoại cũ một lần trước khi khởi chạy Codex thông qua Codex++.",
+ "强制中文界面": "Buộc giao diện người dùng Trung Quốc",
+ "强制启用 Codex App 内置 zh-CN 语言包,避免 Statsig/VPN 不通时回退英文。需重启 Codex 才能完整生效。": "Buộc gói ngôn ngữ zh-CN tích hợp của ứng dụng Codex tránh chuyển về tiếng Anh khi không thể truy cập Statsig/VPN. Yêu cầu khởi động lại Codex để áp dụng đầy đủ.",
+ "当前": "Hiện hành",
+ "当前 provider": "nhà cung cấp hiện tại",
+ "当前不会写入 Codex config.toml / auth.json。打开供应商配置总开关后再切换。": "Codex config.toml / auth.json sẽ không được viết ngay bây giờ. Bật công tắc chính cấu hình nhà cung cấp trước khi chuyển đổi.",
+ "当前为": "Hiện nay",
+ "当前为兼容增强模式,插件市场解锁不会启用;其他页面功能仍可用。": "Hiện đang ở chế độ nâng cao tương thích; tính năng mở khóa thị trường plugin chưa được bật nhưng các tính năng khác của trang vẫn hoạt động.",
+ "当前会话": "Phiên hiện tại",
+ "当前使用中:打开时从 ~/.codex/auth.json 回填,保存后会作为此供应商 auth 存档": "Hiện đang được sử dụng: được chèn lấp từ ~/.codex/auth.json khi mở; lưu trữ nó dưới dạng kho lưu trữ xác thực của nhà cung cấp này",
+ "当前供应商 config.toml 里没有可提取的通用配置。": "config.toml của nhà cung cấp hiện tại không có cấu hình chung có thể trích xuất được.",
+ "当前供应商切换后会写入的预览;上下文开关变化会立即反映": "Xem trước những gì nhà cung cấp hiện tại viết sau khi chuyển đổi; chuyển đổi bối cảnh được phản ánh ngay lập tức",
+ "当前供应商还没有完整 config.toml / API Key 存档。": "Nhà cung cấp hiện tại chưa có kho lưu trữ config.toml/API Key hoàn chỉnh.",
+ "当前共有": "Hiện tại có",
+ "当前未登录官方账号,也未配置混入 API 的 Base URL / Key。": "Chưa đăng nhập vào tài khoản chính thức và không có URL/Khóa cơ sở API hỗn hợp được định cấu hình.",
+ "当前未登录官方账号;切到官方登录模式后仍需要先在 Codex/ChatGPT 登录。": "Chưa đăng nhập vào tài khoản chính thức; sau khi chuyển sang chế độ đăng nhập chính thức bạn vẫn cần đăng nhập qua Codex/ChatGPT trước.",
+ "当前未登录官方账号;官方登录混入 API Key 需要先登录官方账号。": "Chưa đăng nhập vào tài khoản chính thức; đăng nhập chính thức bằng Khóa API hỗn hợp yêu cầu đăng nhập vào tài khoản chính thức trước.",
+ "当前正在使用": "Hiện đang được sử dụng",
+ "当前识别": "Hiện đã phát hiện",
+ "当前还没有填写混入 API 的 Base URL / Key。": "URL/Khóa cơ sở API hỗn hợp chưa được điền vào.",
+ "当前进程": "Quá trình hiện tại",
+ "当前配置 provider": "Nhà cung cấp được cấu hình hiện tại",
+ "快捷方式修复": "Sửa chữa lối tắt",
+ "快捷方式写入系统实际桌面位置,不使用写死桌面路径": "Các phím tắt được ghi vào vị trí màn hình thực tế của hệ thống, không phải đường dẫn màn hình được mã hóa cứng",
+ "快速启动": "Khởi động nhanh",
+ "总权重": "Tổng trọng lượng",
+ "成员供应商": "Nhà cung cấp thành viên",
+ "成员数量": "Số thành viên",
+ "或": "hoặc",
+ "手动": "Thủ công",
+ "手动启动": "Khởi chạy thủ công",
+ "打开": "Mở",
+ "打开 JOJO Code": "Mở mã JOJO",
+ "打开关于": "Mở Giới thiệu",
+ "打开链接": "Mở liên kết",
+ "打开项目主页": "Mở trang chủ dự án",
+ "扩展项": "lối vào",
+ "批量删除会话": "Xóa phiên hàng loạt",
+ "把 Codex++ 菜单插入 Codex 顶部原生菜单栏。": "Chèn menu Codex++ vào thanh menu gốc trên cùng của Codex.",
+ "把主对话和输入框限制到固定最大宽度,适合大屏阅读。": "Giới hạn cuộc trò chuyện chính và hộp nhập liệu ở độ rộng tối đa cố định, phù hợp để đọc trên màn hình lớn.",
+ "把会话移动到普通对话或其他本地项目。": "Chuyển phiên sang cuộc trò chuyện thông thường hoặc dự án địa phương khác.",
+ "投稿": "Nộp",
+ "拖动排序": "Kéo để sắp xếp lại",
+ "按对话轮转": "Vòng tròn cho mỗi cuộc trò chuyện",
+ "按对话轮转会让同一对话尽量保持固定成员,降低上下文漂移。": "Vòng tròn trên mỗi cuộc trò chuyện sẽ giữ cùng một cuộc trò chuyện với một thành viên cố định nếu có thể, giúp giảm tình trạng lệch ngữ cảnh.",
+ "按成员权重分配请求,权重越高承担越多。": "Phân phối yêu cầu theo trọng lượng thành viên; trọng lượng cao hơn mất nhiều hơn.",
+ "按成员顺序请求,失败后切到下一个供应商。": "Yêu cầu các thành viên theo thứ tự, chuyển sang nhà cung cấp tiếp theo nếu không thành công.",
+ "按更新时间倒序显示": "Sắp xếp theo thời gian cập nhật, mới nhất xếp trước",
+ "按请求轮转": "Vòng tròn theo yêu cầu",
+ "按请求轮转会逐请求切换成员,适合供应商能力接近的场景。": "Theo yêu cầu, chuyển đổi vòng tròn các thành viên theo yêu cầu, phù hợp với các nhà cung cấp có khả năng tương tự.",
+ "接入模式": "Chế độ truy cập",
+ "推荐内容": "Khuyến nghị",
+ "提取当前供应商配置": "Trích xuất cấu hình nhà cung cấp hiện tại",
+ "插件": "Plugin",
+ "插件列表全量展示": "Hiển thị danh sách plugin đầy đủ",
+ "插件市场修复": "Sửa chữa thị trường plugin",
+ "插件市场修复失败,请查看错误提示后重试。": "Sửa chữa thị trường plugin không thành công. Kiểm tra thông báo lỗi và thử lại.",
+ "插件市场修复进度": "Tiến trình sửa chữa thị trường plugin",
+ "插件市场解锁": "Mở khóa thị trường plugin",
+ "官方远端插件缓存": "Bộ đệm plugin từ xa chính thức",
+ "官方远端插件缓存进度": "Tiến trình bộ nhớ đệm plugin từ xa chính thức",
+ "官方远端插件缓存修复失败,请查看错误提示后重试。": "Sửa chữa bộ nhớ đệm plugin từ xa chính thức không thành công. Kiểm tra thông báo lỗi và thử lại.",
+ "使用 Codex++ 内置快照补齐远端插件,API 模式也可显示和安装 Product Design 插件。": "Sử dụng ảnh chụp nhanh Codex++ được nhúng để thêm plugin từ xa, nhờ đó chế độ API cũng có thể hiển thị và cài đặt plugin Thiết kế Sản phẩm.",
+ "搜索供应商…": "Tìm kiếm nhà cung cấp…",
+ "数据库": "Cơ sở dữ liệu",
+ "新增": "Thêm vào",
+ "新建供应商需要先保存到列表": "Nhà cung cấp mới phải được lưu vào danh sách trước",
+ "新机器没有本地插件市场时,可从 openai/plugins 初始化到当前 CODEX_HOME。": "Trên máy mới không có thị trường plugin cục bộ, hãy khởi tạo nó thành CODEX_HOME hiện tại từ openai/plugin.",
+ "新窗口": "Cửa sổ mới",
+ "日志已刷新": "Đã làm mới nhật ký",
+ "日志已复制。": "Đã sao chép nhật ký.",
+ "时间": "Thời gian",
+ "释放并注册内置缓存": "Trích xuất và đăng ký bộ nhớ đệm nhúng",
+ "显示服务模式切换按钮;Fast 仅支持 gpt-5.4 / gpt-5.5,其他模型按 Standard 发送。": "Hiển thị nút chuyển đổi cấp dịch vụ; Fast chỉ hỗ trợ gpt-5.4 / gpt-5.5, các mẫu khác được gửi dưới dạng Tiêu chuẩn.",
+ "普通推荐": "Khuyến nghị thường xuyên",
+ "暂无": "Không có",
+ "暂无启动状态。": "Chưa có trạng thái khởi chạy.",
+ "暂无描述。": "Không có mô tả.",
+ "暂无日志。": "Không có nhật ký.",
+ "暂无普通推荐。": "Không có khuyến nghị thường xuyên.",
+ "暂无状态文件": "Không có tập tin trạng thái",
+ "暂无赞助商推荐。": "Không có đề xuất nhà tài trợ.",
+ "暂无项目。": "Không có dự án.",
+ "更多选项": "Nhiều lựa chọn hơn",
+ "更新": "Cập nhật",
+ "更新安装": "Cập nhật cài đặt",
+ "最新版本": "Phiên bản mới nhất",
+ "最近启动": "Ra mắt gần đây",
+ "最近打开": "Mới mở gần đây",
+ "最近日志": "Nhật ký gần đây",
+ "未发现可导入供应商": "Không tìm thấy nhà cung cấp có thể nhập khẩu nào",
+ "未发现用户脚本。": "Không tìm thấy tập lệnh người dùng.",
+ "未命名会话": "Phiên không có tiêu đề",
+ "未命名供应商": "Nhà cung cấp không có tiêu đề",
+ "未命名聚合供应商": "Nhà cung cấp tổng hợp không có tiêu đề",
+ "未填写": "Không điền vào",
+ "未填写 URL": "Không có URL nào được điền vào",
+ "未安装": "Chưa được cài đặt",
+ "未实现": "Chưa được triển khai",
+ "未归档": "Chưa được lưu trữ",
+ "未检查": "Chưa được kiểm tra",
+ "未检测到": "Không được phát hiện",
+ "未检测到 Codex 应用版本。": "Phiên bản ứng dụng Codex không được phát hiện.",
+ "未发现缓存": "Không tìm thấy bộ đệm",
+ "未发现本地缓存;点击按钮会从 Codex++ 内置快照释放并注册,无需官方账号预缓存。": "Không tìm thấy bộ đệm cục bộ. Nhấp vào nút để trích xuất và đăng ký ảnh chụp nhanh Codex++ được nhúng; không yêu cầu bộ nhớ đệm trước của tài khoản chính thức.",
+ "未知": "Không xác định",
+ "未知作者": "Tác giả không xác định",
+ "未知来源": "Nguồn không xác định",
+ "未知版本": "Phiên bản không xác định",
+ "未记录路径": "Không có đường dẫn nào được ghi lại",
+ "未记录项目路径": "Không có đường dẫn dự án nào được ghi lại",
+ "未读取到本地会话,或当前 SQLite 会话库不存在。": "Không có phiên cục bộ nào được đọc hoặc cơ sở dữ liệu phiên SQLite hiện tại không tồn tại.",
+ "本地 Codex 增强、管理工具和安装包维护": "Cải tiến Codex cục bộ, công cụ quản lý và bảo trì gói cài đặt",
+ "本地会话": "Phiên cục bộ",
+ "本地整体": "Tổng thể địa phương",
+ "本地脚本": "Tập lệnh cục bộ",
+ "权重": "Cân nặng",
+ "权重轮转": "Vòng tròn có trọng số",
+ "权重轮转会读取每个成员的权重值,权重越高的成员获得更多请求。": "Vòng tròn có trọng số sẽ đọc cân nặng của từng thành viên; thành viên có trọng lượng cao hơn nhận được nhiều yêu cầu hơn.",
+ "查看、删除和修复 Codex 本地会话": "Xem, xóa và sửa chữa các phiên cục bộ Codex",
+ "检查": "Kiểm tra",
+ "检查与修复": "Kiểm tra & sửa chữa",
+ "检查入口、Codex 应用和 Watcher 状态": "Kiểm tra điểm vào, ứng dụng Codex và trạng thái người theo dõi",
+ "检查配置、模型列表和一次真实请求,定位供应商不可用原因。": "Kiểm tra cấu hình, danh sách model và một yêu cầu thực tế để tìm hiểu lý do tại sao không có nhà cung cấp.",
+ "检查完成": "Kiểm tra hoàn tất",
+ "检查更新": "Kiểm tra các bản cập nhật",
+ "检查问题、启动与快速修复": "Kiểm tra sự cố, khởi chạy và khắc phục nhanh",
+ "诊断供应商": "Nhà cung cấp chẩn đoán",
+ "检测": "Phát hiện",
+ "检测到 OPENAI 环境变量": "Đã phát hiện các biến môi trường OPENAI",
+ "检测到来自网页的供应商配置导入请求,确认后会写入本机 Codex++ 管理工具。": "Đã phát hiện yêu cầu nhập cấu hình nhà cung cấp từ web; xác nhận ghi nó vào trình quản lý Codex++ của máy này.",
+ "概览": "Tổng quan",
+ "概览只展示关键问题,具体配置在对应页面处理": "Phần tổng quan chỉ hiển thị các vấn đề chính; cấu hình cụ thể được xử lý trên các trang có liên quan",
+ "概览已检查": "Đã kiểm tra tổng quan",
+ "模型列表": "Danh sách người mẫu",
+ "模型名称": "Tên mẫu",
+ "模型白名单解锁": "Mở khóa danh sách trắng mô hình",
+ "模式": "Cách thức",
+ "模式。": "cách thức.",
+ "正在下载安装包…": "Đang tải xuống trình cài đặt…",
+ "正在下载插件市场快照…": "Đang tải xuống ảnh chụp nhanh thị trường plugin…",
+ "正在修复…": "Đang sửa chữa…",
+ "正在修复历史会话": "Sửa chữa các phiên lịch sử",
+ "正在准备安装包下载…": "Đang chuẩn bị tải xuống trình cài đặt…",
+ "正在启动安装包…": "Đang khởi chạy trình cài đặt…",
+ "正在写入 Codex 配置…": "Đang viết cấu hình Codex…",
+ "正在写入修复与备份…": "Viết sửa chữa và sao lưu…",
+ "正在删除…": "Đang xóa…",
+ "正在扫描历史会话与索引…": "Đang quét các phiên và chỉ mục lịch sử…",
+ "正在检查会话 provider 标记…": "Đang kiểm tra thẻ nhà cung cấp phiên…",
+ "正在检查本地插件市场…": "Đang kiểm tra thị trường plugin địa phương…",
+ "正在获取 GitHub Release 信息…": "Đang tìm nạp thông tin phát hành GitHub…",
+ "正在解压并校验插件文件…": "Đang trích xuất và xác minh các tệp plugin…",
+ "正在连接 openai/plugins…": "Đang kết nối với openai/plugin…",
+ "正常": "ĐƯỢC RỒI",
+ "此上游会通过本地 127.0.0.1:57321 转成 Responses API,需要从 Codex++ 启动 Codex。": "Luồng ngược dòng này được chuyển đổi thành API phản hồi thông qua 127.0.0.1:57321 cục bộ, yêu cầu khởi chạy Codex từ Codex++.",
+ "此供应商会保留官方登录模式,并把请求混入当前 API Key;Codex增强仍使用兼容模式。": "Nhà cung cấp này giữ chế độ đăng nhập chính thức và trộn Khóa API hiện tại vào các yêu cầu; Các cải tiến của Codex vẫn ở chế độ tương thích.",
+ "此供应商会切回官方登录模式,使用 ChatGPT 官方账号,不写入 API Key。": "Nhà cung cấp này chuyển về chế độ đăng nhập chính thức bằng tài khoản ChatGPT chính thức mà không cần viết Khóa API.",
+ "此供应商会同时写入 config.toml 和 auth.json;API Key 也会注入到 provider bearer token。": "Nhà cung cấp này viết cả config.toml và auth.json; Khóa API cũng được đưa vào mã thông báo mang của nhà cung cấp.",
+ "每次请求按成员顺序切换,适合均匀摊请求量。": "Chuyển đổi thành viên theo thứ tự trên mỗi yêu cầu, tốt cho việc phân bổ đều khối lượng yêu cầu.",
+ "每行一个参数,例如 --force_high_performance_gpu。不需要填写 open 或 --args。": "Một đối số trên mỗi dòng, ví dụ: --force_high_performance_gpu. Không cần bao gồm open hoặc --args.",
+ "每行一个模型;上下文窗口可填": "Một mô hình trên mỗi dòng; cửa sổ ngữ cảnh có thể",
+ "没有匹配「": "Không có nhà cung cấp nào phù hợp với “",
+ "浅色": "Ánh sáng",
+ "测试模型": "Mô hình thử nghiệm",
+ "消息": "Tin nhắn",
+ "深色": "Tối tăm",
+ "混入 API": "API hỗn hợp",
+ "混入 API KEY": "Trộn vào API KEY",
+ "混入 API Key": "Kết hợp khóa API",
+ "添加供应商": "Thêm nhà cung cấp",
+ "添加模型": "Thêm mô hình",
+ "添加聚合供应商": "Thêm nhà cung cấp tổng hợp",
+ "清空选择": "Xóa lựa chọn",
+ "清除保存路径": "Xóa đường dẫn đã lưu",
+ "点击刷新会话读取本地数据库": "Bấm vào Làm mới phiên để đọc cơ sở dữ liệu cục bộ",
+ "点击刷新市场加载远程脚本。": "Nhấp vào Làm mới Marketplace để tải tập lệnh từ xa.",
+ "版本信息、项目链接、GitHub Release 更新、日志与诊断": "Thông tin phiên bản, liên kết dự án, Cập nhật phát hành GitHub, nhật ký và chẩn đoán",
+ "状态": "Trạng thái",
+ "独立管理 Codex 的 MCP、Skills、Plugins;切换任意供应商都会带上。": "Quản lý MCP, Kỹ năng và Plugin của Codex một cách độc lập; họ sẽ chuyển tiếp bất cứ khi nào bạn chuyển đổi nhà cung cấp.",
+ "独立管理 MCP、Skills、Plugins": "Quản lý độc lập MCP, Kỹ năng và Plugin",
+ "环境变量": "Biến môi trường",
+ "环境变量检测": "Phát hiện biến môi trường",
+ "环境变量清理": "Dọn dẹp biến môi trường",
+ "用户": "người dùng",
+ "用户环境": "Môi trường người dùng",
+ "界面主题": "chủ đề giao diện người dùng",
+ "留空不改写,例如 160000": "Để trống để giữ nguyên, ví dụ: 160000",
+ "留空不改写,例如 200000": "Để trống để giữ nguyên, ví dụ: 200000",
+ "留空使用默认值": "Để trống để sử dụng mặc định",
+ "登录状态": "Trạng thái đăng nhập",
+ "确认删除": "Xác nhận xóa",
+ "确认导入": "Xác nhận nhập",
+ "禁用": "Vô hiệu hóa",
+ "禁用此扩展项": "Vô hiệu hóa mục này",
+ "移除 watcher": "Xóa người theo dõi",
+ "移除最近记录": "Xóa khỏi gần đây",
+ "立刻修复历史会话": "Sửa chữa các phiên lịch sử ngay bây giờ",
+ "第三方": "Bên thứ ba",
+ "策略": "Chiến lược",
+ "管理 API 供应商、协议、Key 与配置文件": "Quản lý nhà cung cấp API, giao thức, khóa và tệp cấu hình",
+ "管理 Codex SSH 项目并加入 Zed workspace": "Quản lý các dự án Codex SSH và thêm chúng vào không gian làm việc của Zed",
+ "管理工具入口": "Điểm vào của người quản lý",
+ "管理控制台": "Bảng điều khiển quản lý",
+ "管理控制台入口": "Điểm vào bảng điều khiển quản lý",
+ "类型": "Kiểu",
+ "粘贴修复": "Dán sửa lỗi",
+ "索引": "chỉ mục",
+ "纯 API": "API thuần túy",
+ "纯 API 就绪:会同时写入 config.toml 和 auth.json。": "API thuần túy đã sẵn sàng: ghi cả config.toml và auth.json.",
+ "纯 API 模式": "Chế độ API thuần túy",
+ "纯 API 配置未完整写入:请检查此供应商是否有 OPENAI_API_KEY,且 config.toml 是否包含 model_provider / provider / base_url。": "Cấu hình API thuần túy chưa đầy đủ: hãy kiểm tra xem nhà cung cấp này có OPENAI_API_KEY hay không và config.toml có bao gồm model_provider/nhà cung cấp/base_url hay không.",
+ "维护 Codex++ 自己的远程项目最近列表。": "Duy trì danh sách các dự án từ xa gần đây của Codex++.",
+ "编辑": "Biên tập",
+ "编辑后保存列表,再切换模式时会使用新配置": "Sau khi chỉnh sửa, lưu danh sách; cấu hình mới sẽ được sử dụng vào lần tiếp theo bạn chuyển chế độ",
+ "编辑扩展项": "Chỉnh sửa mục nhập",
+ "缺失": "Mất tích",
+ "缺少 Codex++ 静默启动快捷方式时可在安装维护页修复。": "Khi thiếu phím tắt khởi chạy im lặng Codex++, hãy sửa nó trên trang Cài đặt & Bảo trì.",
+ "缺少管理工具快捷方式时可在安装维护页修复。": "Khi thiếu phím tắt trình quản lý, hãy sửa nó trên trang Cài đặt & Bảo trì.",
+ "聚合": "Tổng hợp",
+ "聚合/中转": "Tổng hợp / chuyển tiếp",
+ "聚合供应商": "Nhà cung cấp tổng hợp",
+ "聚合供应商会在真实对话中轮转成员,请测试成员供应商": "Các nhà cung cấp tổng hợp luân chuyển thành viên trong các cuộc trò chuyện thực tế; thay vào đó hãy kiểm tra các nhà cung cấp thành viên",
+ "聚合供应商只保存成员和策略配置,成员来自已有 API 供应商;切为当前后会通过本地协议代理轮转请求。": "Các nhà cung cấp tổng hợp chỉ lưu trữ cấu hình chiến lược và thành viên được lấy từ các nhà cung cấp API hiện có; sau khi hoạt động, các yêu cầu sẽ chuyển qua proxy giao thức cục bộ.",
+ "聚合供应商至少需要勾选 1 个已填写 Base URL / Key 的 API 供应商。": "Một nhà cung cấp tổng hợp cần có ít nhất 1 nhà cung cấp API được chọn có điền URL/Khóa cơ sở.",
+ "聚合策略": "Chiến lược tổng hợp",
+ "聚合配置只引用已有供应商,不复制 Key 和配置文件": "Cấu hình tổng hợp chỉ tham chiếu các nhà cung cấp hiện có; nó không sao chép khóa hoặc tập tin cấu hình",
+ "脚本市场": "Chợ kịch bản",
+ "自动接管": "Tự động tiếp quản",
+ "覆盖图片": "Hình ảnh lớp phủ",
+ "背景适配方式": "Chế độ phù hợp với nền",
+ "填充": "Đổ đầy",
+ "适应": "Phù hợp",
+ "拉伸": "Kéo dài",
+ "平铺": "Ngói",
+ "居中": "Trung tâm",
+ "记录最近打开": "Bản ghi được mở gần đây",
+ "设为当前": "Đặt như hiện tại",
+ "设置": "Cài đặt",
+ "设置保存": "Đã lưu cài đặt",
+ "设置已加载": "Đã tải cài đặt",
+ "设置重置": "Đặt lại cài đặt",
+ "诊断已生成": "Đã tạo chẩn đoán",
+ "诊断报告": "Báo cáo chẩn đoán",
+ "诊断报告已复制。": "Đã sao chép báo cáo chẩn đoán.",
+ "点击后会打开诊断弹框,按步骤检查供应商。": "Nhấp để mở hộp thoại chẩn đoán và kiểm tra nhà cung cấp từng bước.",
+ "正在诊断供应商,请稍候。": "Nhà cung cấp dịch vụ chẩn đoán, vui lòng đợi.",
+ "诊断已完成。": "Chẩn đoán hoàn tất.",
+ "诊断中": "Chẩn đoán",
+ "异常": "Lỗi",
+ "完成": "Hoàn thành",
+ "配置完整性": "Tính toàn vẹn của cấu hình",
+ "等待检查 Base URL / API Key。": "Đang chờ kiểm tra URL cơ sở/Khóa API.",
+ "等待检查 /v1/models。": "Đang chờ kiểm tra /v1/models.",
+ "真实请求": "Yêu cầu thực sự",
+ "等待发送一次测试请求。": "Đang chờ gửi một yêu cầu kiểm tra.",
+ "处理建议": "Sự giới thiệu",
+ "等待生成建议。": "Đang chờ để tạo đề xuất.",
+ "正在检查配置完整性…": "Đang kiểm tra tính toàn vẹn của cấu hình…",
+ "该步骤未执行。": "Bước này không được chạy.",
+ "请先填写或选择应用路径。": "Trước tiên hãy điền hoặc chọn đường dẫn ứng dụng.",
+ "请先选择要删除的会话。": "Chọn các phiên để xóa đầu tiên.",
+ "读取 Codex 本地 SQLite 会话库,会删除数据库记录和对应 rollout 文件": "Đọc cơ sở dữ liệu phiên SQLite cục bộ của Codex; xóa các bản ghi cơ sở dữ liệu và các tập tin triển khai tương ứng",
+ "读取 cc-switch 供应商失败。": "Không đọc được nhà cung cấp cc-switch.",
+ "读取 ~/.cc-switch/cc-switch.db": "Đọc ~/.cc-switch/cc-switch.db",
+ "调用失败": "Cuộc gọi không thành công",
+ "资源": "Tài sản",
+ "赞助商推荐": "Khuyến nghị của nhà tài trợ",
+ "赞助商推荐与普通推荐": "Nhà tài trợ và khuyến nghị thường xuyên",
+ "输入中转服务的 API Key": "Nhập Khóa API dịch vụ chuyển tiếp",
+ "运行中": "Đang chạy",
+ "返回列表": "Quay lại danh sách",
+ "这些变量可能覆盖当前供应商写入的 config.toml / auth.json;CODEX_HOME 不会被清理。": "Các biến này có thể ghi đè config.toml/auth.json do nhà cung cấp hiện tại viết; CODEX_HOME sẽ không được dọn sạch.",
+ "进入插件页后自动连续展开“更多”,尽量一次显示完整插件列表。": "Tự động tiếp tục mở rộng 'Thêm' trên trang plugin để hiển thị danh sách plugin đầy đủ cùng một lúc.",
+ "进度": "Tiến triển",
+ "远程 SSH 文件引用可直接用 Zed Remote Development 打开。": "Các tham chiếu tệp SSH từ xa có thể được mở trực tiếp bằng Zed Remote Development.",
+ "远程脚本": "Tập lệnh từ xa",
+ "适合官方登录或官方混入 API Key;保留会话删除、导出、项目移动和用户脚本,关闭插件市场相关增强。": "Phù hợp với đăng nhập chính thức hoặc Khóa API hỗn hợp chính thức; tiếp tục xóa phiên, xuất, di chuyển dự án và tập lệnh người dùng, đồng thời vô hiệu hóa các cải tiến liên quan đến thị trường plugin.",
+ "适合纯 API;启用插件市场、会话删除导出、项目移动等全部页面能力。": "Phù hợp với API thuần túy; cho phép tất cả các khả năng của trang bao gồm thị trường plugin, xóa/xuất phiên và di chuyển dự án.",
+ "选择 Codex 应用目录": "Chọn thư mục ứng dụng Codex",
+ "选择 Codex.exe": "Chọn Codex.exe",
+ "选择 Codex.exe 或 Codex.app": "Chọn Codex.exe hoặc Codex.app",
+ "选择 Codex.exe、Codex.app、app 目录或解包目录": "Chọn Codex.exe, Codex.app, thư mục ứng dụng hoặc thư mục đã giải nén",
+ "选择 png / jpg / webp / gif / bmp": "Chọn png/jpg/webp/gif/bmp",
+ "选择会话": "Chọn phiên",
+ "选择图片": "Chọn hình ảnh",
+ "选择已有供应商作为成员,保存后写入 settings payload": "Chọn các nhà cung cấp hiện có làm thành viên; lưu ghi chúng vào tải trọng cài đặt",
+ "选择应用目录": "Chọn thư mục ứng dụng",
+ "选择覆盖图片": "Chọn hình ảnh lớp phủ",
+ "通用配置文件": "Tệp cấu hình chung",
+ "配置": "Cấu hình",
+ "配置文件": "Tập tin cấu hình",
+ "配置模型": "Mô hình cấu hình",
+ "重启 Codex++": "Khởi động lại Codex++",
+ "重新安装": "Cài đặt lại",
+ "重新生成": "tái sinh",
+ "重置背景": "Đặt lại nền",
+ "静默启动入口": "Điểm khởi động im lặng",
+ "项目地址": "URL dự án",
+ "额外参数": "Đối số bổ sung",
+ "高级选项,默认关闭;当前实现不主动改写 Zed settings。": "Tùy chọn nâng cao, tắt theo mặc định; việc triển khai hiện tại không tích cực sửa đổi cài đặt Zed.",
+ "默认中转": "Rơle mặc định",
+ "默认关闭;开启后启动 Codex 时会自动保留官方 Computer Use 插件所需的 config.toml、bundled 插件和 notify 配置。": "Tắt theo mặc định; khi được bật, việc khởi chạy Codex sẽ tự động lưu giữ config.toml, các plugin đi kèm và cấu hình thông báo theo yêu cầu của plugin Sử dụng Máy tính chính thức.",
+ "默认启动 Codex 时使用的模型名,请勿带后缀;上下文窗口请在下方「模型列表」中按模型单独配置。": "Tên model được sử dụng theo mặc định khi khởi chạy Codex; không bao gồm một hậu tố. Định cấu hình cửa sổ ngữ cảnh cho mỗi mô hình trong “Danh sách mô hình” bên dưới.",
+ "默认关闭;无 VPN 时可开启,让 Statsig 初始化快速失败,减少启动时长。需重启 Codex 才生效。": "Tắt theo mặc định; kích hoạt nó mà không cần VPN để quá trình khởi tạo Statsig không thành công nhanh chóng và giảm thời gian khởi chạy. Yêu cầu khởi động lại Codex.",
+ "默认打开策略": "Chiến lược mở mặc định",
+ "(": " (",
+ ")": ")",
+ ",可以从通用配置文件或这里新增。": "; bạn có thể thêm chúng từ tệp cấu hình chung hoặc tại đây.",
+ ",留空表示使用 Codex 默认长度。": "; để trống để sử dụng độ dài mặc định của Codex.",
+ ";这些条目独立于供应商保存,会写入所有供应商切换后的 config.toml。": "; các mục này được lưu độc lập với nhà cung cấp và được ghi vào config.toml sau khi chuyển sang bất kỳ nhà cung cấp nào.",
+};
+
+export const VI_TEMPLATE: Record = {
+ "\n...以及另外 {0} 个会话": "...và {0} phiên khác",
+ "{0} · {1} 个成员": "{0} · {1} thành viên",
+ "{0} 个": "{0}",
+ "{0} 个 Codex++ 可识别项目,默认策略:{1}": "{0} (các) dự án được Codex++ công nhận, chiến lược mặc định: {1}",
+ "{0} 个供应商": "{0} nhà cung cấp",
+ "{0} 个供应商配置;可拖动排序,点编辑进入详情": "{0} (các) cấu hình nhà cung cấp; kéo để sắp xếp lại, bấm chỉnh sửa để biết chi tiết",
+ "{0} 个市场脚本,已安装 {1} 个,本地整体 {2}": "{0} (các) tập lệnh thị trường, {1} đã cài đặt, tổng thể cục bộ {2}",
+ "{0} 个项目": "{0} dự án",
+ "{0} 副本": "{0} bản sao",
+ "{0} 条": "{0} mặt hàng",
+ "供应商 {0}": "Nhà cung cấp {0}",
+ "供应商「{0}」缺少独立 config.toml,已停止切换,避免继续显示上一套配置文件。请先在该供应商详情里保存 config.toml。": "Nhà cung cấp “{0}” thiếu config.toml riêng nên quá trình chuyển đổi đã bị dừng để tránh hiển thị các tệp cấu hình trước đó. Trước tiên hãy lưu config.toml trong thông tin chi tiết của nhà cung cấp này.",
+ "删除会话“{0}”?此操作会删除本地数据库记录和 rollout 文件,并创建备份。": "Xóa phiên “{0}”? Thao tác này sẽ xóa bản ghi cơ sở dữ liệu cục bộ và tệp triển khai, đồng thời tạo bản sao lưu.",
+ "删除脚本“{0}”?此操作会移除本地脚本文件。": "Xóa tập lệnh “{0}”? Thao tác này sẽ xóa tệp tập lệnh cục bộ.",
+ "删除这些环境变量?\n\n{0}\n\n删除前会写入备份。": "Xóa các biến môi trường này?\n\n{0}\n\nMột bản sao lưu được viết trước khi xóa.",
+ "删除选中的 {0} 个会话?此操作会删除本地数据库记录和 rollout 文件,并为每个会话创建备份。\n\n{1}{2}": "Xóa {0} phiên đã chọn? Thao tác này sẽ xóa các bản ghi cơ sở dữ liệu cục bộ và các tệp triển khai, đồng thời tạo bản sao lưu cho mỗi phiên.\n\n{1}{2}",
+ "发现 {0} 个 Codex 供应商": "Đã tìm thấy {0} nhà cung cấp Codex",
+ "发现新版本 {0}": "Đã có phiên bản mới {0}",
+ "官方登录已就绪:{0},会混入当前 API Key。": "Đăng nhập chính thức đã sẵn sàng: {0}, Khóa API hiện tại sẽ được trộn vào.",
+ "官方账号已登录:{0}。": "Tài khoản chính thức đã đăng nhập: {0}.",
+ "已删除 {0} 个会话。": "Đã xóa {0} phiên.",
+ "已删除 {0} 个,失败 {1} 个:{2}": "Đã xóa {0}, không thành công {1}: {2}",
+ "已加载 {0} 条推荐": "Đã tải {0} đề xuất",
+ "已同步到 {0}:修复 {1} 个会话文件,更新 {2} 行索引{3}。": "Đã đồng bộ hóa với {0}: đã sửa chữa {1} tệp phiên, đã cập nhật {2} hàng chỉ mục{3}.",
+ "已安装 {0}": "Đã cài đặt {0}",
+ "已缓存 {0} 个插件 / {1} 个技能。": "Đã lưu vào bộ nhớ đệm {0} plugin / {1} kỹ năng.",
+ "已运行 {0} 分钟": "Chạy được {0} phút",
+ "已运行 {0} 小时 {1} 分钟": "Chạy trong {0} giờ {1} phút",
+ "市场 · {0}": "Chợ · {0}",
+ "当前版本 {0}": "Phiên bản hiện tại {0}",
+ "打开选择器失败:{0}": "Không mở được bộ chọn: {0}",
+ "正在同步到 {0}…": "Đang đồng bộ hóa với {0}…",
+ "清单更新时间:{0}": "Bản kê khai được cập nhật lúc: {0}",
+ "留空使用默认:{0}": "Để trống để sử dụng mặc định: {0}",
+ "聚合供应商 {0}": "Nhà cung cấp tổng hợp {0}",
+ "聚合供应商已配置为{0},包含 {1} 个成员;真实对话会走本地代理轮转。": "Nhà cung cấp tổng hợp được định cấu hình là {0} với {1} thành viên; các cuộc hội thoại thực sự xoay vòng qua proxy cục bộ.",
+ "进程状态:{0}。是否要重新启动?": "Trạng thái xử lý: {0}. Khởi động lại?",
+ "选择会话 {0}": "Chọn phiên {0}",
+ "透明度 {0}%": "Độ mờ {0}%",
+ ",跳过 {0} 个占用文件": ", đã bỏ qua {0} tệp bị khóa",
+};
+
+export const VI_BACKEND: Record = {
+ "后端版本已读取。": "Đã tải phiên bản phụ trợ.",
+ "启动参数已读取。": "Khởi chạy các đối số đã được tải.",
+ "概览后台任务失败。": "Nhiệm vụ nền tổng quan không thành công.",
+ "概览已加载。": "Đã tải tổng quan.",
+ "启动任务已在后台开始,可稍后查看概览状态。": "Nhiệm vụ khởi động bắt đầu ở chế độ nền. Kiểm tra trạng thái tổng quan sau.",
+ "设置已加载。": "Đã tải cài đặt.",
+ "设置读取失败": "Không đọc được cài đặt",
+ "设置保存后重新读取失败": "Không thể tải lại cài đặt sau khi lưu",
+ "没有新的 cc-switch 供应商配置需要导入。": "Không có cấu hình nhà cung cấp cc-switch mới nào để nhập.",
+ "导入供应商配置后重新读取设置失败": "Không thể tải lại cài đặt sau khi nhập cấu hình nhà cung cấp",
+ "待确认供应商导入已读取。": "Đang chờ nhập nhà cung cấp.",
+ "没有待确认的供应商导入。": "Không có nhà cung cấp đang chờ nhập.",
+ "已取消供应商导入。": "Đã hủy nhập nhà cung cấp.",
+ "会话 ID 不能为空。": "ID phiên không được để trống.",
+ "推荐内容已加载。": "Đã tải đề xuất.",
+ "脚本市场已刷新。": "Thị trường tập lệnh được làm mới.",
+ "脚本 id 不能为空。": "ID tập lệnh không được để trống.",
+ "市场清单中未找到该脚本。": "Không tìm thấy tập lệnh trong bảng kê khai thị trường.",
+ "脚本已安装。": "Đã cài đặt tập lệnh.",
+ "脚本 key 不能为空。": "Khóa tập lệnh không được để trống.",
+ "脚本已启用。": "Đã bật tập lệnh.",
+ "脚本已禁用。": "Tập lệnh bị vô hiệu hóa.",
+ "脚本启停失败": "Không thể chuyển đổi tập lệnh",
+ "脚本已删除。": "Kịch bản đã bị xóa.",
+ "脚本删除失败": "Không xóa được tập lệnh",
+ "只允许打开 http 或 https 链接。": "Chỉ có thể mở liên kết http hoặc https.",
+ "已在系统浏览器打开链接。": "Liên kết được mở trong trình duyệt hệ thống.",
+ "安装入口": "Cài đặt điểm vào",
+ "卸载入口": "Gỡ cài đặt điểm vào",
+ "修复快捷方式": "Sửa chữa phím tắt",
+ "修复后重新读取设置失败": "Không thể tải lại cài đặt sau khi sửa chữa",
+ "插件市场需要初始化或注册。": "Thị trường plugin cần khởi tạo hoặc đăng ký.",
+ "插件市场已可用。": "Thị trường plugin có sẵn.",
+ "插件市场已从 openai/plugins 初始化并注册。": "Thị trường plugin được khởi tạo và đăng ký từ openai/plugin.",
+ "已注册本地插件市场。": "Đã đăng ký thị trường plugin địa phương.",
+ "插件市场已可用,无需修复。": "Thị trường plugin có sẵn; không cần sửa chữa.",
+ "官方远端插件缓存需要释放或注册。": "Bộ đệm plugin từ xa chính thức cần trích xuất hoặc đăng ký.",
+ "官方远端插件缓存已可用。": "Bộ đệm plugin từ xa chính thức có sẵn.",
+ "已释放并注册内置官方远端插件缓存。": "Đã trích xuất và đăng ký bộ nhớ đệm plugin từ xa chính thức được nhúng.",
+ "已注册官方远端插件缓存。": "Đã đăng ký bộ nhớ đệm plugin từ xa chính thức.",
+ "官方远端插件缓存已可用,无需修复。": "Bộ đệm plugin từ xa chính thức có sẵn; không cần sửa chữa.",
+ "发现可用更新。": "Cập nhật có sẵn.",
+ "当前已是最新版本。": "Đã có trên phiên bản mới nhất.",
+ "请先检查更新并选择可下载的 Release asset。": "Trước tiên hãy kiểm tra các bản cập nhật và chọn nội dung phát hành có thể tải xuống.",
+ "安装包已下载并启动,请按安装向导完成更新。": "Trình cài đặt đã được tải xuống và khởi chạy. Làm theo trình hướng dẫn thiết lập để hoàn tất cập nhật.",
+ "日志已读取。": "Đã tải nhật ký.",
+ "诊断报告已生成。": "Đã tạo báo cáo chẩn đoán.",
+ "设置已重置为默认值。": "Cài đặt lại về mặc định.",
+ "设置重置后重新读取失败": "Không thể tải lại cài đặt sau khi đặt lại",
+ "图片覆盖层设置已重置。": "Đặt lại cài đặt lớp phủ hình ảnh.",
+ "图片覆盖层重置后重新读取失败": "Không thể tải lại cài đặt sau khi đặt lại lớp phủ hình ảnh",
+ "已检测到 ChatGPT 登录状态。": "Đã phát hiện đăng nhập ChatGPT.",
+ "未检测到 ChatGPT 登录状态,请先在 Codex/ChatGPT 中正常登录。": "Không phát hiện đăng nhập ChatGPT. Vui lòng đăng nhập vào Codex/ChatGPT trước.",
+ "配置文件内容已读取。": "Đã tải nội dung tệp cấu hình.",
+ "未检测到会覆盖 Codex 供应商配置的 OPENAI 环境变量。": "Không tìm thấy biến môi trường OPENAI nào sẽ ghi đè cấu hình nhà cung cấp Codex.",
+ "检测到可能覆盖 Codex 供应商配置的 OPENAI 环境变量。": "Các biến môi trường OPENAI được phát hiện có thể ghi đè cấu hình nhà cung cấp Codex.",
+ "环境变量已按确认项删除;重新启动 Codex 后生效。": "Các biến môi trường đã bị xóa như đã được xác nhận. Khởi động lại Codex để các thay đổi có hiệu lực.",
+ "配置文件已保存。": "Đã lưu tập tin cấu hình.",
+ "供应商切换锁已损坏,请重启管理器后再试。": "Khóa chuyển đổi nhà cung cấp bị hỏng. Vui lòng khởi động lại trình quản lý và thử lại.",
+ "供应商已切换。": "Nhà cung cấp đã chuyển đổi.",
+ "当前供应商已不在配置列表中,已停止切换以避免覆盖用户改动。": "Nhà cung cấp hiện tại không còn trong danh sách cấu hình. Việc chuyển đổi đã dừng lại để tránh ghi đè những thay đổi của người dùng.",
+ "当前供应商配置已从 live 文件回填。": "Cấu hình nhà cung cấp hiện tại được chèn lấp từ các tệp trực tiếp.",
+ "工具与插件列表已读取。": "Đã tải danh sách công cụ và plugin.",
+ "通用配置已按兼容切换规则提取。": "Cấu hình chung được trích xuất bằng quy tắc chuyển đổi tương thích.",
+ "供应商配置总开关已关闭,未写入 config.toml / auth.json。": "Công tắc chính của cấu hình nhà cung cấp đang tắt. Không có gì được ghi vào config.toml/auth.json.",
+ "已按兼容切换规则切换供应商。": "Nhà cung cấp đã chuyển đổi bằng cách sử dụng các quy tắc tương thích.",
+ "未检测到 ChatGPT 登录状态": "Không phát hiện đăng nhập ChatGPT",
+ "未检测到 ChatGPT 登录状态,已停止写入中转配置。": "Không phát hiện đăng nhập ChatGPT. Cấu hình chuyển tiếp không được ghi.",
+ "中转配置已写入,密钥未在界面明文显示。": "Cấu hình chuyển tiếp được viết. Các khóa không được hiển thị dưới dạng văn bản gốc trong giao diện người dùng.",
+ "聚合供应商配置已写入,真实请求会由本地代理按策略轮转。": "Đã viết cấu hình nhà cung cấp tổng hợp. Các yêu cầu thực sự sẽ được proxy cục bộ luân chuyển theo chiến lược.",
+ "已清除 custom 中转 API 模式,并切换到官方 ChatGPT 登录模式。": "Đã xóa chế độ API chuyển tiếp tùy chỉnh. Đã chuyển sang chế độ đăng nhập ChatGPT chính thức.",
+ "纯 API 模式已写入:config.toml 已写入 custom provider,auth.json 已切换为当前供应商。": "Chế độ API thuần túy được viết: config.toml hiện có nhà cung cấp tùy chỉnh, auth.json đã chuyển sang nhà cung cấp hiện tại.",
+ "纯 API 配置写入后未检测到完整 custom provider,请检查 config.toml 和供应商 API Key。": "Sau khi viết cấu hình API thuần túy, không phát hiện thấy nhà cung cấp tùy chỉnh hoàn chỉnh nào. Vui lòng kiểm tra config.toml và Khóa API của nhà cung cấp.",
+ "供应商导入后重新读取设置失败": "Không thể tải lại cài đặt sau khi nhập nhà cung cấp",
+ "诊断日志已写入。": "Nhật ký chẩn đoán được viết.",
+ "未命名供应商": "Nhà cung cấp ẩn danh",
+ "响应内容为空": "Phản hồi trống",
+};
+
+export const VI_BACKEND_PATTERNS: Array<[RegExp, string]> = [
+ [new RegExp("^启动静默入口失败:(.+)$"), "Không thể khởi chạy điểm vào im lặng: $1"],
+ [new RegExp("^无法启动 (.+?):(.+)$"), "Không thể khởi chạy $1: $2"],
+ [new RegExp("^设置已保存。(.*)$"), "Đã lưu cài đặt.$1"],
+ [new RegExp("^保存设置失败:(.+)$"), "Không lưu được cài đặt: $1"],
+ [new RegExp("^已读取 cc-switch Codex 供应商配置:(\\d+) 个。$"), "Đọc (các) cấu hình nhà cung cấp Codex $1 cc-switch."],
+ [new RegExp("^读取 cc-switch 供应商配置失败:(.+)$"), "Không đọc được cấu hình nhà cung cấp cc-switch: $1"],
+ [new RegExp("^已从 cc-switch 导入供应商配置:(\\d+) 个。$"), "Đã nhập (các) cấu hình nhà cung cấp cc-switch $1."],
+ [new RegExp("^保存 cc-switch 供应商配置失败:(.+)$"), "Không lưu được cấu hình nhà cung cấp cc-switch: $1"],
+ [new RegExp("^已导入供应商配置:(.+)。$"), "Cấu hình nhà cung cấp đã nhập: $1."],
+ [new RegExp("^供应商配置已存在:(.+)。$"), "Cấu hình nhà cung cấp đã tồn tại: $1."],
+ [new RegExp("^导入供应商配置失败:(.+)$"), "Không thể nhập cấu hình nhà cung cấp: $1"],
+ [new RegExp("^取消供应商导入失败:(.+)$"), "Không hủy được việc nhập nhà cung cấp: $1"],
+ [new RegExp("^已读取 (\\d+) 个本地会话。$"), "Đọc (các) phiên địa phương $1."],
+ [new RegExp("^读取部分本地会话失败:(.+)$"), "Không đọc được một số phiên địa phương: $1"],
+ [new RegExp("^已读取 (\\d+) 个 Zed 远程项目。$"), "Đọc (các) dự án từ xa $1 của Zed."],
+ [new RegExp("^读取 Zed 远程项目失败。$"), "Không đọc được các dự án từ xa của Zed."],
+ [new RegExp("^已在 Zed Remote 打开项目。$"), "Dự án đã mở trong Zed Remote."],
+ [new RegExp("^无法在 Zed Remote 打开项目。$"), "Không thể mở dự án trong Zed Remote."],
+ [new RegExp("^移除 Zed 远程项目失败。$"), "Không thể xóa dự án từ xa Zed."],
+ [new RegExp("^供应商已同步一次:(\\d+) 个会话文件,(\\d+) 行索引,跳过 (\\d+) 个占用文件。$"), "Nhà cung cấp đã đồng bộ hóa: $1 tệp phiên, $2 hàng chỉ mục, bỏ qua $3 tệp bị khóa."],
+ [new RegExp("^供应商同步失败:(.+)$"), "Đồng bộ hóa nhà cung cấp không thành công: $1"],
+ [new RegExp("^推荐内容加载失败:(.+)$"), "Không tải được đề xuất: $1"],
+ [new RegExp("^脚本市场加载失败:(.+)$"), "Không thể tải thị trường tập lệnh: $1"],
+ [new RegExp("^安装脚本失败:(.+)$"), "Không cài đặt được tập lệnh: $1"],
+ [new RegExp("^脚本启停失败:(.+)$"), "Không thể chuyển đổi tập lệnh: $1"],
+ [new RegExp("^脚本删除失败:(.+)$"), "Không xóa được tập lệnh: $1"],
+ [new RegExp("^打开链接失败:(.+)$"), "Không mở được liên kết: $1"],
+ [new RegExp("^插件市场修复失败:(.+)$"), "Sửa chữa thị trường plugin không thành công: $1"],
+ [new RegExp("^官方远端插件缓存修复失败:(.+)$"), "Sửa chữa bộ nhớ đệm plugin từ xa chính thức không thành công: $1"],
+ [new RegExp("^检查更新失败:(.+)$"), "Không kiểm tra được bản cập nhật: $1"],
+ [new RegExp("^安装更新失败:(.+)$"), "Không cài đặt được bản cập nhật: $1"],
+ [new RegExp("^安装 watcher 失败:(.+)$"), "Không cài đặt được trình theo dõi: $1"],
+ [new RegExp("^移除 watcher 失败:(.+)$"), "Không xóa được người theo dõi: $1"],
+ [new RegExp("^启用 watcher 失败:(.+)$"), "Không bật được trình theo dõi: $1"],
+ [new RegExp("^禁用 watcher 失败:(.+)$"), "Không tắt được trình theo dõi: $1"],
+ [new RegExp("^读取日志失败:(.+)$"), "Không đọc được nhật ký: $1"],
+ [new RegExp("^重置设置失败:(.+)$"), "Không thể đặt lại cài đặt: $1"],
+ [new RegExp("^重置图片覆盖层失败:(.+)$"), "Không thể đặt lại lớp phủ hình ảnh: $1"],
+ [new RegExp("^读取配置文件失败:(.+)$"), "Không đọc được tệp cấu hình: $1"],
+ [new RegExp("^删除环境变量失败:(.+)$"), "Không thể xóa các biến môi trường: $1"],
+ [new RegExp("^保存配置文件失败:(.+)$"), "Không lưu được tập tin cấu hình: $1"],
+ [new RegExp("^供应商切换失败:(.+)$"), "Chuyển đổi nhà cung cấp không thành công: $1"],
+ [new RegExp("^写入诊断日志失败:(.+)$"), "Không thể ghi nhật ký chẩn đoán: $1"],
+ [new RegExp("^回填当前供应商配置失败:(.+)$"), "Không thể chèn lấp cấu hình nhà cung cấp hiện tại: $1"],
+ [new RegExp("^读取工具与插件列表失败:(.+)$"), "Không đọc được danh sách công cụ và plugin: $1"],
+ [new RegExp("^读取 live 工具与插件失败:(.+)$"), "Không đọc được các công cụ và plugin trực tiếp: $1"],
+ [new RegExp("^保存工具与插件失败:(.+)$"), "Không lưu được công cụ và plugin: $1"],
+ [new RegExp("^读取 live config.toml 失败:(.+)$"), "Không thể đọc config.toml trực tiếp: $1"],
+ [new RegExp("^同步 live 工具与插件失败:(.+)$"), "Không thể đồng bộ hóa các công cụ và plugin trực tiếp: $1"],
+ [new RegExp("^创建 Codex 配置目录失败:(.+)$"), "Không tạo được thư mục cấu hình Codex: $1"],
+ [new RegExp("^写入 live config.toml 失败:(.+)$"), "Không thể ghi config.toml trực tiếp: $1"],
+ [new RegExp("^读取同步后的 live 工具与插件失败:(.+)$"), "Không thể đọc các công cụ và plugin trực tiếp sau khi đồng bộ hóa: $1"],
+ [new RegExp("^删除工具与插件失败:(.+)$"), "Không xóa được công cụ và plugin: $1"],
+ [new RegExp("^提取通用配置失败:(.+)$"), "Không trích xuất được cấu hình chung: $1"],
+ [new RegExp("^已向「(.+?)」用模型「(.+?)」发送 hi,HTTP (\\d+)。(.*)$"), "Đã gửi lời chào tới \"$1\" bằng mô hình \"$2\", HTTP $3.$4"],
+ [new RegExp("^测试「(.+?)」失败:(.+)$"), "Kiểm tra \"$1\" không thành công: $2"],
+ [new RegExp("^已从「(.+?)」获取 (\\d+) 个模型。$"), "Đã tìm nạp (các) mẫu $2 từ \"$1\"."],
+ [new RegExp("^从「(.+?)」获取模型失败:(.+)$"), "Không tìm nạp được mô hình từ \"$1\": $2"],
+ [new RegExp("^切换完整中转配置失败:(.+)$"), "Không thể chuyển đổi cấu hình chuyển tiếp đầy đủ: $1"],
+ [new RegExp("^写入中转配置失败:(.+)$"), "Không thể ghi cấu hình chuyển tiếp: $1"],
+ [new RegExp("^写入聚合供应商配置失败:(.+)$"), "Không thể ghi cấu hình nhà cung cấp tổng hợp: $1"],
+ [new RegExp("^切换纯 API 配置失败:(.+)$"), "Không thể chuyển sang cấu hình API thuần túy: $1"],
+ [new RegExp("^写入纯 API 模式失败:(.+)$"), "Không thể ghi chế độ API thuần túy: $1"],
+ [new RegExp("^清除中转配置失败:(.+)$"), "Không xóa được cấu hình chuyển tiếp: $1"],
+ [new RegExp("^未知配置文件类型:(.+)$"), "Loại tệp cấu hình không xác định: $1"],
+ [new RegExp("^启动系统浏览器失败:(.+)$"), "Không khởi chạy được trình duyệt hệ thống: $1"],
+ [new RegExp("^诊断报告序列化失败:(.+)$"), "Không thể tuần tự hóa báo cáo chẩn đoán: $1"],
+ [new RegExp("^响应:(.+)$"), "Phản hồi: $1"],
+];
diff --git a/apps/codex-plus-manager/src/i18n.ts b/apps/codex-plus-manager/src/i18n.ts
index b9efa2d76..0e1d70b30 100644
--- a/apps/codex-plus-manager/src/i18n.ts
+++ b/apps/codex-plus-manager/src/i18n.ts
@@ -2,75 +2,84 @@
//
// The app is authored in Chinese. Every user-facing Chinese literal is wrapped
// with `t("中文")` (plain strings) or `tf("前缀 {0}", [expr])` (interpolated
-// strings) by tools/i18n-codemod.mjs. When the active language is English we
-// look the source text up in the English dictionary; otherwise we return the
-// original Chinese, so Chinese stays the zero-overhead default.
+// strings). Dictionaries: i18n-en.ts, i18n-vi.ts.
//
-// Language is resolved once at module load. Many Chinese literals live in
-// module-level constants (route tables, preset labels, …) that evaluate a
-// single time at import, so a live in-place swap can't reach them. Switching
-// language therefore persists the choice and reloads the webview, which is
-// instant for a local Tauri window and guarantees every literal — module-level
-// or render-level — re-evaluates under the new language.
+// Language is resolved once at module load. Switching language persists and
+// reloads the webview so module-level literals re-evaluate.
import { EN_BACKEND, EN_BACKEND_PATTERNS, EN_PLAIN, EN_TEMPLATE } from "@/i18n-en";
+import { VI_BACKEND, VI_BACKEND_PATTERNS, VI_PLAIN, VI_TEMPLATE } from "@/i18n-vi";
-export type Language = "zh" | "en";
+export type Language = "zh" | "en" | "vi";
const STORAGE_KEY = "codex-plus-lang";
function resolveInitialLanguage(): Language {
try {
- return window.localStorage.getItem(STORAGE_KEY) === "en" ? "en" : "zh";
+ const stored = window.localStorage.getItem(STORAGE_KEY);
+ if (stored === "en" || stored === "vi") return stored;
} catch {
- return "zh";
+ // ignore
}
+ return "zh";
}
-// Resolved once per webview load. Do not mutate at runtime — use setLanguage,
-// which persists and reloads so module-level literals pick up the change.
const LANG: Language = resolveInitialLanguage();
export function getLanguage(): Language {
return LANG;
}
-/** Translate a plain Chinese literal. Falls back to the source text. */
-export function t(zh: string): string {
- if (LANG !== "en") return zh;
- const plain = EN_PLAIN[zh] ?? EN_BACKEND[zh];
+function translatePlain(zh: string): string {
+ if (LANG === "zh") return zh;
+ const plain = LANG === "en" ? EN_PLAIN[zh] ?? EN_BACKEND[zh] : VI_PLAIN[zh] ?? VI_BACKEND[zh];
if (plain) return plain;
- for (const [re, replacement] of EN_BACKEND_PATTERNS) {
+ const patterns = LANG === "en" ? EN_BACKEND_PATTERNS : VI_BACKEND_PATTERNS;
+ for (const [re, replacement] of patterns) {
if (re.test(zh)) return zh.replace(re, replacement);
}
return zh;
}
-/**
- * Translate an interpolated literal. `key` carries `{0}`,`{1}`… placeholders in
- * the original (Chinese) order; `args` are the runtime values for each. In
- * Chinese we substitute into the key itself; in English we substitute into the
- * looked-up template (also falling back to the key).
- */
+/** Translate a plain Chinese literal. Falls back to the source text. */
+export function t(zh: string): string {
+ return translatePlain(zh);
+}
+
export function tf(key: string, args: Array): string {
- const template = LANG === "en" ? EN_TEMPLATE[key] ?? key : key;
+ const dict = LANG === "en" ? EN_TEMPLATE : LANG === "vi" ? VI_TEMPLATE : null;
+ const template = dict ? dict[key] ?? key : key;
return template.replace(/\{(\d+)\}/g, (match, index) => {
const value = args[Number(index)];
return value === undefined || value === null ? match : String(value);
});
}
-/** Persist a new language and reload so every literal re-evaluates under it. */
export function setLanguage(language: Language): void {
try {
window.localStorage.setItem(STORAGE_KEY, language);
} catch {
- // Ignore storage failures; the reload below simply keeps the old value.
+ // ignore
}
window.location.reload();
}
-/** Flip between Chinese and English. */
+const LANG_CYCLE: Language[] = ["zh", "vi", "en"];
+
+/** Cycle UI language: 中文 → Tiếng Việt → English. */
+export function cycleLanguage(): void {
+ const idx = LANG_CYCLE.indexOf(LANG);
+ const next = LANG_CYCLE[(idx + 1) % LANG_CYCLE.length];
+ setLanguage(next);
+}
+
+/** @deprecated Use cycleLanguage() */
export function toggleLanguage(): void {
- setLanguage(LANG === "en" ? "zh" : "en");
+ cycleLanguage();
+}
+
+export function languageButtonTitle(): string {
+ if (LANG === "zh") return translatePlain("切换到越南语");
+ if (LANG === "vi") return translatePlain("切换到英文");
+ return translatePlain("切换到中文");
}
diff --git a/apps/codex-plus-manager/src/i18n.ts.bak b/apps/codex-plus-manager/src/i18n.ts.bak
new file mode 100644
index 000000000..b9efa2d76
--- /dev/null
+++ b/apps/codex-plus-manager/src/i18n.ts.bak
@@ -0,0 +1,76 @@
+// Lightweight source-text-keyed i18n for the Codex++ manager UI.
+//
+// The app is authored in Chinese. Every user-facing Chinese literal is wrapped
+// with `t("中文")` (plain strings) or `tf("前缀 {0}", [expr])` (interpolated
+// strings) by tools/i18n-codemod.mjs. When the active language is English we
+// look the source text up in the English dictionary; otherwise we return the
+// original Chinese, so Chinese stays the zero-overhead default.
+//
+// Language is resolved once at module load. Many Chinese literals live in
+// module-level constants (route tables, preset labels, …) that evaluate a
+// single time at import, so a live in-place swap can't reach them. Switching
+// language therefore persists the choice and reloads the webview, which is
+// instant for a local Tauri window and guarantees every literal — module-level
+// or render-level — re-evaluates under the new language.
+
+import { EN_BACKEND, EN_BACKEND_PATTERNS, EN_PLAIN, EN_TEMPLATE } from "@/i18n-en";
+
+export type Language = "zh" | "en";
+
+const STORAGE_KEY = "codex-plus-lang";
+
+function resolveInitialLanguage(): Language {
+ try {
+ return window.localStorage.getItem(STORAGE_KEY) === "en" ? "en" : "zh";
+ } catch {
+ return "zh";
+ }
+}
+
+// Resolved once per webview load. Do not mutate at runtime — use setLanguage,
+// which persists and reloads so module-level literals pick up the change.
+const LANG: Language = resolveInitialLanguage();
+
+export function getLanguage(): Language {
+ return LANG;
+}
+
+/** Translate a plain Chinese literal. Falls back to the source text. */
+export function t(zh: string): string {
+ if (LANG !== "en") return zh;
+ const plain = EN_PLAIN[zh] ?? EN_BACKEND[zh];
+ if (plain) return plain;
+ for (const [re, replacement] of EN_BACKEND_PATTERNS) {
+ if (re.test(zh)) return zh.replace(re, replacement);
+ }
+ return zh;
+}
+
+/**
+ * Translate an interpolated literal. `key` carries `{0}`,`{1}`… placeholders in
+ * the original (Chinese) order; `args` are the runtime values for each. In
+ * Chinese we substitute into the key itself; in English we substitute into the
+ * looked-up template (also falling back to the key).
+ */
+export function tf(key: string, args: Array): string {
+ const template = LANG === "en" ? EN_TEMPLATE[key] ?? key : key;
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
+ const value = args[Number(index)];
+ return value === undefined || value === null ? match : String(value);
+ });
+}
+
+/** Persist a new language and reload so every literal re-evaluates under it. */
+export function setLanguage(language: Language): void {
+ try {
+ window.localStorage.setItem(STORAGE_KEY, language);
+ } catch {
+ // Ignore storage failures; the reload below simply keeps the old value.
+ }
+ window.location.reload();
+}
+
+/** Flip between Chinese and English. */
+export function toggleLanguage(): void {
+ setLanguage(LANG === "en" ? "zh" : "en");
+}
diff --git a/apps/codex-plus-manager/src/model-windows.ts b/apps/codex-plus-manager/src/model-windows.ts
index 3dd46a7cc..a2b82f367 100644
--- a/apps/codex-plus-manager/src/model-windows.ts
+++ b/apps/codex-plus-manager/src/model-windows.ts
@@ -90,7 +90,7 @@ export function buildModelWindows(modelList: string, modelWindowsText: string):
if (models.length !== windows.length) {
return {
ok: false,
- error: `模型名称有 ${models.length} 行,上下文窗口有 ${windows.length} 行,请保持行数一致。`,
+ error: `Danh sách model có ${models.length} dòng, cửa sổ ngữ cảnh có ${windows.length} dòng; hãy giữ số dòng khớp nhau.`,
};
}
return { ok: true, modelWindows: modelWindowsTextToMap(modelList, modelWindowsText) };
diff --git a/assets/inject/renderer-inject.js b/assets/inject/renderer-inject.js
index 4bd8a8e5a..c0844665d 100644
--- a/assets/inject/renderer-inject.js
+++ b/assets/inject/renderer-inject.js
@@ -1031,7 +1031,7 @@
.codex-plus-toggle:disabled { cursor: not-allowed; opacity: .55; }
.codex-plus-toggle[data-relay-unneeded="true"] { width: 72px; cursor: default; background: rgba(16,163,127,.16); color: #6ee7b7; }
.codex-plus-toggle[data-relay-unneeded="true"] span { display: none; }
- .codex-plus-toggle[data-relay-unneeded="true"]::after { content: "无需开启"; font-size: 12px; font-weight: 650; line-height: 1; }
+ .codex-plus-toggle[data-relay-unneeded="true"]::after { content: "Không cần bật"; font-size: 12px; font-weight: 650; line-height: 1; }
.codex-plus-width-control { display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-width: 176px; align-self: center; }
.codex-plus-width-input {
width: 78px;
@@ -1387,7 +1387,7 @@
let codexServiceTierState = {
status: "loading",
serviceTier: null,
- message: "正在读取…",
+ message: "Đang đọc…",
fastTierValue: "priority",
controlMode: "inherit",
defaultMode: "inherit",
@@ -1434,7 +1434,7 @@
if (!codexServiceTierModulePromises.has(namePart)) {
const promise = Promise.resolve().then(async () => {
const url = codexAppAssetUrl(namePart) || await codexAppAssetUrlFromScriptText(namePart);
- if (!url) throw new Error(`未找到 Codex App asset: ${namePart}`);
+ if (!url) throw new Error(`Không tìm thấy Codex App asset: ${namePart}`);
return await import(url);
}).catch((error) => {
codexServiceTierModulePromises.delete(namePart);
@@ -1511,8 +1511,8 @@
}
function codexServiceTierFastUnsupportedMessage(modelName = codexServiceTierCurrentModelName()) {
- const modelText = modelName ? `当前模型 ${modelName} 不支持` : "当前模型未读取";
- return `Fast 仅支持 ${codexServiceTierFastModelListLabel()},${modelText}`;
+ const modelText = modelName ? `model hiện tại ${modelName} không hỗ trợ` : "chưa đọc model hiện tại";
+ return `Fast chỉ hỗ trợ ${codexServiceTierFastModelListLabel()}, ${modelText}`;
}
function codexServiceTierMaybeLoadModelCatalog(force = false) {
@@ -1581,9 +1581,9 @@
}
function serviceTierGlobalStatusMessage(serviceTier) {
- if (isFastServiceTierValue(serviceTier)) return "Fast 已开启";
- if (!serviceTier) return "默认服务模式";
- return `当前:${serviceTier}`;
+ if (isFastServiceTierValue(serviceTier)) return "Fast đã bật";
+ if (!serviceTier) return "Chế độ dịch vụ mặc định";
+ return `Hiện tại: ${serviceTier}`;
}
function serviceTierStatusMessage(
@@ -1592,13 +1592,13 @@
effectiveMode = codexServiceTierState.effectiveMode || "standard",
defaultMode = codexServiceTierState.defaultMode || "inherit"
) {
- if (codexServiceTierState.status === "loading") return "正在读取…";
- if (codexServiceTierState.status === "failed") return "读取失败";
- if (controlMode === "inherit") return `继承 config.toml:${effectiveMode}`;
- if (controlMode === "global-standard") return "全局 Standard";
- if (controlMode === "global-fast") return "全局 Fast";
- if (threadMode === "inherit") return `自定义:默认 ${defaultMode}`;
- return `自定义:当前 thread ${threadMode}`;
+ if (codexServiceTierState.status === "loading") return "Đang đọc…";
+ if (codexServiceTierState.status === "failed") return "Đọc thất bại";
+ if (controlMode === "inherit") return `Kế thừa config.toml: ${effectiveMode}`;
+ if (controlMode === "global-standard") return "Standard toàn cục";
+ if (controlMode === "global-fast") return "Fast toàn cục";
+ if (threadMode === "inherit") return `Tùy chỉnh: mặc định ${defaultMode}`;
+ return `Tùy chỉnh: thread hiện tại ${threadMode}`;
}
function readThreadServiceTierState() {
@@ -1716,7 +1716,7 @@
function setCodexServiceTierControlMode(mode) {
if (codexPlusBackendStatus.status !== "ok") {
- showToast("后端未连接,无法切换服务模式", null);
+ showToast("Backend chưa kết nối, không thể đổi chế độ dịch vụ", null);
refreshCodexServiceTierControls();
return;
}
@@ -1742,12 +1742,12 @@
writeThreadServiceTierState(state);
refreshCodexServiceTierControls();
const labels = {
- inherit: "继承 config.toml",
- "global-standard": "全局 Standard",
- "global-fast": "全局 Fast",
- custom: "自定义",
+ inherit: "Kế thừa config.toml",
+ "global-standard": "Standard toàn cục",
+ "global-fast": "Fast toàn cục",
+ custom: "Tùy chỉnh",
};
- showToast(`服务模式:${labels[normalizedMode] || normalizedMode}`, null);
+ showToast(`Chế độ dịch vụ: ${labels[normalizedMode] || normalizedMode}`, null);
}
function syncCodexServiceTierEffectiveState() {
@@ -1758,7 +1758,7 @@
threadMode: "inherit",
effectiveServiceTier: codexServiceTierState.serviceTier || null,
effectiveMode: codexServiceTierEffectiveMode(codexServiceTierState.serviceTier),
- message: "未启用",
+ message: "Chưa bật",
};
return;
}
@@ -1790,22 +1790,22 @@
}
function codexServiceTierBadgeState() {
- if (codexPlusBackendStatus.status === "checking") return { tier: "loading", label: "...", disabled: true, title: "服务模式:正在检查后端连接" };
- if (codexPlusBackendStatus.status && codexPlusBackendStatus.status !== "ok") return { tier: "failed", label: "未连接", disabled: true, title: "服务模式:后端未连接,无法切换" };
- if (codexServiceTierState.status === "loading") return { tier: "loading", label: "...", title: "服务模式:正在读取" };
- if (codexServiceTierState.status === "failed") return { tier: "failed", label: "?", title: "服务模式:读取失败" };
+ if (codexPlusBackendStatus.status === "checking") return { tier: "loading", label: "...", disabled: true, title: "Chế độ dịch vụ: đang kiểm tra kết nối backend" };
+ if (codexPlusBackendStatus.status && codexPlusBackendStatus.status !== "ok") return { tier: "failed", label: "Chưa kết nối", disabled: true, title: "Chế độ dịch vụ: backend chưa kết nối, không thể đổi" };
+ if (codexServiceTierState.status === "loading") return { tier: "loading", label: "...", title: "Chế độ dịch vụ: đang đọc" };
+ if (codexServiceTierState.status === "failed") return { tier: "failed", label: "?", title: "Chế độ dịch vụ: đọc thất bại" };
const fastAvailability = codexServiceTierFastAvailability();
const effectiveMode = codexServiceTierState.effectiveMode || "standard";
const scope = codexServiceTierState.controlMode === "custom" && codexServiceTierState.threadMode !== "inherit"
- ? `当前 thread:${codexServiceTierState.threadMode}`
+ ? `Thread hiện tại:${codexServiceTierState.threadMode}`
: serviceTierStatusMessage(codexServiceTierState.controlMode, codexServiceTierState.threadMode, effectiveMode, codexServiceTierState.defaultMode);
const title = [
- `服务模式:${scope}`,
- "Standard:使用标准处理;不在请求上设置 priority。",
- `Fast:仅支持 ${codexServiceTierFastModelListLabel()};对支持模型使用 service_tier=\"priority\",官方说明其延迟更低且更一致,但会按更高价格计费;rate limit 与 Standard 共享,流量快速上涨时可能回落到 Standard。`,
+ `Chế độ dịch vụ: ${scope}`,
+ "Standard: dùng xử lý tiêu chuẩn; không đặt priority trong request.",
+ `Fast: chỉ hỗ trợ ${codexServiceTierFastModelListLabel()}; model hỗ trợ sẽ dùng service_tier=\"priority\", độ trễ thấp và ổn định hơn nhưng giá cao hơn; rate limit dùng chung với Standard và có thể rơi về Standard khi lưu lượng tăng nhanh.`,
].join("\n");
if (effectiveMode === "fast" && !fastAvailability.supported) {
- return { tier: "unsupported", label: "不支持", title: `${title}\n${codexServiceTierFastUnsupportedMessage(fastAvailability.modelName)};当前请求会按 Standard 发送。` };
+ return { tier: "unsupported", label: "Không hỗ trợ", title: `${title}\n${codexServiceTierFastUnsupportedMessage(fastAvailability.modelName)};request hiện tại sẽ gửi theo Standard。` };
}
if (effectiveMode === "fast") return { tier: "fast", label: "fast", title };
return { tier: "standard", label: "standard", title };
@@ -1840,8 +1840,8 @@
document.querySelectorAll("[data-codex-service-tier-status]").forEach((node) => {
node.dataset.status = fastUnsupportedActive ? "unsupported" : (featureEnabled && backendConnected ? (codexServiceTierState.status || "loading") : (backendChecking ? "loading" : "failed"));
node.textContent = featureEnabled
- ? (backendConnected ? (codexServiceTierState.message || "未读取") : (backendChecking ? "正在检查后端…" : "未连接"))
- : "未启用";
+ ? (backendConnected ? (codexServiceTierState.message || "Chưa đọc") : (backendChecking ? "Đang kiểm tra backend…" : "Chưa kết nối"))
+ : "Chưa bật";
});
document.querySelectorAll("[data-codex-service-tier-inherit]").forEach((button) => {
button.disabled = !featureEnabled || !backendConnected || codexServiceTierState.status === "loading";
@@ -1863,7 +1863,7 @@
document.querySelectorAll("[data-codex-service-tier-thread-inherit]").forEach((button) => {
button.disabled = !featureEnabled || !backendConnected || codexServiceTierState.status === "loading";
button.dataset.active = String(codexServiceTierState.controlMode === "custom" && codexServiceTierState.threadMode === "inherit");
- button.title = `当前 thread 不单独覆盖,继承自定义默认 ${codexServiceTierState.defaultMode || "inherit"}`;
+ button.title = `Thread hiện tại không ghi đè riêng, kế thừa mặc định tùy chỉnh ${codexServiceTierState.defaultMode || "inherit"}`;
});
document.querySelectorAll("[data-codex-service-tier-thread-standard]").forEach((button) => {
button.disabled = !featureEnabled || !backendConnected || codexServiceTierState.status === "loading";
@@ -1879,11 +1879,11 @@
async function loadCodexServiceTierState() {
if (!codexPlusSettings().serviceTierControls) {
- codexServiceTierState = { ...codexServiceTierState, status: "idle", message: "未启用" };
+ codexServiceTierState = { ...codexServiceTierState, status: "idle", message: "Chưa bật" };
refreshCodexServiceTierControls();
return;
}
- codexServiceTierState = { ...codexServiceTierState, status: "loading", message: "正在读取…" };
+ codexServiceTierState = { ...codexServiceTierState, status: "loading", message: "Đang đọc…" };
refreshCodexServiceTierControls();
try {
const serviceTier = await getCodexServiceTierSetting();
@@ -1897,7 +1897,7 @@
codexServiceTierState = {
...codexServiceTierState,
status: "failed",
- message: "读取失败",
+ message: "Đọc thất bại",
};
sendCodexPlusDiagnostic("service_tier_read_failed", {
errorName: error?.name || "",
@@ -1910,7 +1910,7 @@
function setCodexThreadServiceTierMode(mode) {
if (codexPlusBackendStatus.status !== "ok") {
- showToast("后端未连接,无法切换服务模式", null);
+ showToast("Backend chưa kết nối, không thể đổi chế độ dịch vụ", null);
refreshCodexServiceTierControls();
return;
}
@@ -1927,13 +1927,13 @@
const threadId = validThreadScrollSessionKey(currentSessionRef().session_id);
setCodexThreadServiceTierOverride(threadId, normalizedMode);
refreshCodexServiceTierControls();
- const target = threadId ? "当前 thread" : "新 thread 草稿";
- showToast(`${target}服务模式:${normalizedMode === "inherit" ? "继承" : normalizedMode}`, null);
+ const target = threadId ? "Thread hiện tại" : "Bản nháp thread mới";
+ showToast(`${target} - chế độ dịch vụ: ${normalizedMode === "inherit" ? "Kế thừa" : normalizedMode}`, null);
}
function toggleCodexServiceTierFromBadge() {
if (codexPlusBackendStatus.status !== "ok") {
- showToast("后端未连接,无法切换服务模式", null);
+ showToast("Backend chưa kết nối, không thể đổi chế độ dịch vụ", null);
refreshCodexServiceTierControls();
return;
}
@@ -2163,7 +2163,7 @@
}
let codexPlusUserScripts = { enabled: true, builtin_dir: "", user_dir: "", scripts: [] };
- let codexPlusBackendStatus = { status: "checking", message: "正在检查后端…" };
+ let codexPlusBackendStatus = { status: "checking", message: "Đang kiểm tra backend…" };
let codexPlusBackendCheckSeq = 0;
function setCodexPlusTriggerLabel(trigger) {
@@ -2189,6 +2189,35 @@
return indicator;
}
+ function codexPlusViMessage(message) {
+ if (!message) return message;
+ const text = String(message);
+ const exact = {
+ "后端已连接": "Backend đã kết nối",
+ "未连接": "Chưa kết nối",
+ "正在检查后端…": "Đang kiểm tra backend…",
+ "正在检查后端": "Đang kiểm tra backend",
+ "后端检查超时": "Kiểm tra backend quá thời gian",
+ "未启用": "Chưa bật",
+ "未读取": "Chưa đọc",
+ "读取失败": "Đọc thất bại",
+ "管理工具已打开": "Đã mở công cụ quản lý",
+ "打开管理工具失败": "Mở công cụ quản lý thất bại",
+ };
+ return exact[text] || text
+ .replaceAll("后端已连接", "Backend đã kết nối")
+ .replaceAll("后端未连接,无法切换服务模式", "Backend chưa kết nối, không thể đổi chế độ dịch vụ")
+ .replaceAll("未连接", "Chưa kết nối")
+ .replaceAll("正在检查后端", "Đang kiểm tra backend")
+ .replaceAll("服务模式", "Chế độ dịch vụ")
+ .replaceAll("读取失败", "Đọc thất bại")
+ .replaceAll("正在读取", "Đang đọc")
+ .replaceAll("未启用", "Chưa bật")
+ .replaceAll("继承", "Kế thừa")
+ .replaceAll("当前 thread", "Thread hiện tại")
+ .replaceAll("自定义", "Tùy chỉnh");
+ }
+
function renderBackendStatus() {
const status = codexPlusBackendStatus.status || "failed";
if (codexPlusBackendStatus.version) {
@@ -2201,11 +2230,11 @@
const label = document.querySelector("[data-codex-backend-status]");
if (label) {
label.dataset.status = status;
- label.textContent = codexPlusBackendStatus.message || (status === "ok" ? "后端已连接" : "未连接");
+ label.textContent = codexPlusViMessage(codexPlusBackendStatus.message) || (status === "ok" ? "Backend đã kết nối" : "Chưa kết nối");
}
document.querySelectorAll("[data-codex-backend-indicator]").forEach((indicator) => {
indicator.dataset.status = status;
- indicator.title = status === "ok" ? "后端已连接" : status === "checking" ? "正在检查后端" : "未连接";
+ indicator.title = status === "ok" ? "Backend đã kết nối" : status === "checking" ? "Đang kiểm tra backend" : "Chưa kết nối";
});
refreshCodexServiceTierControls();
}
@@ -2213,7 +2242,7 @@
function withBackendTimeout(request) {
return Promise.race([
request,
- new Promise((resolve) => setTimeout(() => resolve({ status: "failed", message: "后端检查超时", timeout: true }), 2000)),
+ new Promise((resolve) => setTimeout(() => resolve({ status: "failed", message: "Kiểm tra backend quá thời gian", timeout: true }), 2000)),
]);
}
@@ -2235,9 +2264,9 @@
async function openManagerFromCodex() {
const result = await postJson("/manager/open", {});
if (result.status === "ok") {
- showToast("管理工具已打开", null);
+ showToast("Đã mở công cụ quản lý", null);
} else {
- showToast(result.message || "打开管理工具失败", null);
+ showToast(codexPlusViMessage(result.message) || "Mở công cụ quản lý thất bại", null);
}
}
@@ -2248,25 +2277,25 @@
}
function userScriptStatusLabel(status) {
- return { loaded: "已加载", failed: "失败", disabled: "已禁用", not_loaded: "未加载", loading: "加载中" }[status] || status || "未知";
+ return { loaded: "Đã tải", failed: "Lỗi", disabled: "Đã tắt", not_loaded: "Chưa tải", loading: "Đang tải" }[status] || status || "Không rõ";
}
function renderUserScripts() {
const enabledToggle = document.querySelector("[data-codex-user-scripts-enabled]");
if (enabledToggle) enabledToggle.dataset.enabled = String(!!codexPlusUserScripts.enabled);
const dirs = document.querySelector("[data-codex-user-script-dirs]");
- if (dirs) dirs.textContent = `内置:${codexPlusUserScripts.builtin_dir || "未找到"} 用户:${codexPlusUserScripts.user_dir || "未找到"}`;
+ if (dirs) dirs.textContent = `Tích hợp: ${codexPlusUserScripts.builtin_dir || "Không tìm thấy"} Người dùng: ${codexPlusUserScripts.user_dir || "Không tìm thấy"}`;
const list = document.querySelector("[data-codex-user-script-list]");
if (!list) return;
if (!codexPlusUserScripts.scripts?.length) {
- list.textContent = "未发现用户脚本。";
+ list.textContent = "Không tìm thấy script người dùng.";
return;
}
list.innerHTML = codexPlusUserScripts.scripts.map((script) => `
${codexPlusBackendSettings.launchMode === "relay" ? "Không cần bật trong chế độ tương thích; đăng nhập ChatGPT vẫn giữ chợ plugin chính thức." : "Trong chế độ API Key, mở rộng yêu cầu chợ plugin để hiển thị danh sách đầy đủ nhất có thể."}
Lấy model từ biến môi trường và /v1/models của relay trong Codex config.toml, rồi thêm vào danh sách chọn model.
-
Fast 按钮
显示服务模式切换按钮;Fast 仅支持 ${codexServiceTierFastModelListLabel()},其他模型按 Standard 发送。
+
Nút Fast
Hiển thị nút đổi chế độ dịch vụ; Fast chỉ hỗ trợ ${codexServiceTierFastModelListLabel()}, model khác gửi theo Standard.
-
Stepwise
在当前 Codex 页面显示可拖动的下一步建议浮层,可在设置页配置模型和直接发送。
+
Stepwise
Hiển thị lớp gợi ý bước tiếp theo có thể kéo trên trang Codex; cấu hình model và gửi trực tiếp trong trang cài đặt.
-
服务模式
继承使用 config.toml 的 service tier;全局模式覆盖全部 thread;自定义允许按 thread 覆盖。
+
Chế độ dịch vụ
Kế thừa service tier từ config.toml; chế độ toàn cục áp dụng cho mọi thread; tùy chỉnh cho phép ghi đè theo thread.
-
正在读取…
+
Đang đọc…
-
-
-
-
+
+
+
+
- 当前 thread 覆盖
-
-
-
+ Ghi đè thread hiện tại
+
+
+
-
会话删除
在会话列表悬停显示删除按钮,并支持撤销。
+
Xóa phiên
Hiển thị nút xóa khi rê chuột trong danh sách phiên, có hỗ trợ hoàn tác.
-
Markdown 导出
在会话列表显示导出按钮,按本地 rollout 导出带时间戳的 Markdown。
+
Xuất Markdown
Hiển thị nút xuất trong danh sách phiên, xuất Markdown có timestamp theo rollout cục bộ.
-
粘贴修复
从 Word 等富文本来源粘贴到 Codex composer 时只保留纯文本,避免被识别为图片/文件附件。需重启 Codex 才生效。
+
Sửa dán
Khi dán từ Word hoặc nguồn rich text vào Codex composer, chỉ giữ văn bản thuần để tránh bị nhận diện thành ảnh/tệp đính kèm. Cần khởi động lại Codex để có hiệu lực.
-
会话项目移动
在会话列表悬停显示移动按钮,可移动到普通对话或其他本地项目。
+
Di chuyển dự án phiên
Hiển thị nút di chuyển khi rê chuột trong danh sách phiên; có thể chuyển sang hội thoại thường hoặc dự án cục bộ khác.
-
会话 ID 标识
在侧边栏会话标题前显示短 ID 和 UUIDv7 创建时间,方便定位历史会话。
+
Nhãn ID phiên
Hiển thị ID ngắn và thời gian tạo UUIDv7 trước tiêu đề phiên trong sidebar để dễ tìm phiên cũ.
-
对话居中宽度
开启后把主对话和输入框限制到固定最大宽度,适合大屏阅读。
+
Độ rộng hội thoại căn giữa
Khi bật, giới hạn hội thoại chính và ô nhập ở độ rộng tối đa cố định, phù hợp màn hình lớn.
-
切换对话保留位置
开启后在不同 thread 之间切换时恢复到上一次浏览位置,不再自动跳到底部。
+
Giữ vị trí khi đổi hội thoại
Khi bật, khôi phục vị trí xem trước đó khi đổi thread, không tự nhảy xuống cuối.
@@ -2499,73 +2528,73 @@
Upstream worktree
Create a Git worktree from a fresh upstream branch, equivalent to git worktree add -b branch path upstream/base.
-
+
-
历史会话修复
切换官方登录、混合 API 或纯 API 后,让旧对话重新显示在当前模式下。
+
Sửa phiên lịch sử
Sau khi đổi giữa đăng nhập chính thức, API hỗn hợp hoặc API thuần, hiển thị lại hội thoại cũ trong chế độ hiện tại.
${codexPlusBackendSettings.launchMode === "relay" ? "Tương thích: giữ xóa phiên, xuất, di chuyển dự án và script người dùng; chỉ tắt tăng cường liên quan chợ plugin." : "Đầy đủ: tải chợ plugin, di chuyển đường dẫn dự án và toàn bộ khả năng trang."}
+
-
原生菜单栏位置
把 Codex++ 菜单插入顶部原生菜单栏;默认关闭以避免页面重渲染冲突。
+
Vị trí thanh menu gốc
Chèn menu Codex++ vào thanh menu gốc phía trên; mặc định tắt để tránh xung đột khi trang render lại.
-
打开 DevTools
打开当前 Codex 页面开发者工具,方便查看用户脚本报错。
-
+
Mở DevTools
Mở DevTools của trang Codex hiện tại để xem lỗi script người dùng.
Nội dung đề xuất gồm đề xuất tài trợ và đề xuất thường. Đề xuất tài trợ đến từ đối tác hỗ trợ duy trì Codex++; đề xuất thường hiển thị dịch vụ và thông tin phù hợp với người dùng Codex.
${renderCodexPlusAds()}
-
如果 Codex++ 帮到了你,可以请我喝杯咖啡,或者随手赞赏支持一下继续维护。
+
Nếu Codex++ hữu ích, bạn có thể mời tôi một ly cà phê hoặc ủng hộ để tiếp tục duy trì.
-
支付宝
-
+
Alipay
+
-
微信
-
+
WeChat
+
@@ -4392,7 +4421,7 @@
});
return await response.json();
} catch (error) {
- return { status: "failed", message: "未连接" };
+ return { status: "failed", message: "Chưa kết nối" };
}
}
sendCodexPlusDiagnostic("bridge_missing_for_route", { path });
@@ -4401,7 +4430,7 @@
function bridgeWithBackendTimeout(path, payload) {
return Promise.race([
window.__codexSessionDeleteBridge(path, payload),
- new Promise((resolve) => setTimeout(() => resolve({ status: "failed", message: "后端检查超时", timeout: true }), 2000)),
+ new Promise((resolve) => setTimeout(() => resolve({ status: "failed", message: "Kiểm tra backend quá thời gian", timeout: true }), 2000)),
]);
}
async function fetchBackendStatusFromHelper(path, payload) {
@@ -4413,7 +4442,7 @@
});
return await response.json();
} catch (error) {
- return { status: "failed", message: "未连接" };
+ return { status: "failed", message: "Chưa kết nối" };
}
}
try {
@@ -5819,7 +5848,7 @@
async function setProjectlessThreadIds(ref, mode) {
const variants = threadIdVariants(ref.session_id);
- if (variants.length === 0) throw new Error("未找到会话 ID");
+ if (variants.length === 0) throw new Error("Không tìm thấy会话 ID");
const existingIds = await getCodexGlobalState("projectless-thread-ids").catch(() => []);
const ids = Array.isArray(existingIds) ? existingIds : [];
const variantSet = new Set(variants);
@@ -5861,7 +5890,7 @@
}
async function moveSessionToProjectless(ref) {
- if (!ref.session_id) throw new Error("未找到会话 ID");
+ if (!ref.session_id) throw new Error("Không tìm thấy会话 ID");
await setProjectlessThreadIds(ref, "add");
await clearThreadWorkspaceHints(ref);
await clearThreadWritableRoots(ref);
@@ -5875,11 +5904,11 @@
}
async function moveSessionToProject(ref, target) {
- if (!ref.session_id) throw new Error("未找到会话 ID");
+ if (!ref.session_id) throw new Error("Không tìm thấy会话 ID");
if (!target?.path) throw new Error("目标项目路径为空");
if (!isNativeProjectTarget(target)) throw new Error("目标项目不在 Codex 项目列表中");
const result = await postJson("/move-thread-workspace", { ...ref, target_cwd: target.path });
- if (result.status !== "moved") throw new Error(result.message || "移动项目失败");
+ if (result.status !== "moved") throw new Error(result.message || "移动项目Lỗi");
await setProjectlessThreadIds(ref, "remove");
await clearThreadWorkspaceHints(ref);
return result;
@@ -6759,10 +6788,10 @@
syncUpstreamBranchTriggerLabel();
showToast(`已从 ${result.sourceRef} 创建 worktree`, null);
} else {
- showToast(result?.message || "创建 upstream worktree 失败", null);
+ showToast(result?.message || "创建 upstream worktree Lỗi", null);
}
} catch (error) {
- showToast(error?.message || "创建 upstream worktree 失败", null);
+ showToast(error?.message || "创建 upstream worktree Lỗi", null);
}
return true;
}
@@ -6794,7 +6823,7 @@
try {
const result = await postJson("/upstream-worktree/defaults", { repoPath });
if (result?.status !== "ok") {
- setUpstreamWorktreeMessage(dialog, result?.message || "读取仓库默认值失败", "failed");
+ setUpstreamWorktreeMessage(dialog, result?.message || "读取仓库默认值Lỗi", "failed");
return;
}
const remote = upstreamWorktreeField(dialog, "remote");
@@ -6803,7 +6832,7 @@
if (baseBranch && (!baseBranch.value || baseBranch.value === "main")) baseBranch.value = result.defaultBaseBranch || "main";
setUpstreamWorktreeMessage(dialog, `将从 ${remote?.value || "upstream"}/${baseBranch?.value || "main"} 创建 worktree。`, "ok");
} catch (error) {
- setUpstreamWorktreeMessage(dialog, error?.message || "读取仓库默认值失败", "failed");
+ setUpstreamWorktreeMessage(dialog, error?.message || "读取仓库默认值Lỗi", "failed");
}
}
@@ -6820,10 +6849,10 @@
setUpstreamWorktreeMessage(dialog, `已从 ${result.sourceRef} 创建:${result.worktreePath}`, "ok");
showToast(`已创建 upstream worktree:${result.branchName}`, null);
} else {
- setUpstreamWorktreeMessage(dialog, result?.message || "创建 upstream worktree 失败", "failed");
+ setUpstreamWorktreeMessage(dialog, result?.message || "创建 upstream worktree Lỗi", "failed");
}
} catch (error) {
- setUpstreamWorktreeMessage(dialog, error?.message || "创建 upstream worktree 失败", "failed");
+ setUpstreamWorktreeMessage(dialog, error?.message || "创建 upstream worktree Lỗi", "failed");
}
}
@@ -6975,7 +7004,7 @@
removeDeletedRow(row, button, ref);
showToast(result.message || "删除成功", result.undo_token);
} else {
- showToast(result.message || "删除失败", null);
+ showToast(result.message || "删除Lỗi", null);
}
});
}
@@ -6991,7 +7020,7 @@
}
return;
}
- showToast(result.message || "导出失败", null);
+ showToast(result.message || "导出Lỗi", null);
}
function sortStateFromMoveResult(result, ref, row) {
@@ -7023,7 +7052,7 @@
} catch (error) {
button.disabled = false;
button.textContent = "移动";
- showToast(`移动失败:${error?.message || error}`, null);
+ showToast(`移动Lỗi:${error?.message || error}`, null);
}
}
@@ -7087,7 +7116,7 @@
list.querySelector("button")?.focus();
} catch (error) {
close();
- showToast(`加载项目失败:${error?.message || error}`, null);
+ showToast(`加载项目Lỗi:${error?.message || error}`, null);
}
}
@@ -7513,7 +7542,7 @@
stopArchivedButtonEvent(event);
const ref = await resolveArchivedThread(row);
if (!ref.session_id) {
- showToast("导出失败:未找到归档会话 ID", null);
+ showToast("导出Lỗi:Không tìm thấy归档会话 ID", null);
return;
}
await exportMarkdown(ref);
diff --git a/crates/codex-plus-core/src/install/mod.rs b/crates/codex-plus-core/src/install/mod.rs
index 2f105edde..3ef3489f3 100644
--- a/crates/codex-plus-core/src/install/mod.rs
+++ b/crates/codex-plus-core/src/install/mod.rs
@@ -6,7 +6,7 @@ pub mod macos;
pub mod windows;
pub const SILENT_NAME: &str = "Codex++";
-pub const MANAGER_NAME: &str = "Codex++ 管理工具";
+pub const MANAGER_NAME: &str = "Codex++ Manager";
pub const SILENT_BINARY: &str = "codex-plus-plus";
pub const MANAGER_BINARY: &str = "codex-plus-plus-manager";
@@ -72,11 +72,11 @@ impl ShortcutState {
}
pub fn shortcut_names() -> (&'static str, &'static str) {
- ("Codex++.lnk", "Codex++ 管理工具.lnk")
+ ("Codex++.lnk", "Codex++ Manager.lnk")
}
pub fn app_bundle_names() -> (&'static str, &'static str) {
- ("Codex++.app", "Codex++ 管理工具.app")
+ ("Codex++.app", "Codex++ Manager.app")
}
pub fn inspect_entrypoints() -> EntryPointState {
diff --git a/crates/codex-plus-core/src/install/windows.rs b/crates/codex-plus-core/src/install/windows.rs
index 3824d007b..947d7e896 100644
--- a/crates/codex-plus-core/src/install/windows.rs
+++ b/crates/codex-plus-core/src/install/windows.rs
@@ -46,7 +46,7 @@ pub fn build_windows_entrypoint_plan(options: &InstallOptions) -> WindowsEntrypo
.to_string_lossy()
.to_string(),
manager_shortcut: install_root
- .join("Codex++ 管理工具.lnk")
+ .join("Codex++ Manager.lnk")
.to_string_lossy()
.to_string(),
install_root: install_root.to_string_lossy().to_string(),
@@ -69,6 +69,7 @@ pub fn install_shortcuts(options: &InstallOptions) -> anyhow::Result<()> {
let plan = build_windows_entrypoint_plan(options);
let install_root = PathBuf::from(&plan.install_root);
std::fs::create_dir_all(&install_root)?;
+ remove_legacy_shortcuts(&install_root);
create_entrypoint_shortcut(
PathBuf::from(&plan.silent_shortcut),
PathBuf::from(&plan.launcher_path),
@@ -86,6 +87,18 @@ pub fn install_shortcuts(options: &InstallOptions) -> anyhow::Result<()> {
Ok(())
}
+#[cfg(windows)]
+fn remove_legacy_shortcuts(install_root: &Path) {
+ for name in [
+ "Codex++ 管理工具.lnk",
+ "Codex++ 绠$悊宸ュ叿.lnk",
+ "Uninstall Codex++.lnk",
+ "卸载 Codex++.lnk",
+ ] {
+ let _ = std::fs::remove_file(install_root.join(name));
+ }
+}
+
#[cfg(windows)]
pub fn uninstall_shortcuts(options: &InstallOptions) -> anyhow::Result<()> {
let plan = build_windows_entrypoint_plan(options);
diff --git a/crates/codex-plus-core/tests/ads.rs b/crates/codex-plus-core/tests/ads.rs
index f44f99b71..2141a2468 100644
--- a/crates/codex-plus-core/tests/ads.rs
+++ b/crates/codex-plus-core/tests/ads.rs
@@ -230,7 +230,7 @@ async fn fetch_ad_list_tries_backup_url_when_primary_fails() {
let request = String::from_utf8_lossy(&buffer[..read]);
if request.starts_with("GET /primary.json?") {
stream
- .write_all(b"HTTP/1.1 503 Service Unavailable\r\nContent-Length: 0\r\n\r\n")
+ .write_all(b"HTTP/1.1 503 Service Unavailable\r\nConnection: close\r\nContent-Length: 0\r\n\r\n")
.unwrap();
} else {
assert!(request.starts_with("GET /backup.json?"), "{request}");
@@ -247,7 +247,7 @@ async fn fetch_ad_list_tries_backup_url_when_primary_fails() {
})
.to_string();
let response = format!(
- "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
+ "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nConnection: close\r\nContent-Length: {}\r\n\r\n{}",
body.len(),
body
);
diff --git a/crates/codex-plus-core/tests/cdp_bridge.rs b/crates/codex-plus-core/tests/cdp_bridge.rs
index 96d7e22ae..6cca5759d 100644
--- a/crates/codex-plus-core/tests/cdp_bridge.rs
+++ b/crates/codex-plus-core/tests/cdp_bridge.rs
@@ -131,14 +131,14 @@ fn injection_script_times_out_backend_bridge_calls_and_falls_back_to_helper() {
fn injection_script_explains_plugin_patch_is_unneeded_in_relay_mode() {
let script = assets::injection_script(57321);
- assert!(script.contains("兼容增强模式下无需开启"));
+ assert!(script.contains("Không cần bật trong chế độ tương thích"));
}
#[test]
fn injection_script_menu_exposes_marketplace_plugin_switch_only() {
let script = assets::injection_script(57321);
- assert!(script.contains("插件市场解锁"));
+ assert!(script.contains("Mở khóa chợ plugin"));
assert!(script.contains("data-codex-plus-setting=\"pluginMarketplaceUnlock\""));
assert!(!script.contains("特殊插件强制安装"));
assert!(!script.contains("data-codex-plus-setting=\"forcePluginInstall\""));
@@ -489,7 +489,7 @@ fn injection_script_exposes_conversation_view_width_control() {
assert!(script.contains("conversationView: false"));
assert!(script.contains("conversationView"));
assert!(script.contains("conversationViewMaxWidth"));
- assert!(script.contains("对话居中宽度"));
+ assert!(script.contains("Độ rộng hội thoại căn giữa"));
assert!(script.contains("data-codex-plus-conversation-view-width"));
assert!(script.contains("conversationViewWidth()"));
assert!(script.contains("normalizeConversationViewWidth"));
@@ -501,7 +501,7 @@ fn injection_script_exposes_sidebar_thread_id_badge_control() {
assert!(script.contains("threadIdBadge: false"));
assert!(script.contains("threadIdBadge: \"codexAppThreadIdBadge\""));
- assert!(script.contains("会话 ID 标识"));
+ assert!(script.contains("Nhãn ID phiên"));
assert!(script.contains("data-codex-plus-setting=\"threadIdBadge\""));
assert!(script.contains("codex-thread-id-badge"));
assert!(script.contains("data-codex-thread-id-badge-wrap=\"true\""));
@@ -651,10 +651,10 @@ fn injection_script_exposes_fast_service_tier_control() {
assert!(script.contains("codexServiceTierBadgeWired"));
assert!(script.contains("setAttribute(\"role\", \"button\")"));
assert!(script.contains("setAttribute(\"tabindex\", \"0\")"));
- assert!(script.contains("继承 config.toml"));
+ assert!(script.contains("Kế thừa config.toml"));
assert!(script.contains("service_tier=\\\"priority\\\""));
- assert!(script.contains("Fast 仅支持"));
- assert!(script.contains("当前 thread"));
+ assert!(script.contains("Fast chỉ hỗ trợ"));
+ assert!(script.contains("Thread hiện tại"));
assert!(script.contains("standard"));
assert!(script.contains("fast"));
}
diff --git a/crates/codex-plus-core/tests/installers.rs b/crates/codex-plus-core/tests/installers.rs
index 7cd4e79a1..c3a68feb4 100644
--- a/crates/codex-plus-core/tests/installers.rs
+++ b/crates/codex-plus-core/tests/installers.rs
@@ -16,7 +16,7 @@ fn windows_entrypoint_plan_contains_silent_and_manager_entrypoints() {
let plan = build_windows_entrypoint_plan(&options);
assert!(plan.silent_shortcut.ends_with("Codex++.lnk"));
- assert!(plan.manager_shortcut.ends_with("Codex++ 管理工具.lnk"));
+ assert!(plan.manager_shortcut.ends_with("Codex++ Manager.lnk"));
assert_eq!(plan.launcher_path, "C:/Tools/codex-plus-plus.exe");
assert_eq!(plan.manager_path, "C:/Tools/codex-plus-plus-manager.exe");
assert_eq!(plan.silent_icon_path, "C:/Tools/codex-plus-plus.exe");
@@ -56,7 +56,7 @@ fn windows_entrypoint_plan_can_request_owned_data_removal_without_shell_script()
let plan = build_windows_entrypoint_plan(&options);
assert!(plan.silent_shortcut.ends_with("Codex++.lnk"));
- assert!(plan.manager_shortcut.ends_with("Codex++ 管理工具.lnk"));
+ assert!(plan.manager_shortcut.ends_with("Codex++ Manager.lnk"));
assert!(plan.remove_owned_data);
}
@@ -73,12 +73,12 @@ fn macos_bundle_metadata_contains_silent_and_manager_apps() {
let manager = build_macos_app_bundle(&options, true);
assert!(silent.app_path.ends_with("Codex++.app"));
- assert!(manager.app_path.ends_with("Codex++ 管理工具.app"));
+ assert!(manager.app_path.ends_with("Codex++ Manager.app"));
assert!(silent.info_plist.contains("Codex++"));
assert!(
manager
.info_plist
- .contains("Codex++ 管理工具")
+ .contains("Codex++ Manager")
);
assert_eq!(
silent.binary_target_name.as_deref(),
@@ -98,8 +98,8 @@ fn macos_bundle_metadata_contains_silent_and_manager_apps() {
#[test]
fn installer_exports_expected_two_entrypoint_names() {
- assert_eq!(shortcut_names(), ("Codex++.lnk", "Codex++ 管理工具.lnk"));
- assert_eq!(app_bundle_names(), ("Codex++.app", "Codex++ 管理工具.app"));
+ assert_eq!(shortcut_names(), ("Codex++.lnk", "Codex++ Manager.lnk"));
+ assert_eq!(app_bundle_names(), ("Codex++.app", "Codex++ Manager.app"));
}
#[test]
@@ -113,7 +113,7 @@ fn macos_dmg_includes_applications_shortcut_for_drag_install() {
#[test]
fn companion_binary_path_resolves_macos_silent_app_next_to_manager_app() {
let manager_exe = std::path::Path::new(
- "/Applications/Codex++ 管理工具.app/Contents/MacOS/CodexPlusPlusManager",
+ "/Applications/Codex++ Manager.app/Contents/MacOS/CodexPlusPlusManager",
);
let companion = companion_binary_path_from_exe(manager_exe, SILENT_BINARY);
@@ -125,7 +125,7 @@ fn companion_binary_path_resolves_macos_silent_app_next_to_manager_app() {
assert_ne!(
companion,
std::path::PathBuf::from(
- "/Applications/Codex++ 管理工具.app/Contents/MacOS/codex-plus-plus"
+ "/Applications/Codex++ Manager.app/Contents/MacOS/codex-plus-plus"
)
);
}
@@ -140,7 +140,7 @@ fn companion_binary_path_resolves_macos_manager_app_next_to_silent_app() {
assert_eq!(
companion,
std::path::PathBuf::from(
- "/Applications/Codex++ 管理工具.app/Contents/MacOS/CodexPlusPlusManager"
+ "/Applications/Codex++ Manager.app/Contents/MacOS/CodexPlusPlusManager"
)
);
}
@@ -151,7 +151,7 @@ fn macos_bundle_does_not_wrap_the_bundle_executable_in_itself() {
install_root: Some("/Applications".into()),
launcher_path: Some("/Applications/Codex++.app/Contents/MacOS/CodexPlusPlus".into()),
manager_path: Some(
- "/Applications/Codex++ 管理工具.app/Contents/MacOS/CodexPlusPlusManager".into(),
+ "/Applications/Codex++ Manager.app/Contents/MacOS/CodexPlusPlusManager".into(),
),
remove_owned_data: false,
};
@@ -168,7 +168,7 @@ fn macos_bundle_does_not_wrap_the_bundle_executable_in_itself() {
assert_eq!(
manager.binary_source,
Some(std::path::PathBuf::from(
- "/Applications/Codex++ 管理工具.app/Contents/MacOS/CodexPlusPlusManager"
+ "/Applications/Codex++ Manager.app/Contents/MacOS/CodexPlusPlusManager"
))
);
assert!(silent.launch_script.contains("$DIR/codex-plus-plus"));
diff --git a/scripts/installer/macos/package-dmg.sh b/scripts/installer/macos/package-dmg.sh
index 287778ee2..2c6726547 100755
--- a/scripts/installer/macos/package-dmg.sh
+++ b/scripts/installer/macos/package-dmg.sh
@@ -119,13 +119,13 @@ verify_app() {
prepare_icon
create_app "Codex++" "CodexPlusPlus" "$BINARY_DIR/codex-plus-plus" "com.bigpizzav3.codexplusplus" "true"
-create_app "Codex++ 管理工具" "CodexPlusPlusManager" "$BINARY_DIR/codex-plus-plus-manager" "com.bigpizzav3.codexplusplus.manager" "false"
+create_app "Codex++ Manager" "CodexPlusPlusManager" "$BINARY_DIR/codex-plus-plus-manager" "com.bigpizzav3.codexplusplus.manager" "false"
sign_app "$STAGE/Codex++.app"
-sign_app "$STAGE/Codex++ 管理工具.app"
+sign_app "$STAGE/Codex++ Manager.app"
verify_app "$STAGE/Codex++.app"
-verify_app "$STAGE/Codex++ 管理工具.app"
+verify_app "$STAGE/Codex++ Manager.app"
ln -s /Applications "$STAGE/Applications"
diff --git a/scripts/installer/windows/CodexPlusPlus.nsi b/scripts/installer/windows/CodexPlusPlus.nsi
index 59506bdd4..505f458e8 100644
--- a/scripts/installer/windows/CodexPlusPlus.nsi
+++ b/scripts/installer/windows/CodexPlusPlus.nsi
@@ -36,15 +36,21 @@ Section "Install"
File "${ROOT}\dist\windows\app\codex-plus-plus.exe"
File "${ROOT}\dist\windows\app\codex-plus-plus-manager.exe"
+ Delete "$DESKTOP\Codex++ Manager.lnk"
+ Delete "$DESKTOP\Codex++ 管理工具.lnk"
Delete "$DESKTOP\Codex++ 绠$悊宸ュ叿.lnk"
+ Delete "$SMPROGRAMS\Codex++\Codex++ Manager.lnk"
+ Delete "$SMPROGRAMS\Codex++\Codex++ 管理工具.lnk"
Delete "$SMPROGRAMS\Codex++\Codex++ 绠$悊宸ュ叿.lnk"
+ Delete "$SMPROGRAMS\Codex++\Uninstall Codex++.lnk"
+ Delete "$SMPROGRAMS\Codex++\卸载 Codex++.lnk"
CreateShortcut "$DESKTOP\Codex++.lnk" "$INSTDIR\codex-plus-plus.exe" "" "$INSTDIR\codex-plus-plus.exe"
- CreateShortcut "$DESKTOP\Codex++ 管理工具.lnk" "$INSTDIR\codex-plus-plus-manager.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
+ CreateShortcut "$DESKTOP\Codex++ Manager.lnk" "$INSTDIR\codex-plus-plus-manager.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
CreateDirectory "$SMPROGRAMS\Codex++"
CreateShortcut "$SMPROGRAMS\Codex++\Codex++.lnk" "$INSTDIR\codex-plus-plus.exe" "" "$INSTDIR\codex-plus-plus.exe"
- CreateShortcut "$SMPROGRAMS\Codex++\Codex++ 管理工具.lnk" "$INSTDIR\codex-plus-plus-manager.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
- CreateShortcut "$SMPROGRAMS\Codex++\卸载 Codex++.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
+ CreateShortcut "$SMPROGRAMS\Codex++\Codex++ Manager.lnk" "$INSTDIR\codex-plus-plus-manager.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
+ CreateShortcut "$SMPROGRAMS\Codex++\Uninstall Codex++.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\codex-plus-plus-manager.exe"
WriteUninstaller "$INSTDIR\uninstall.exe"
WriteRegStr HKCU "Software\Codex++" "InstallDir" "$INSTDIR"
@@ -63,11 +69,14 @@ Section "Uninstall"
Pop $0
Delete "$DESKTOP\Codex++.lnk"
+ Delete "$DESKTOP\Codex++ Manager.lnk"
Delete "$DESKTOP\Codex++ 管理工具.lnk"
Delete "$DESKTOP\Codex++ 绠$悊宸ュ叿.lnk"
Delete "$SMPROGRAMS\Codex++\Codex++.lnk"
+ Delete "$SMPROGRAMS\Codex++\Codex++ Manager.lnk"
Delete "$SMPROGRAMS\Codex++\Codex++ 管理工具.lnk"
Delete "$SMPROGRAMS\Codex++\Codex++ 绠$悊宸ュ叿.lnk"
+ Delete "$SMPROGRAMS\Codex++\Uninstall Codex++.lnk"
Delete "$SMPROGRAMS\Codex++\卸载 Codex++.lnk"
RMDir "$SMPROGRAMS\Codex++"
diff --git a/tools/build_i18n_vi.py b/tools/build_i18n_vi.py
new file mode 100644
index 000000000..912d88951
--- /dev/null
+++ b/tools/build_i18n_vi.py
@@ -0,0 +1,42 @@
+import json
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+DATA = json.loads((ROOT / "tools/i18n-export.json").read_text(encoding="utf-8"))
+CACHE_PATH = ROOT / "tools/i18n-vi-cache.json"
+cache = json.loads(CACHE_PATH.read_text(encoding="utf-8")) if CACHE_PATH.exists() else {}
+
+def esc(s: str) -> str:
+ return s.replace("\\", "\\\\").replace(""", "\"").replace("
+", "
+").replace("
", "")
+
+def vi(en: str) -> str:
+ return cache.get(en, en)
+
+def block(name: str, mapping: dict) -> str:
+ lines = [f"export const {name}: Record = {{"]
+ for zh, en in mapping.items():
+ lines.append(f" "{esc(zh)}": "{esc(vi(en))}",")
+ lines.append("};")
+ return "
+".join(lines)
+
+parts = [
+ "// Vietnamese UI. Refresh: python tools/gen-i18n-vi.py then python tools/build_i18n_vi.py
+",
+ block("VI_PLAIN", DATA["plain"]),
+ block("VI_TEMPLATE", DATA["template"]),
+ block("VI_BACKEND", DATA["backend"]),
+ "export const VI_BACKEND_PATTERNS: Array<[RegExp, string]> = [",
+]
+for src, en_rep in DATA["patterns"]:
+ parts.append(f" [new RegExp({json.dumps(src)}), {json.dumps(vi(en_rep))}],")
+parts.append("];
+")
+out = ROOT / "apps/codex-plus-manager/src/i18n-vi.ts"
+out.write_text("
+
+".join(parts), encoding="utf-8")
+hit = sum(1 for en in DATA["plain"].values() if en in cache)
+print(out, "cache", len(cache), "plain_vi", hit, "/", len(DATA["plain"]))
diff --git a/tools/gen-i18n-vi.mjs b/tools/gen-i18n-vi.mjs
new file mode 100644
index 000000000..9c1e36ca1
--- /dev/null
+++ b/tools/gen-i18n-vi.mjs
@@ -0,0 +1,27 @@
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
+const exportPath = path.join(root, "tools/i18n-export.json");
+const cachePath = path.join(root, "tools/i18n-vi-cache.json");
+const outPath = path.join(root, "apps/codex-plus-manager/src/i18n-vi.ts");
+const data = JSON.parse(fs.readFileSync(exportPath, "utf8"));
+const cache = fs.existsSync(cachePath) ? JSON.parse(fs.readFileSync(cachePath, "utf8")) : {};
+function esc(s){return s.replaceAll("\\","\\\\").replaceAll("\"","\\\"").replaceAll("
+","\n").replaceAll("
","");}
+function viFromEn(en){return cache[en]??en;}
+function emitRecord(name,zhToEn){const lines=[`export const ${name}: Record = {`];for(const[zh,en]of Object.entries(zhToEn))lines.push(` "${esc(zh)}": "${esc(viFromEn(en))}",`);lines.push("};");return lines.join("
+");}
+const patLines=["export const VI_BACKEND_PATTERNS: Array<[RegExp, string]> = ["];
+for(const[src,enRep]of data.patterns)patLines.push(` [new RegExp(${JSON.stringify(src)}), ${JSON.stringify(viFromEn(enRep))}],`);
+patLines.push("];");
+const body=[emitRecord("VI_PLAIN",data.plain),emitRecord("VI_TEMPLATE",data.template),emitRecord("VI_BACKEND",data.backend),patLines.join("
+")].join("
+
+");
+fs.writeFileSync(outPath,"// Vietnamese UI
+
+"+body+"
+");
+const hit=Object.values(data.plain).filter(en=>cache[en]).length;
+console.log("wrote",outPath,hit,Object.keys(data.plain).length);
\ No newline at end of file
diff --git a/tools/gen-i18n-vi.py b/tools/gen-i18n-vi.py
new file mode 100644
index 000000000..a91c93169
--- /dev/null
+++ b/tools/gen-i18n-vi.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+"""Generate i18n-vi.ts from tools/i18n-export.json (EN values -> VI)."""
+import json, time
+from pathlib import Path
+from deep_translator import GoogleTranslator
+
+ROOT = Path(__file__).resolve().parent.parent
+EXPORT = ROOT / "tools" / "i18n-export.json"
+OUT = ROOT / "apps" / "codex-plus-manager" / "src" / "i18n-vi.ts"
+CACHE = ROOT / "tools" / "i18n-vi-cache.json"
+SLEEP = 0.35
+
+def esc(s):
+ return s.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\n").replace("\r", "")
+
+def translate_map(tr, mapping, cache):
+ out = {}
+ items = list(mapping.items())
+ for i, (zh_key, en_val) in enumerate(items):
+ if en_val in cache:
+ out[zh_key] = cache[en_val]
+ continue
+ try:
+ vi = tr.translate(en_val)
+ cache[en_val] = vi
+ out[zh_key] = vi
+ except Exception as e:
+ print("fail", i, repr(e))
+ out[zh_key] = en_val
+ cache[en_val] = en_val
+ if (i + 1) % 10 == 0:
+ CACHE.write_text(json.dumps(cache, ensure_ascii=False), encoding="utf-8")
+ print(i + 1, "/", len(items))
+ time.sleep(SLEEP)
+ return out
+
+def emit_record(name, mapping):
+ lines = ["export const %s: Record = {" % name]
+ for k, v in mapping.items():
+ lines.append(' "%s": "%s",' % (esc(k), esc(v)))
+ lines.append("};")
+ return "\n".join(lines)
+
+def main():
+ data = json.loads(EXPORT.read_text(encoding="utf-8"))
+ cache = json.loads(CACHE.read_text(encoding="utf-8")) if CACHE.exists() else {}
+ tr = GoogleTranslator(source="en", target="vi")
+ vi_plain = translate_map(tr, data["plain"], cache)
+ vi_template = translate_map(tr, data["template"], cache)
+ vi_backend = translate_map(tr, data["backend"], cache)
+ vi_patterns = []
+ for src, en_rep in data["patterns"]:
+ if en_rep in cache:
+ vi_rep = cache[en_rep]
+ else:
+ try:
+ vi_rep = tr.translate(en_rep)
+ cache[en_rep] = vi_rep
+ except Exception:
+ vi_rep = en_rep
+ time.sleep(SLEEP)
+ vi_patterns.append((src, vi_rep))
+ CACHE.write_text(json.dumps(cache, ensure_ascii=False), encoding="utf-8")
+ header = "// Vietnamese translations for Codex++ manager UI (tools/gen-i18n-vi.py)\n\n"
+ parts = [emit_record("VI_PLAIN", vi_plain), emit_record("VI_TEMPLATE", vi_template), emit_record("VI_BACKEND", vi_backend)]
+ pat_lines = ["export const VI_BACKEND_PATTERNS: Array<[RegExp, string]> = ["]
+ for src, vi_rep in vi_patterns:
+ pat_lines.append(" [new RegExp(%s), %s]," % (json.dumps(src), json.dumps(vi_rep)))
+ pat_lines.append("];")
+ OUT.write_text(header + "\n\n".join(parts) + "\n\n" + "\n".join(pat_lines) + "\n", encoding="utf-8")
+ print("wrote", OUT)
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/i18n-export.json b/tools/i18n-export.json
new file mode 100644
index 000000000..4df12bf16
--- /dev/null
+++ b/tools/i18n-export.json
@@ -0,0 +1 @@
+{"plain":{"JOJO Code 包月":"JOJO Code Monthly","Codex++ 管理工具":"Codex++ Manager","小米 MiMo":"Xiaomi MiMo","百度千帆 Coding Plan":"Baidu Qianfan Coding Plan","火山引擎 Ark":"Volcengine Ark","API Key 模式下扩展插件市场请求,尽量显示完整插件列表;官方/混合模式通常不需要。":"Expands plugin marketplace requests in API Key mode to show the full plugin list. Usually unnecessary in official/mixed mode.","API Key 环境变量":"API Key environment variable","Chat Completions 转 Responses":"Chat Completions to Responses","Codex 启动参数":"Codex launch arguments","Codex 工具与插件":"Codex tools & plugins","Codex 应用":"Codex app","Codex 应用路径":"Codex app path","Codex 意外停止":"Codex stopped unexpectedly","Codex 版本":"Codex version","Codex 目标":"Codex goals","Codex++ 官方中转站,主打稳定接入和划算价格,支持 GPT-5.5、GPT-5.4、Claude Opus 4.8、Claude Opus 4.7、gpt-image-2 等模型与图像能力。":"The official Codex++ relay, built for stable access and good value, supporting GPT-5.5, GPT-5.4, Claude Opus 4.8, Claude Opus 4.7, gpt-image-2 and other models plus image capabilities.","Codex++ 导入":"Codex++ import","Codex++ 版本":"Codex++ version","Codex增强":"Codex enhancements","Codex增强模式":"Codex enhancement mode","Debug 端口":"Debug port","Fast 按钮":"Fast button","GitHub Release 更新":"GitHub Release update","GitHub Release 检查":"GitHub Release check","Helper 端口":"Helper port","MCP、Skills、Plugins 作为全局配置独立管理,切换任意供应商都会合并。":"MCP, Skills and Plugins are managed independently as global config and merged in whenever you switch providers.","Markdown 导出":"Markdown export","Provider 同步目标":"Provider sync target","Stepwise 直接发送":"Stepwise direct send","基于当前对话生成下一步建议,使用独立 API 配置。":"Generate next-step suggestions from the current conversation using a separate API configuration.","插件与模型":"Plugins and models","管理插件市场、模型列表和服务档位相关增强。":"Manage enhancements for the plugin marketplace, model list and service tier.","对话与输入":"Conversation and input","调整会话管理、输入行为和对话阅读体验。":"Adjust session management, input behavior and conversation reading experience.","界面与启动":"Interface and startup","控制语言、启动速度和 Codex 原生界面调整。":"Control language, startup speed and Codex native UI adjustments.","远程项目":"Remote projects","连接 Zed Remote 和 upstream worktree 辅助能力。":"Connect Zed Remote and upstream worktree helper capabilities.","最多建议数":"Max suggestions","最大输入字符":"Max input characters","最大输出 tokens":"Max output tokens","测试连接":"Test connection","超时毫秒":"Timeout milliseconds","连接":"Connection","高级参数":"Advanced parameters","TOML 配置体":"TOML config body","Watcher 操作":"Watcher action","Watcher 状态":"Watcher status","Watcher 用于保持 Codex++ 接管状态":"The watcher keeps Codex++ in control","Watcher 自动接管":"Watcher auto-takeover","Zed 远程打开":"Zed remote open","Zed 远程项目":"Zed remote projects","Zed 项目记录":"Zed project history","Zed 默认打开策略":"Default Zed open strategy","Zed 默认行为":"Zed default behavior","cc-switch 导入":"cc-switch import","config.toml 预览":"config.toml preview","provider 未记录":"provider not recorded","ssh:// URL 已复制。":"ssh:// URL copied.","、":", ","」的供应商":"”","上一次切换还没有完成,请稍后再试。":"The previous switch hasn't finished yet. Please try again shortly.","上下文大小":"Context size","上下文窗口":"Context window","上次修复结果":"Last repair result","上次更新结果":"Last update result","上游协议":"Upstream protocol","下载并运行安装包":"Download and run installer","不写 API 文件":"Does not write API files","与 Codex 内插件菜单使用同一个远端广告源":"Uses the same remote ad source as the in-Codex plugin menu","个":"","个会话":" session(s)","中国官方":"China official","主页":"Homepage","主题和启动参数":"Theme and launch arguments","从 GitHub 静态清单加载":"Loaded from the static GitHub manifest","从 Word 等富文本粘贴到 Codex composer 时只保留纯文本,避免被识别为图片/文件附件。需重启 Codex 才生效。":"Keeps only plain text when pasting rich text (e.g. from Word) into the Codex composer, avoiding it being treated as an image/file attachment. Requires restarting Codex.","从上游获取":"Fetch from upstream","从最新 upstream 分支创建 Git worktree。":"Create a Git worktree from the latest upstream branch.","从环境变量和 config.toml 的 /v1/models 拉取模型并补进模型列表。":"Pull models from environment variables and config.toml's /v1/models and add them to the model list.","从第三方导入":"Import from third party","从预设模板创建":"Create from a preset template","会话":"Session","会话 ID 标识":"Session ID badge","会话删除":"Session deletion","会话删除、导出、项目移动和用户脚本等界面能力":"UI capabilities like session deletion, export, project move and user scripts","会话删除、导出、项目移动和脚本能力":"Session deletion, export, project move and script capabilities","会话总数":"Total sessions","会话管理":"Session management","会话项目移动":"Session project move","使用":"Use","使用中":"In use","例如 C:\\Program Files\\WindowsApps\\OpenAI.Codex...\\app":"e.g. C:\\Program Files\\WindowsApps\\OpenAI.Codex...\\app","例如 context7":"e.g. context7","例如 deepseek-v4-pro":"e.g. deepseek-v4-pro","例如 gpt-5.4-mini":"e.g. gpt-5.4-mini","例如 主力聚合池":"e.g. Primary aggregate pool","供":"P","供应商":"Provider","供应商切换":"Provider switch","供应商切换不可用":"Provider switching unavailable","供应商切换中":"Switching provider","供应商列表":"Provider list","供应商测试":"Provider test","供应商测试模型":"Provider test model","供应商配置":"Provider configuration","供应商配置可能不正确":"Provider configuration may be incorrect","供应商配置已关闭":"Provider configuration disabled","供应商配置总开关已关闭":"The provider configuration master switch is off","供应商配置总开关已关闭;当前只保存配置,不写入 Codex live 文件":"The provider configuration master switch is off; changes are only saved, not written to Codex live files","供应商预设列表":"Provider preset list","保存":"Save","保存为默认路径":"Save as default path","保存到 Codex++ state,不改写 Zed settings。":"Saved to Codex++ state, does not modify Zed settings.","保存增强设置":"Save enhancement settings","保存扩展项":"Save entry","保存的应用路径":"Saved app path","保存策略":"Save strategy","保存自动修复设置":"Save auto-repair settings","保存设置":"Save settings","保存路径":"Saved path","修复入口":"Repair entrypoints","修复快捷方式":"Repair shortcuts","修复插件市场":"Repair plugin marketplace","健康检查":"Health check","先添加至少 1 个已填写 Base URL / Key 的 API 供应商,再创建聚合供应商。":"Add at least 1 API provider with a Base URL / Key before creating an aggregate provider.","免安装版或解包版只需要选择一次,之后静默启动会自动复用":"Portable or unpacked builds only need to be selected once; silent launch reuses it afterwards","入口卸载":"Entrypoint uninstall","入口安装":"Entrypoint install","入口安装、修复、Watcher 与手动启动":"Entrypoint install, repair, watcher and manual launch","入口管理":"Entrypoint management","全选当前列表":"Select all in current list","关于":"About","关于 Codex++":"About Codex++","关闭":"Off","关闭后会停用删除、导出、项目移动、插件相关和菜单位置增强。":"When off, disables deletion, export, project move, plugin-related and menu placement enhancements.","关闭后本工具不会在手动切换时写入 Codex 的 config.toml / auth.json;启动 Codex 时始终不会自动改这些文件。":"When off, this tool won't write Codex's config.toml / auth.json on manual switches; it never auto-modifies these files when launching Codex.","兼容增强":"Compatible enhancement","内容来自 BigPizzaV3/Ad-List,分为赞助商推荐和普通推荐。":"Content comes from BigPizzaV3/Ad-List, split into sponsor recommendations and regular recommendations.","内置":"Built-in","内置、手动和市场安装脚本;可在这里启停或删除用户脚本":"Built-in, manual and marketplace-installed scripts; enable, disable or delete user scripts here","内置和用户自定义脚本清单":"Built-in and user-defined script inventory","切换 thread 时恢复上一次浏览位置。":"Restore the last scroll position when switching threads.","切换中":"Switching","切换主题":"Toggle theme","切换到此供应商时会写入 ~/.codex/auth.json":"Switching to this provider writes ~/.codex/auth.json","切换到此供应商时会写入的预览;上下文开关变化会立即反映":"Preview of what gets written when switching to this provider; context toggles are reflected immediately","切换到中文":"Switch to Chinese","切换到越南语":"Switch to Vietnamese","切换到英文":"Switch to English","切换到浅色":"Switch to light","切换到深色":"Switch to dark","切换对话保留位置":"Preserve scroll position across threads","点击建议后自动发送;关闭时只填入输入框。":"Automatically sends after clicking a suggestion. When off, it only fills the composer.","刚刚启动":"Just launched","删除":"Delete","删除会创建本地备份;如果 Codex App 正在使用该会话,建议先关闭对应会话窗口再操作。":"Deletion creates a local backup; if the Codex app is using this session, close the session window first.","删除会话":"Delete session","删除供应商":"Delete provider","删除已选":"Delete selected","删除扩展项":"Delete entry","删除模型":"Delete model","刷新":"Refresh","刷新会话":"Refresh sessions","刷新列表":"Refresh list","刷新市场":"Refresh marketplace","刷新当前页面":"Refresh current page","刷新推荐":"Refresh recommendations","刷新本地":"Refresh local","刷新项目":"Refresh projects","加入当前工作区":"Add to current workspace","包含版本、路径、设置和平台信息":"Includes version, paths, settings and platform info","协议":"Protocol","卸载入口":"Uninstall entrypoints","卸载时移除 Codex++ 托管数据":"Remove Codex++ managed data on uninstall","历史会话修复":"Historical session repair","历史会话修复失败,请查看错误提示后重试。":"Historical session repair failed. Check the error message and retry.","历史会话修复进度":"Historical session repair progress","压缩上下文大小":"Compaction context size","原生菜单栏位置":"Native menu bar placement","原生菜单汉化":"Native menu localization","反馈问题":"Report an issue","发现":"Discovered","发送 hi 测试":"Send a 'hi' test","取消":"Cancel","只保留非 MCP、Skills、Plugins 的跨供应商配置;工具与插件在独立页面管理。":"Keeps only cross-provider config that isn't MCP/Skills/Plugins; tools and plugins are managed on a separate page.","只填写表头下面的内容,例如:\ncommand = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]":"Fill in only the content under the header, for example:\ncommand = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]","只能勾选已填写 Base URL / Key 的 API 供应商,聚合供应商不会作为成员。":"Only API providers with a Base URL / Key can be selected; aggregate providers can't be members.","可更新":"Update available","同一对话保持一个成员,不同对话依次分配。":"Keeps one member per conversation; different conversations are assigned in turn.","同步 Zed settings":"Sync Zed settings","同步目标":"Sync target","名称":"Name","启动 Codex App 时追加到默认 CDP 参数后。留空则保持默认启动行为。":"Appended after the default CDP arguments when launching the Codex app. Leave empty to keep default launch behavior.","启动 Codex++":"Launch Codex++","启动任务":"Launch task","启动前自动修复历史会话":"Auto-repair historical sessions before launch","启动时通过本地主进程调试端口汉化 Codex 原生菜单;不修改安装包。需重启 Codex 才生效。":"Localizes the Codex native menu via the local main-process debug port at launch; doesn't modify the install package. Requires restarting Codex.","启用":"Enable","启用 Codex 图片覆盖层":"Enable Codex image overlay","启用 Codex增强":"Enable Codex enhancements","启用 Windows Computer Use Guard":"Enable Windows Computer Use Guard","启用供应商配置切换":"Enable provider configuration switching","启用此扩展项":"Enable this entry","启用目标功能":"Enable goals feature","图片":"Image","图片覆盖层":"Image overlay","在会话列表悬停显示删除按钮,并支持撤销。":"Show a delete button on hover in the session list, with undo support.","在会话列表显示导出按钮,导出带时间戳的 Markdown。":"Show an export button in the session list to export timestamped Markdown.","在 Codex 页面显示可拖动的后续建议浮层;建议由单独配置的 Stepwise API 生成。":"Shows a draggable follow-up suggestion overlay in the Codex page. Suggestions are generated by a separate Stepwise API.","在侧边栏会话标题前显示短 ID 和 UUIDv7 创建时间,方便定位历史会话。":"Show a short ID and UUIDv7 creation time before session titles in the sidebar to help locate past sessions.","基础设置":"Basic settings","填写中转服务 Base URL":"Enter the relay service Base URL","复制":"Copy","复制 ssh:// URL":"Copy ssh:// URL","复制失败":"Copy failed","复制报告":"Copy report","复用窗口":"Reuse window","多选":"Multi-select","失败":"Failed","失败切换":"Failover","失败切换会保留成员顺序,优先使用第一个可用供应商。":"Failover preserves member order, preferring the first available provider.","如果使用官方模式或官方混入 API 模式,通常不需要开启插件市场解锁。":"If you use official mode or official mixed-API mode, you usually don't need plugin marketplace unlock.","安装":"Install","安装 watcher":"Install watcher","安装入口":"Install entrypoints","安装包更新失败,请查看错误提示后重试。":"Installer update failed. Check the error message and retry.","安装包更新进度":"Installer update progress","安装维护":"Install & maintenance","完整增强":"Full enhancement","官方":"Official","官方中转站":"Official relay","官方混入 API Key":"Official mixed-in API Key","官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的 auth.json 后再切换。":"Official mixed API should not store OPENAI_API_KEY in auth.json. Clear this provider's auth.json before switching.","官方登录":"Official login","官方登录模式":"Official login mode","对话居中宽度":"Centered conversation width","导入 Codex++ 供应商":"Import Codex++ provider","尚未刷新":"Not refreshed yet","尚未加载推荐内容":"Recommendations not loaded yet","尚未检查 Codex 应用路径。":"Codex app path not checked yet.","尚未检查 GitHub Release;更新会下载并启动安装包。":"GitHub Release not checked yet; updating downloads and launches the installer.","尚未生成诊断报告。":"No diagnostic report generated yet.","尚未运行安装包更新。":"Installer update has not run yet.","尚未运行历史会话修复。":"Historical session repair hasn't run yet.","尚未运行插件市场修复。":"Plugin marketplace repair hasn't run yet.","尚未检查官方远端插件缓存。":"Official remote plugin cache has not been checked yet.","正在检查内置官方远端插件缓存…":"Checking embedded official remote plugin cache…","正在释放内置远端插件快照…":"Extracting embedded remote plugin snapshot…","正在注册官方远端插件市场…":"Registering official remote plugin marketplace…","正在刷新官方远端插件缓存状态…":"Refreshing official remote plugin cache status…","正在处理…":"Processing…","工具与插件":"Tools & plugins","已切回官方登录;Codex增强已设为兼容增强。":"Switched back to official login; Codex enhancements set to compatible.","已切换到纯 API;Codex增强已设为完整增强。":"Switched to pure API; Codex enhancements set to full.","已切换到聚合供应商;真实对话会按所选策略轮转成员。":"Switched to aggregate provider; real conversations rotate members per the chosen strategy.","已刷新 Codex 应用、入口和 Watcher 状态。":"Refreshed Codex app, entrypoint and watcher status.","已受理":"Accepted","已安装":"Installed","已归档":"Archived","已打开聚合供应商详情;请先添加或完善至少 1 个普通 API 供应商的 Base URL / Key,再勾选为成员。":"Opened aggregate provider details; first add or complete the Base URL / Key of at least 1 regular API provider, then select it as a member.","已找到":"Found","已按此供应商使用官方登录,并混入 API Key;Codex增强已设为兼容增强。":"Using official login for this provider with the API Key mixed in; Codex enhancements set to compatible.","已按此供应商切回官方登录;Codex增强已设为兼容增强。":"Switched back to official login for this provider; Codex enhancements set to compatible.","已按此供应商切换到纯 API;Codex增强已设为完整增强。":"Switched to pure API for this provider; Codex enhancements set to full.","已检测":"Detected","已注册":"Registered","已缓存未注册":"Cached, not registered","已清除保存路径,后续启动会回到自动探测。":"Saved path cleared; future launches fall back to auto-detection.","已登录":"Logged in","已禁用":"Disabled","已选择":"Selected","市场状态":"Marketplace status","市场脚本":"Marketplace scripts","序列化字段":"Serialized fields","应用路径已保存,之后启动会自动复用。":"App path saved; future launches reuse it automatically.","应用路径留空时使用已保存路径;没有保存路径时使用自动探测":"When the app path is empty, the saved path is used; with no saved path, auto-detection is used","应用路径覆盖":"App path override","开启":"On","开启后,通过 Codex++ 启动 Codex 前自动整理一次旧对话的归属标记。":"When on, tidies up ownership tags of old conversations once before launching Codex through Codex++.","强制中文界面":"Force Chinese UI","强制启用 Codex App 内置 zh-CN 语言包,避免 Statsig/VPN 不通时回退英文。需重启 Codex 才能完整生效。":"Forces the Codex app's built-in zh-CN language pack to avoid falling back to English when Statsig/VPN is unreachable. Requires restarting Codex to fully apply.","当前":"Current","当前 provider":"current provider","当前不会写入 Codex config.toml / auth.json。打开供应商配置总开关后再切换。":"Codex config.toml / auth.json won't be written right now. Turn on the provider configuration master switch before switching.","当前为":"Currently ","当前为兼容增强模式,插件市场解锁不会启用;其他页面功能仍可用。":"Currently in compatible enhancement mode; plugin marketplace unlock is not enabled, but other page features still work.","当前会话":"Current session","当前使用中:打开时从 ~/.codex/auth.json 回填,保存后会作为此供应商 auth 存档":"Currently in use: backfilled from ~/.codex/auth.json when opened; saving stores it as this provider's auth archive","当前供应商 config.toml 里没有可提取的通用配置。":"The current provider's config.toml has no extractable common config.","当前供应商切换后会写入的预览;上下文开关变化会立即反映":"Preview of what the current provider writes after switching; context toggles are reflected immediately","当前供应商还没有完整 config.toml / API Key 存档。":"The current provider doesn't have a complete config.toml / API Key archive yet.","当前共有":"There are currently ","当前未登录官方账号,也未配置混入 API 的 Base URL / Key。":"Not logged into an official account, and no mixed-in API Base URL / Key configured.","当前未登录官方账号;切到官方登录模式后仍需要先在 Codex/ChatGPT 登录。":"Not logged into an official account; after switching to official login mode you still need to log in via Codex/ChatGPT first.","当前未登录官方账号;官方登录混入 API Key 需要先登录官方账号。":"Not logged into an official account; official login with a mixed-in API Key requires logging into an official account first.","当前正在使用":"Currently in use","当前识别":"Currently detected","当前还没有填写混入 API 的 Base URL / Key。":"The mixed-in API Base URL / Key hasn't been filled in yet.","当前进程":"Current process","当前配置 provider":"Currently configured provider","快捷方式修复":"Shortcut repair","快捷方式写入系统实际桌面位置,不使用写死桌面路径":"Shortcuts are written to the system's actual desktop location, not a hardcoded desktop path","快速启动":"Fast startup","总权重":"Total weight","成员供应商":"Member providers","成员数量":"Member count","或":" or ","手动":"Manual","手动启动":"Manual launch","打开":"Open","打开 JOJO Code":"Open JOJO Code","打开关于":"Open About","打开链接":"Open link","打开项目主页":"Open project homepage","扩展项":"entry","批量删除会话":"Bulk delete sessions","把 Codex++ 菜单插入 Codex 顶部原生菜单栏。":"Insert the Codex++ menu into Codex's top native menu bar.","把主对话和输入框限制到固定最大宽度,适合大屏阅读。":"Constrain the main conversation and input box to a fixed max width, good for large-screen reading.","把会话移动到普通对话或其他本地项目。":"Move a session to a regular conversation or another local project.","投稿":"Submit","拖动排序":"Drag to reorder","按对话轮转":"Per-conversation round-robin","按对话轮转会让同一对话尽量保持固定成员,降低上下文漂移。":"Per-conversation round-robin keeps the same conversation on a fixed member where possible, reducing context drift.","按成员权重分配请求,权重越高承担越多。":"Distribute requests by member weight; higher weight takes on more.","按成员顺序请求,失败后切到下一个供应商。":"Request members in order, switching to the next provider on failure.","按更新时间倒序显示":"Sorted by update time, newest first","按请求轮转":"Per-request round-robin","按请求轮转会逐请求切换成员,适合供应商能力接近的场景。":"Per-request round-robin switches members request by request, suited to providers with similar capabilities.","接入模式":"Access mode","推荐内容":"Recommendations","提取当前供应商配置":"Extract current provider config","插件":"Plugins","插件列表全量展示":"Show full plugin list","插件市场修复":"Plugin marketplace repair","插件市场修复失败,请查看错误提示后重试。":"Plugin marketplace repair failed. Check the error message and retry.","插件市场修复进度":"Plugin marketplace repair progress","插件市场解锁":"Plugin marketplace unlock","官方远端插件缓存":"Official remote plugin cache","官方远端插件缓存进度":"Official remote plugin cache progress","官方远端插件缓存修复失败,请查看错误提示后重试。":"Official remote plugin cache repair failed. Check the error message and retry.","使用 Codex++ 内置快照补齐远端插件,API 模式也可显示和安装 Product Design 插件。":"Use the embedded Codex++ snapshot to add remote plugins, so API mode can also show and install the Product Design plugin.","搜索供应商…":"Search providers…","数据库":"Database","新增":"Add ","新建供应商需要先保存到列表":"A new provider must be saved to the list first","新机器没有本地插件市场时,可从 openai/plugins 初始化到当前 CODEX_HOME。":"On a new machine without a local plugin marketplace, initialize it into the current CODEX_HOME from openai/plugins.","新窗口":"New window","日志已刷新":"Logs refreshed","日志已复制。":"Logs copied.","时间":"Time","释放并注册内置缓存":"Extract and register embedded cache","显示服务模式切换按钮;Fast 仅支持 gpt-5.4 / gpt-5.5,其他模型按 Standard 发送。":"Show the service-tier toggle button; Fast only supports gpt-5.4 / gpt-5.5, other models are sent as Standard.","普通推荐":"Regular recommendations","暂无":"None","暂无启动状态。":"No launch status yet.","暂无描述。":"No description.","暂无日志。":"No logs.","暂无普通推荐。":"No regular recommendations.","暂无状态文件":"No status file","暂无赞助商推荐。":"No sponsor recommendations.","暂无项目。":"No projects.","更多选项":"More options","更新":"Update","更新安装":"Update install","最新版本":"Latest version","最近启动":"Recent launches","最近打开":"Recently opened","最近日志":"Recent logs","未发现可导入供应商":"No importable providers found","未发现用户脚本。":"No user scripts found.","未命名会话":"Untitled session","未命名供应商":"Untitled provider","未命名聚合供应商":"Untitled aggregate provider","未填写":"Not filled in","未填写 URL":"No URL filled in","未安装":"Not installed","未实现":"Not implemented","未归档":"Not archived","未检查":"Not checked","未检测到":"Not detected","未检测到 Codex 应用版本。":"Codex app version not detected.","未发现缓存":"Cache not found","未发现本地缓存;点击按钮会从 Codex++ 内置快照释放并注册,无需官方账号预缓存。":"Local cache not found. Click the button to extract and register the embedded Codex++ snapshot; no official-account pre-cache is required.","未知":"Unknown","未知作者":"Unknown author","未知来源":"Unknown source","未知版本":"Unknown version","未记录路径":"No path recorded","未记录项目路径":"No project path recorded","未读取到本地会话,或当前 SQLite 会话库不存在。":"No local sessions read, or the current SQLite session database doesn't exist.","本地 Codex 增强、管理工具和安装包维护":"Local Codex enhancements, management tools and install package maintenance","本地会话":"Local sessions","本地整体":"Local overall","本地脚本":"Local scripts","权重":"Weight","权重轮转":"Weighted round-robin","权重轮转会读取每个成员的权重值,权重越高的成员获得更多请求。":"Weighted round-robin reads each member's weight; members with higher weight receive more requests.","查看、删除和修复 Codex 本地会话":"View, delete and repair Codex local sessions","检查":"Check","检查与修复":"Check & repair","检查入口、Codex 应用和 Watcher 状态":"Check entrypoint, Codex app and watcher status","检查配置、模型列表和一次真实请求,定位供应商不可用原因。":"Check configuration, model list and one real request to find why a provider is unavailable.","检查完成":"Check complete","检查更新":"Check for updates","检查问题、启动与快速修复":"Check issues, launch and quick fixes","诊断供应商":"Diagnose provider","检测":"Detect","检测到 OPENAI 环境变量":"OPENAI environment variables detected","检测到来自网页的供应商配置导入请求,确认后会写入本机 Codex++ 管理工具。":"A provider config import request from the web was detected; confirming writes it to this machine's Codex++ manager.","概览":"Overview","概览只展示关键问题,具体配置在对应页面处理":"The overview shows only key issues; specific configuration is handled on the relevant pages","概览已检查":"Overview checked","模型列表":"Model list","模型名称":"Model name","模型白名单解锁":"Model whitelist unlock","模式":"Mode","模式。":" mode.","正在下载安装包…":"Downloading installer…","正在下载插件市场快照…":"Downloading plugin marketplace snapshot…","正在修复…":"Repairing…","正在修复历史会话":"Repairing historical sessions","正在准备安装包下载…":"Preparing installer download…","正在启动安装包…":"Launching installer…","正在写入 Codex 配置…":"Writing Codex config…","正在写入修复与备份…":"Writing repairs and backups…","正在删除…":"Deleting…","正在扫描历史会话与索引…":"Scanning historical sessions and indexes…","正在检查会话 provider 标记…":"Checking session provider tags…","正在检查本地插件市场…":"Checking local plugin marketplace…","正在获取 GitHub Release 信息…":"Fetching GitHub Release information…","正在解压并校验插件文件…":"Extracting and verifying plugin files…","正在连接 openai/plugins…":"Connecting to openai/plugins…","正常":"OK","此上游会通过本地 127.0.0.1:57321 转成 Responses API,需要从 Codex++ 启动 Codex。":"This upstream is converted to the Responses API via local 127.0.0.1:57321, which requires launching Codex from Codex++.","此供应商会保留官方登录模式,并把请求混入当前 API Key;Codex增强仍使用兼容模式。":"This provider keeps official login mode and mixes the current API Key into requests; Codex enhancements stay in compatible mode.","此供应商会切回官方登录模式,使用 ChatGPT 官方账号,不写入 API Key。":"This provider switches back to official login mode using the official ChatGPT account, without writing an API Key.","此供应商会同时写入 config.toml 和 auth.json;API Key 也会注入到 provider bearer token。":"This provider writes both config.toml and auth.json; the API Key is also injected into the provider bearer token.","每次请求按成员顺序切换,适合均匀摊请求量。":"Switches members in order on each request, good for evenly spreading request volume.","每行一个参数,例如 --force_high_performance_gpu。不需要填写 open 或 --args。":"One argument per line, e.g. --force_high_performance_gpu. No need to include open or --args.","每行一个模型;上下文窗口可填":"One model per line; the context window can be","没有匹配「":"No providers matching “","浅色":"Light","测试模型":"Test model","消息":"Message","深色":"Dark","混入 API":"Mixed-in API","混入 API KEY":"Mix in API KEY","混入 API Key":"Mix in API Key","添加供应商":"Add provider","添加模型":"Add model","添加聚合供应商":"Add aggregate provider","清空选择":"Clear selection","清除保存路径":"Clear saved path","点击刷新会话读取本地数据库":"Click Refresh Sessions to read the local database","点击刷新市场加载远程脚本。":"Click Refresh Marketplace to load remote scripts.","版本信息、项目链接、GitHub Release 更新、日志与诊断":"Version info, project links, GitHub Release updates, logs and diagnostics","状态":"Status","独立管理 Codex 的 MCP、Skills、Plugins;切换任意供应商都会带上。":"Manage Codex's MCP, Skills and Plugins independently; they carry over whenever you switch providers.","独立管理 MCP、Skills、Plugins":"Independently manage MCP, Skills and Plugins","环境变量":"Environment variables","环境变量检测":"Environment variable detection","环境变量清理":"Environment variable cleanup","用户":"User","用户环境":"User environment","界面主题":"UI theme","留空不改写,例如 160000":"Leave empty to keep unchanged, e.g. 160000","留空不改写,例如 200000":"Leave empty to keep unchanged, e.g. 200000","留空使用默认值":"Leave empty to use the default","登录状态":"Login status","确认删除":"Confirm delete","确认导入":"Confirm import","禁用":"Disable","禁用此扩展项":"Disable this entry","移除 watcher":"Remove watcher","移除最近记录":"Remove from recent","立刻修复历史会话":"Repair historical sessions now","第三方":"Third party","策略":"Strategy","管理 API 供应商、协议、Key 与配置文件":"Manage API providers, protocols, keys and config files","管理 Codex SSH 项目并加入 Zed workspace":"Manage Codex SSH projects and add them to a Zed workspace","管理工具入口":"Manager entrypoint","管理控制台":"Management console","管理控制台入口":"Management console entrypoint","类型":"Type","粘贴修复":"Paste fix","索引":"Index","纯 API":"Pure API","纯 API 就绪:会同时写入 config.toml 和 auth.json。":"Pure API ready: writes both config.toml and auth.json.","纯 API 模式":"Pure API mode","纯 API 配置未完整写入:请检查此供应商是否有 OPENAI_API_KEY,且 config.toml 是否包含 model_provider / provider / base_url。":"Pure API config is incomplete: check whether this provider has OPENAI_API_KEY and whether config.toml includes model_provider / provider / base_url.","维护 Codex++ 自己的远程项目最近列表。":"Maintain Codex++'s own recent list of remote projects.","编辑":"Edit","编辑后保存列表,再切换模式时会使用新配置":"After editing, save the list; the new config is used the next time you switch modes","编辑扩展项":"Edit entry","缺失":"Missing","缺少 Codex++ 静默启动快捷方式时可在安装维护页修复。":"When the Codex++ silent launch shortcut is missing, repair it on the Install & Maintenance page.","缺少管理工具快捷方式时可在安装维护页修复。":"When the manager shortcut is missing, repair it on the Install & Maintenance page.","聚合":"Aggregate","聚合/中转":"Aggregate/relay","聚合供应商":"Aggregate provider","聚合供应商会在真实对话中轮转成员,请测试成员供应商":"Aggregate providers rotate members in real conversations; test the member providers instead","聚合供应商只保存成员和策略配置,成员来自已有 API 供应商;切为当前后会通过本地协议代理轮转请求。":"Aggregate providers only store member and strategy config drawn from existing API providers; once active, requests rotate through the local protocol proxy.","聚合供应商至少需要勾选 1 个已填写 Base URL / Key 的 API 供应商。":"An aggregate provider needs at least 1 selected API provider with a Base URL / Key filled in.","聚合策略":"Aggregate strategy","聚合配置只引用已有供应商,不复制 Key 和配置文件":"Aggregate config only references existing providers; it doesn't copy keys or config files","脚本市场":"Script marketplace","自动接管":"Auto-takeover","覆盖图片":"Overlay image","背景适配方式":"Background fit mode","填充":"Fill","适应":"Fit","拉伸":"Stretch","平铺":"Tile","居中":"Center","记录最近打开":"Record recently opened","设为当前":"Set as current","设置":"Settings","设置保存":"Settings saved","设置已加载":"Settings loaded","设置重置":"Settings reset","诊断已生成":"Diagnostics generated","诊断报告":"Diagnostic report","诊断报告已复制。":"Diagnostic report copied.","点击后会打开诊断弹框,按步骤检查供应商。":"Click to open the diagnostic dialog and check the provider step by step.","正在诊断供应商,请稍候。":"Diagnosing provider, please wait.","诊断已完成。":"Diagnosis complete.","诊断中":"Diagnosing","异常":"Error","完成":"Complete","配置完整性":"Configuration integrity","等待检查 Base URL / API Key。":"Waiting to check Base URL / API Key.","等待检查 /v1/models。":"Waiting to check /v1/models.","真实请求":"Real request","等待发送一次测试请求。":"Waiting to send one test request.","处理建议":"Recommendation","等待生成建议。":"Waiting to generate a recommendation.","正在检查配置完整性…":"Checking configuration integrity…","该步骤未执行。":"This step was not run.","请先填写或选择应用路径。":"Fill in or select an app path first.","请先选择要删除的会话。":"Select the sessions to delete first.","读取 Codex 本地 SQLite 会话库,会删除数据库记录和对应 rollout 文件":"Reads Codex's local SQLite session database; deletes database records and the corresponding rollout files","读取 cc-switch 供应商失败。":"Failed to read cc-switch providers.","读取 ~/.cc-switch/cc-switch.db":"Reading ~/.cc-switch/cc-switch.db","调用失败":"Call failed","资源":"Asset","赞助商推荐":"Sponsor recommendations","赞助商推荐与普通推荐":"Sponsor and regular recommendations","输入中转服务的 API Key":"Enter the relay service API Key","运行中":"Running","返回列表":"Back to list","这些变量可能覆盖当前供应商写入的 config.toml / auth.json;CODEX_HOME 不会被清理。":"These variables may override the config.toml / auth.json written by the current provider; CODEX_HOME won't be cleaned up.","进入插件页后自动连续展开“更多”,尽量一次显示完整插件列表。":"Automatically keep expanding 'More' on the plugins page to show the full plugin list at once.","进度":"Progress","远程 SSH 文件引用可直接用 Zed Remote Development 打开。":"Remote SSH file references can be opened directly with Zed Remote Development.","远程脚本":"Remote scripts","适合官方登录或官方混入 API Key;保留会话删除、导出、项目移动和用户脚本,关闭插件市场相关增强。":"Suited to official login or official mixed-in API Key; keeps session deletion, export, project move and user scripts, while disabling plugin-marketplace-related enhancements.","适合纯 API;启用插件市场、会话删除导出、项目移动等全部页面能力。":"Suited to pure API; enables all page capabilities including plugin marketplace, session deletion/export and project move.","选择 Codex 应用目录":"Select Codex app directory","选择 Codex.exe":"Select Codex.exe","选择 Codex.exe 或 Codex.app":"Select Codex.exe or Codex.app","选择 Codex.exe、Codex.app、app 目录或解包目录":"Select Codex.exe, Codex.app, the app directory or the unpacked directory","选择 png / jpg / webp / gif / bmp":"Select png / jpg / webp / gif / bmp","选择会话":"Select session","选择图片":"Select image","选择已有供应商作为成员,保存后写入 settings payload":"Select existing providers as members; saving writes them to the settings payload","选择应用目录":"Select app directory","选择覆盖图片":"Select overlay image","通用配置文件":"Common config file","配置":"Config","配置文件":"Config file","配置模型":"Config model","重启 Codex++":"Restart Codex++","重新安装":"Reinstall","重新生成":"Regenerate","重置背景":"Reset background","静默启动入口":"Silent launch entrypoint","项目地址":"Project URL","额外参数":"Extra arguments","高级选项,默认关闭;当前实现不主动改写 Zed settings。":"Advanced option, off by default; the current implementation doesn't actively modify Zed settings.","默认中转":"Default relay","默认关闭;开启后启动 Codex 时会自动保留官方 Computer Use 插件所需的 config.toml、bundled 插件和 notify 配置。":"Off by default; when on, launching Codex automatically preserves the config.toml, bundled plugins and notify config required by the official Computer Use plugin.","默认启动 Codex 时使用的模型名,请勿带后缀;上下文窗口请在下方「模型列表」中按模型单独配置。":"The model name used by default when launching Codex; don't include a suffix. Configure context windows per model in the “Model list” below.","默认关闭;无 VPN 时可开启,让 Statsig 初始化快速失败,减少启动时长。需重启 Codex 才生效。":"Off by default; enable it without a VPN to let Statsig initialization fail fast and reduce launch time. Requires restarting Codex.","默认打开策略":"Default open strategy","(":" (",")":")",",可以从通用配置文件或这里新增。":"; you can add them from the common config file or here.",",留空表示使用 Codex 默认长度。":"; leave empty to use Codex's default length.",";这些条目独立于供应商保存,会写入所有供应商切换后的 config.toml。":"; these entries are saved independently of providers and written to config.toml after switching to any provider."},"template":{"\n...以及另外 {0} 个会话":"\n...and {0} more session(s)","{0} · {1} 个成员":"{0} · {1} member(s)","{0} 个":"{0}","{0} 个 Codex++ 可识别项目,默认策略:{1}":"{0} project(s) recognized by Codex++, default strategy: {1}","{0} 个供应商":"{0} provider(s)","{0} 个供应商配置;可拖动排序,点编辑进入详情":"{0} provider configuration(s); drag to reorder, click edit for details","{0} 个市场脚本,已安装 {1} 个,本地整体 {2}":"{0} marketplace script(s), {1} installed, local overall {2}","{0} 个项目":"{0} project(s)","{0} 副本":"{0} copy","{0} 条":"{0} item(s)","供应商 {0}":"Provider {0}","供应商「{0}」缺少独立 config.toml,已停止切换,避免继续显示上一套配置文件。请先在该供应商详情里保存 config.toml。":"Provider “{0}” is missing its own config.toml, so the switch was stopped to avoid showing the previous config files. Save config.toml in this provider's details first.","删除会话“{0}”?此操作会删除本地数据库记录和 rollout 文件,并创建备份。":"Delete session “{0}”? This deletes the local database record and rollout file, and creates a backup.","删除脚本“{0}”?此操作会移除本地脚本文件。":"Delete script “{0}”? This removes the local script file.","删除这些环境变量?\n\n{0}\n\n删除前会写入备份。":"Delete these environment variables?\n\n{0}\n\nA backup is written before deletion.","删除选中的 {0} 个会话?此操作会删除本地数据库记录和 rollout 文件,并为每个会话创建备份。\n\n{1}{2}":"Delete the {0} selected session(s)? This deletes the local database records and rollout files, and creates a backup for each session.\n\n{1}{2}","发现 {0} 个 Codex 供应商":"Found {0} Codex provider(s)","发现新版本 {0}":"New version {0} available","官方登录已就绪:{0},会混入当前 API Key。":"Official login ready: {0}, the current API Key will be mixed in.","官方账号已登录:{0}。":"Official account logged in: {0}.","已删除 {0} 个会话。":"Deleted {0} session(s).","已删除 {0} 个,失败 {1} 个:{2}":"Deleted {0}, failed {1}: {2}","已加载 {0} 条推荐":"Loaded {0} recommendation(s)","已同步到 {0}:修复 {1} 个会话文件,更新 {2} 行索引{3}。":"Synced to {0}: repaired {1} session file(s), updated {2} index row(s){3}.","已安装 {0}":"Installed {0}","已缓存 {0} 个插件 / {1} 个技能。":"Cached {0} plugin(s) / {1} skill(s).","已运行 {0} 分钟":"Running for {0} minute(s)","已运行 {0} 小时 {1} 分钟":"Running for {0} hour(s) {1} minute(s)","市场 · {0}":"Marketplace · {0}","当前版本 {0}":"Current version {0}","打开选择器失败:{0}":"Failed to open the picker: {0}","正在同步到 {0}…":"Syncing to {0}…","清单更新时间:{0}":"Manifest updated at: {0}","留空使用默认:{0}":"Leave empty to use the default: {0}","聚合供应商 {0}":"Aggregate provider {0}","聚合供应商已配置为{0},包含 {1} 个成员;真实对话会走本地代理轮转。":"The aggregate provider is configured as {0} with {1} member(s); real conversations rotate through the local proxy.","进程状态:{0}。是否要重新启动?":"Process status: {0}. Restart?","选择会话 {0}":"Select session {0}","透明度 {0}%":"Opacity {0}%",",跳过 {0} 个占用文件":", skipped {0} locked file(s)"},"backend":{"后端版本已读取。":"Backend version loaded.","启动参数已读取。":"Launch arguments loaded.","概览后台任务失败。":"Overview background task failed.","概览已加载。":"Overview loaded.","启动任务已在后台开始,可稍后查看概览状态。":"Launch task started in the background. Check overview status later.","设置已加载。":"Settings loaded.","设置读取失败":"Failed to read settings","设置保存后重新读取失败":"Failed to reload settings after save","没有新的 cc-switch 供应商配置需要导入。":"No new cc-switch provider configs to import.","导入供应商配置后重新读取设置失败":"Failed to reload settings after importing provider config","待确认供应商导入已读取。":"Pending provider import loaded.","没有待确认的供应商导入。":"No pending provider import.","已取消供应商导入。":"Provider import cancelled.","会话 ID 不能为空。":"Session ID must not be empty.","推荐内容已加载。":"Recommendations loaded.","脚本市场已刷新。":"Script marketplace refreshed.","脚本 id 不能为空。":"Script ID must not be empty.","市场清单中未找到该脚本。":"Script not found in marketplace manifest.","脚本已安装。":"Script installed.","脚本 key 不能为空。":"Script key must not be empty.","脚本已启用。":"Script enabled.","脚本已禁用。":"Script disabled.","脚本启停失败":"Failed to toggle script","脚本已删除。":"Script deleted.","脚本删除失败":"Failed to delete script","只允许打开 http 或 https 链接。":"Only http or https links can be opened.","已在系统浏览器打开链接。":"Link opened in system browser.","安装入口":"Install entrypoints","卸载入口":"Uninstall entrypoints","修复快捷方式":"Repair shortcuts","修复后重新读取设置失败":"Failed to reload settings after repair","插件市场需要初始化或注册。":"Plugin marketplace needs initialization or registration.","插件市场已可用。":"Plugin marketplace is available.","插件市场已从 openai/plugins 初始化并注册。":"Plugin marketplace initialized and registered from openai/plugins.","已注册本地插件市场。":"Local plugin marketplace registered.","插件市场已可用,无需修复。":"Plugin marketplace is available; no repair needed.","官方远端插件缓存需要释放或注册。":"Official remote plugin cache needs extraction or registration.","官方远端插件缓存已可用。":"Official remote plugin cache is available.","已释放并注册内置官方远端插件缓存。":"Embedded official remote plugin cache extracted and registered.","已注册官方远端插件缓存。":"Official remote plugin cache registered.","官方远端插件缓存已可用,无需修复。":"Official remote plugin cache is available; no repair needed.","发现可用更新。":"Update available.","当前已是最新版本。":"Already on the latest version.","请先检查更新并选择可下载的 Release asset。":"Check for updates first and select a downloadable release asset.","安装包已下载并启动,请按安装向导完成更新。":"Installer downloaded and launched. Follow the setup wizard to finish updating.","日志已读取。":"Logs loaded.","诊断报告已生成。":"Diagnostics report generated.","设置已重置为默认值。":"Settings reset to defaults.","设置重置后重新读取失败":"Failed to reload settings after reset","图片覆盖层设置已重置。":"Image overlay settings reset.","图片覆盖层重置后重新读取失败":"Failed to reload settings after image overlay reset","已检测到 ChatGPT 登录状态。":"ChatGPT login detected.","未检测到 ChatGPT 登录状态,请先在 Codex/ChatGPT 中正常登录。":"ChatGPT login not detected. Please log in to Codex/ChatGPT first.","配置文件内容已读取。":"Config file content loaded.","未检测到会覆盖 Codex 供应商配置的 OPENAI 环境变量。":"No OPENAI environment variables found that would override the Codex provider config.","检测到可能覆盖 Codex 供应商配置的 OPENAI 环境变量。":"OPENAI environment variables detected that may override the Codex provider config.","环境变量已按确认项删除;重新启动 Codex 后生效。":"Environment variables deleted as confirmed. Restart Codex for changes to take effect.","配置文件已保存。":"Config file saved.","供应商切换锁已损坏,请重启管理器后再试。":"Provider switch lock is corrupted. Please restart the manager and try again.","供应商已切换。":"Provider switched.","当前供应商已不在配置列表中,已停止切换以避免覆盖用户改动。":"The current provider is no longer in the config list. Switching stopped to avoid overwriting user changes.","当前供应商配置已从 live 文件回填。":"Current provider config backfilled from live files.","工具与插件列表已读取。":"Tools & plugins list loaded.","通用配置已按兼容切换规则提取。":"Common config extracted using compatibility switching rules.","供应商配置总开关已关闭,未写入 config.toml / auth.json。":"Provider config master switch is off. Nothing written to config.toml / auth.json.","已按兼容切换规则切换供应商。":"Provider switched using compatibility rules.","未检测到 ChatGPT 登录状态":"ChatGPT login not detected","未检测到 ChatGPT 登录状态,已停止写入中转配置。":"ChatGPT login not detected. Relay config not written.","中转配置已写入,密钥未在界面明文显示。":"Relay config written. Keys are not shown in plaintext in the UI.","聚合供应商配置已写入,真实请求会由本地代理按策略轮转。":"Aggregate provider config written. Real requests will be rotated by the local proxy according to the strategy.","已清除 custom 中转 API 模式,并切换到官方 ChatGPT 登录模式。":"Custom relay API mode cleared. Switched to official ChatGPT login mode.","纯 API 模式已写入:config.toml 已写入 custom provider,auth.json 已切换为当前供应商。":"Pure API mode written: config.toml now has a custom provider, auth.json switched to the current provider.","纯 API 配置写入后未检测到完整 custom provider,请检查 config.toml 和供应商 API Key。":"After writing pure API config, no complete custom provider was detected. Please check config.toml and the provider API Key.","供应商导入后重新读取设置失败":"Failed to reload settings after provider import","诊断日志已写入。":"Diagnostics log written.","未命名供应商":"Unnamed provider","响应内容为空":"Response is empty"},"patterns":[["^启动静默入口失败:(.+)$","Failed to launch silent entrypoint: $1"],["^无法启动 (.+?):(.+)$","Cannot launch $1: $2"],["^设置已保存。(.*)$","Settings saved.$1"],["^保存设置失败:(.+)$","Failed to save settings: $1"],["^已读取 cc-switch Codex 供应商配置:(\\d+) 个。$","Read $1 cc-switch Codex provider config(s)."],["^读取 cc-switch 供应商配置失败:(.+)$","Failed to read cc-switch provider configs: $1"],["^已从 cc-switch 导入供应商配置:(\\d+) 个。$","Imported $1 cc-switch provider config(s)."],["^保存 cc-switch 供应商配置失败:(.+)$","Failed to save cc-switch provider configs: $1"],["^已导入供应商配置:(.+)。$","Imported provider config: $1."],["^供应商配置已存在:(.+)。$","Provider config already exists: $1."],["^导入供应商配置失败:(.+)$","Failed to import provider config: $1"],["^取消供应商导入失败:(.+)$","Failed to cancel provider import: $1"],["^已读取 (\\d+) 个本地会话。$","Read $1 local session(s)."],["^读取部分本地会话失败:(.+)$","Failed to read some local sessions: $1"],["^已读取 (\\d+) 个 Zed 远程项目。$","Read $1 Zed remote project(s)."],["^读取 Zed 远程项目失败。$","Failed to read Zed remote projects."],["^已在 Zed Remote 打开项目。$","Project opened in Zed Remote."],["^无法在 Zed Remote 打开项目。$","Cannot open project in Zed Remote."],["^移除 Zed 远程项目失败。$","Failed to remove Zed remote project."],["^供应商已同步一次:(\\d+) 个会话文件,(\\d+) 行索引,跳过 (\\d+) 个占用文件。$","Provider synced: $1 session file(s), $2 index row(s), skipped $3 locked file(s)."],["^供应商同步失败:(.+)$","Provider sync failed: $1"],["^推荐内容加载失败:(.+)$","Failed to load recommendations: $1"],["^脚本市场加载失败:(.+)$","Failed to load script marketplace: $1"],["^安装脚本失败:(.+)$","Failed to install script: $1"],["^脚本启停失败:(.+)$","Failed to toggle script: $1"],["^脚本删除失败:(.+)$","Failed to delete script: $1"],["^打开链接失败:(.+)$","Failed to open link: $1"],["^插件市场修复失败:(.+)$","Plugin marketplace repair failed: $1"],["^官方远端插件缓存修复失败:(.+)$","Official remote plugin cache repair failed: $1"],["^检查更新失败:(.+)$","Failed to check for updates: $1"],["^安装更新失败:(.+)$","Failed to install update: $1"],["^安装 watcher 失败:(.+)$","Failed to install watcher: $1"],["^移除 watcher 失败:(.+)$","Failed to remove watcher: $1"],["^启用 watcher 失败:(.+)$","Failed to enable watcher: $1"],["^禁用 watcher 失败:(.+)$","Failed to disable watcher: $1"],["^读取日志失败:(.+)$","Failed to read logs: $1"],["^重置设置失败:(.+)$","Failed to reset settings: $1"],["^重置图片覆盖层失败:(.+)$","Failed to reset image overlay: $1"],["^读取配置文件失败:(.+)$","Failed to read config file: $1"],["^删除环境变量失败:(.+)$","Failed to delete environment variables: $1"],["^保存配置文件失败:(.+)$","Failed to save config file: $1"],["^供应商切换失败:(.+)$","Provider switch failed: $1"],["^写入诊断日志失败:(.+)$","Failed to write diagnostics log: $1"],["^回填当前供应商配置失败:(.+)$","Failed to backfill current provider config: $1"],["^读取工具与插件列表失败:(.+)$","Failed to read tools & plugins list: $1"],["^读取 live 工具与插件失败:(.+)$","Failed to read live tools & plugins: $1"],["^保存工具与插件失败:(.+)$","Failed to save tools & plugins: $1"],["^读取 live config.toml 失败:(.+)$","Failed to read live config.toml: $1"],["^同步 live 工具与插件失败:(.+)$","Failed to sync live tools & plugins: $1"],["^创建 Codex 配置目录失败:(.+)$","Failed to create Codex config directory: $1"],["^写入 live config.toml 失败:(.+)$","Failed to write live config.toml: $1"],["^读取同步后的 live 工具与插件失败:(.+)$","Failed to read live tools & plugins after sync: $1"],["^删除工具与插件失败:(.+)$","Failed to delete tools & plugins: $1"],["^提取通用配置失败:(.+)$","Failed to extract common config: $1"],["^已向「(.+?)」用模型「(.+?)」发送 hi,HTTP (\\d+)。(.*)$","Sent hi to \"$1\" using model \"$2\", HTTP $3.$4"],["^测试「(.+?)」失败:(.+)$","Test \"$1\" failed: $2"],["^已从「(.+?)」获取 (\\d+) 个模型。$","Fetched $2 model(s) from \"$1\"."],["^从「(.+?)」获取模型失败:(.+)$","Failed to fetch models from \"$1\": $2"],["^切换完整中转配置失败:(.+)$","Failed to switch full relay config: $1"],["^写入中转配置失败:(.+)$","Failed to write relay config: $1"],["^写入聚合供应商配置失败:(.+)$","Failed to write aggregate provider config: $1"],["^切换纯 API 配置失败:(.+)$","Failed to switch to pure API config: $1"],["^写入纯 API 模式失败:(.+)$","Failed to write pure API mode: $1"],["^清除中转配置失败:(.+)$","Failed to clear relay config: $1"],["^未知配置文件类型:(.+)$","Unknown config file type: $1"],["^启动系统浏览器失败:(.+)$","Failed to launch system browser: $1"],["^诊断报告序列化失败:(.+)$","Failed to serialize diagnostics report: $1"],["^响应:(.+)$","Response: $1"]]}
\ No newline at end of file
diff --git a/tools/i18n-vi-cache.json b/tools/i18n-vi-cache.json
new file mode 100644
index 000000000..1dc2f0dfe
--- /dev/null
+++ b/tools/i18n-vi-cache.json
@@ -0,0 +1,774 @@
+{
+"Expands plugin marketplace requests in API Key mode to show the full plugin list. Usually unnecessary in official/mixed mode.": "Mở rộng các yêu cầu về thị trường plugin trong chế độ Khóa API để hiển thị danh sách plugin đầy đủ. Thường không cần thiết ở chế độ chính thức/hỗn hợp.",
+"API Key environment variable": "Biến môi trường khóa API",
+"Chat Completions to Responses": "Hoàn thành trò chuyện để phản hồi",
+"Codex launch arguments": "Đối số khởi chạy Codex",
+"Codex tools & plugins": "Công cụ và plugin Codex",
+"Codex app": "ứng dụng Codex",
+"Codex app path": "Đường dẫn ứng dụng Codex",
+"Codex stopped unexpectedly": "Codex dừng đột ngột",
+"Codex version": "Phiên bản Codex",
+"Codex goals": "Mục tiêu Codex",
+"The official Codex++ relay, built for stable access and good value, supporting GPT-5.5, GPT-5.4, Claude Opus 4.8, Claude Opus 4.7, gpt-image-2 and other models plus image capabilities.": "Rơle Codex++ chính thức, được thiết kế để truy cập ổn định và có giá trị tốt, hỗ trợ GPT-5.5, GPT-5.4, Claude Opus 4.8, Claude Opus 4.7, gpt-image-2 và các mẫu khác cùng với khả năng hình ảnh.",
+"Codex++ import": "Nhập Codex++",
+"Codex++ version": "Phiên bản Codex++",
+"Codex enhancements": "Cải tiến Codex",
+"Codex enhancement mode": "Chế độ nâng cao Codex",
+"Debug port": "Cổng gỡ lỗi",
+"Fast button": "Nút nhanh",
+"GitHub Release update": "Cập nhật phát hành GitHub",
+"GitHub Release check": "Kiểm tra phát hành GitHub",
+"Helper port": "Cổng trợ giúp",
+"MCP, Skills and Plugins are managed independently as global config and merged in whenever you switch providers.": "MCP, Kỹ năng và Plugin được quản lý độc lập dưới dạng cấu hình chung và được hợp nhất bất cứ khi nào bạn chuyển đổi nhà cung cấp.",
+"Markdown export": "Xuất khẩu giảm giá",
+"Provider sync target": "Mục tiêu đồng bộ hóa nhà cung cấp",
+"Stepwise direct send": "Gửi trực tiếp từng bước",
+"Generate next-step suggestions from the current conversation using a separate API configuration.": "Tạo đề xuất bước tiếp theo từ cuộc trò chuyện hiện tại bằng cách sử dụng cấu hình API riêng.",
+"Plugins and models": "Plugin và mô hình",
+"Manage enhancements for the plugin marketplace, model list and service tier.": "Quản lý các cải tiến cho thị trường plugin, danh sách mô hình và cấp dịch vụ.",
+"Conversation and input": "Cuộc trò chuyện và đầu vào",
+"Adjust session management, input behavior and conversation reading experience.": "Điều chỉnh quản lý phiên, hành vi đầu vào và trải nghiệm đọc hội thoại.",
+"Interface and startup": "Giao diện và khởi động",
+"Control language, startup speed and Codex native UI adjustments.": "Kiểm soát ngôn ngữ, tốc độ khởi động và điều chỉnh giao diện người dùng gốc Codex.",
+"Remote projects": "Dự án từ xa",
+"Connect Zed Remote and upstream worktree helper capabilities.": "Kết nối Zed Remote và các khả năng trợ giúp của cây công việc ngược dòng.",
+"Max suggestions": "Đề xuất tối đa",
+"Max input characters": "Ký tự đầu vào tối đa",
+"Max output tokens": "Mã thông báo đầu ra tối đa",
+"Test connection": "Kiểm tra kết nối",
+"Timeout milliseconds": "Hết thời gian tính bằng mili giây",
+"Connection": "Sự liên quan",
+"Advanced parameters": "Thông số nâng cao",
+"TOML config body": "Nội dung cấu hình TOML",
+"Watcher action": "Hành động của người theo dõi",
+"Watcher status": "Trạng thái người theo dõi",
+"The watcher keeps Codex++ in control": "Người theo dõi giữ quyền kiểm soát Codex++",
+"Watcher auto-takeover": "Watcher tự động tiếp quản",
+"Zed remote open": "Zed mở remote",
+"Zed remote projects": "Dự án từ xa của Zed",
+"Zed project history": "Lịch sử dự án Zed",
+"Default Zed open strategy": "Chiến lược mở Zed mặc định",
+"Zed default behavior": "Hành vi mặc định của Zed",
+"cc-switch import": "nhập cc-switch",
+"config.toml preview": "xem trước config.toml",
+"provider not recorded": "nhà cung cấp không được ghi lại",
+"ssh:// URL copied.": "ssh:// URL đã được sao chép.",
+", ": null,
+"”": null,
+"The previous switch hasn't finished yet. Please try again shortly.": "Việc chuyển đổi trước đó vẫn chưa kết thúc. Vui lòng thử lại trong thời gian ngắn.",
+"Context size": "Kích thước ngữ cảnh",
+"Context window": "Cửa sổ ngữ cảnh",
+"Last repair result": "Kết quả sửa chữa cuối cùng",
+"Last update result": "Kết quả cập nhật lần cuối",
+"Upstream protocol": "Giao thức ngược dòng",
+"Download and run installer": "Tải xuống và chạy trình cài đặt",
+"Does not write API files": "Không ghi tệp API",
+"Uses the same remote ad source as the in-Codex plugin menu": "Sử dụng nguồn quảng cáo từ xa giống như menu plugin trong Codex",
+"": "",
+" session(s)": "(các) phiên",
+"China official": "quan chức trung quốc",
+"Homepage": "Trang chủ",
+"Theme and launch arguments": "Chủ đề và khởi động các đối số",
+"Loaded from the static GitHub manifest": "Được tải từ bảng kê khai GitHub tĩnh",
+"Keeps only plain text when pasting rich text (e.g. from Word) into the Codex composer, avoiding it being treated as an image/file attachment. Requires restarting Codex.": "Chỉ giữ lại văn bản thuần túy khi dán văn bản có định dạng (ví dụ: từ Word) vào trình soạn thảo Codex, tránh bị coi là văn bản đính kèm hình ảnh/tệp. Yêu cầu khởi động lại Codex.",
+"Fetch from upstream": "Tìm nạp từ thượng nguồn",
+"Create a Git worktree from the latest upstream branch.": "Tạo cây công việc Git từ nhánh ngược dòng mới nhất.",
+"Pull models from environment variables and config.toml's /v1/models and add them to the model list.": "Kéo các mô hình từ các biến môi trường và /v1/models của config.toml rồi thêm chúng vào danh sách mô hình.",
+"Import from third party": "Nhập khẩu từ bên thứ ba",
+"Create from a preset template": "Tạo từ mẫu đặt trước",
+"Session": "Phiên họp",
+"Session ID badge": "Huy hiệu ID phiên",
+"Session deletion": "Xóa phiên",
+"UI capabilities like session deletion, export, project move and user scripts": "Các khả năng của giao diện người dùng như xóa phiên, xuất, di chuyển dự án và tập lệnh người dùng",
+"Session deletion, export, project move and script capabilities": "Khả năng xóa phiên, xuất, di chuyển dự án và tập lệnh",
+"Total sessions": "Tổng số phiên",
+"Session management": "Quản lý phiên",
+"Session project move": "Phiên di chuyển dự án",
+"Use": "Sử dụng",
+"In use": "Đang sử dụng",
+"e.g. C:\\Program Files\\WindowsApps\\OpenAI.Codex...\\app": "ví dụ. C:\\Tệp chương trình\\WindowsApps\\OpenAI.Codex...\\app",
+"e.g. context7": "ví dụ. bối cảnh7",
+"e.g. deepseek-v4-pro": "ví dụ. deepseek-v4-pro",
+"Codex++ Manager": "Trình quản lý Codex++",
+"Xiaomi MiMo": "Xiaomi MiMo",
+"Baidu Qianfan Coding Plan": "Kế hoạch mã hóa Baidu Qianfan",
+"Volcengine Ark": "Hòm động cơ Volc",
+"e.g. gpt-5.4-mini": "ví dụ. gpt-5.4-mini",
+"e.g. Primary aggregate pool": "ví dụ. Nhóm tổng hợp chính",
+"P": "P",
+"Provider": "nhà cung cấp",
+"Provider switch": "Chuyển đổi nhà cung cấp",
+"Provider switching unavailable": "Chuyển đổi nhà cung cấp không có sẵn",
+"Switching provider": "Chuyển đổi nhà cung cấp",
+"Provider list": "Danh sách nhà cung cấp",
+"Provider test": "Kiểm tra nhà cung cấp",
+"Provider test model": "Mô hình thử nghiệm nhà cung cấp",
+"Provider configuration": "Cấu hình nhà cung cấp",
+"Provider configuration may be incorrect": "Cấu hình nhà cung cấp có thể không chính xác",
+"Provider configuration disabled": "Đã tắt cấu hình nhà cung cấp",
+"The provider configuration master switch is off": "Công tắc chính cấu hình nhà cung cấp đang tắt",
+"The provider configuration master switch is off; changes are only saved, not written to Codex live files": "Công tắc chính cấu hình nhà cung cấp bị tắt; các thay đổi chỉ được lưu, không được ghi vào tệp trực tiếp Codex",
+"Provider preset list": "Danh sách đặt trước của nhà cung cấp",
+"Save": "Cứu",
+"Save as default path": "Lưu làm đường dẫn mặc định",
+"Saved to Codex++ state, does not modify Zed settings.": "Đã lưu vào trạng thái Codex++, không sửa đổi cài đặt Zed.",
+"Save enhancement settings": "Lưu cài đặt nâng cao",
+"Save entry": "Lưu mục nhập",
+"Saved app path": "Đường dẫn ứng dụng đã lưu",
+"Save strategy": "Lưu chiến lược",
+"Save auto-repair settings": "Lưu cài đặt tự động sửa chữa",
+"Save settings": "Lưu cài đặt",
+"Saved path": "Đường dẫn đã lưu",
+"Repair entrypoints": "Sửa chữa điểm vào",
+"Repair shortcuts": "Sửa chữa phím tắt",
+"Repair plugin marketplace": "Thị trường plugin sửa chữa",
+"Health check": "Kiểm tra sức khỏe",
+"Add at least 1 API provider with a Base URL / Key before creating an aggregate provider.": "Thêm ít nhất 1 nhà cung cấp API có URL/Khóa cơ sở trước khi tạo nhà cung cấp tổng hợp.",
+"Portable or unpacked builds only need to be selected once; silent launch reuses it afterwards": "Các bản dựng di động hoặc đã giải nén chỉ cần được chọn một lần; khởi động im lặng sẽ tái sử dụng nó sau đó",
+"Entrypoint uninstall": "Gỡ cài đặt điểm đầu vào",
+"Entrypoint install": "Cài đặt điểm đầu vào",
+"Entrypoint install, repair, watcher and manual launch": "Cài đặt điểm truy cập, sửa chữa, theo dõi và khởi chạy thủ công",
+"Entrypoint management": "Quản lý điểm vào",
+"Select all in current list": "Chọn tất cả trong danh sách hiện tại",
+"About": "Về",
+"About Codex++": "Giới thiệu về Codex++",
+"Off": "Tắt",
+"When off, disables deletion, export, project move, plugin-related and menu placement enhancements.": "Khi tắt, nó sẽ vô hiệu hóa tính năng xóa, xuất, di chuyển dự án, các cải tiến liên quan đến plugin và vị trí menu.",
+"When off, this tool won't write Codex's config.toml / auth.json on manual switches; it never auto-modifies these files when launching Codex.": "Khi tắt, công cụ này sẽ không ghi config.toml / auth.json của Codex trên các công tắc thủ công; nó không bao giờ tự động sửa đổi các tệp này khi khởi chạy Codex.",
+"Compatible enhancement": "Cải tiến tương thích",
+"Content comes from BigPizzaV3/Ad-List, split into sponsor recommendations and regular recommendations.": "Nội dung đến từ BigPizzaV3/Ad-List, được chia thành đề xuất của nhà tài trợ và đề xuất thông thường.",
+"Built-in": "Tích hợp sẵn",
+"Built-in, manual and marketplace-installed scripts; enable, disable or delete user scripts here": "Các tập lệnh tích hợp, thủ công và được cài đặt trên thị trường; bật, tắt hoặc xóa tập lệnh người dùng tại đây",
+"Built-in and user-defined script inventory": "Khoảng không quảng cáo tập lệnh tích hợp và do người dùng xác định",
+"Restore the last scroll position when switching threads.": "Khôi phục vị trí cuộn cuối cùng khi chuyển chủ đề.",
+"Switching": "Chuyển đổi",
+"Toggle theme": "Chuyển đổi chủ đề",
+"Switching to this provider writes ~/.codex/auth.json": "Chuyển sang nhà cung cấp này ghi ~/.codex/auth.json",
+"Preview of what gets written when switching to this provider; context toggles are reflected immediately": "Xem trước nội dung được viết khi chuyển sang nhà cung cấp này; chuyển đổi bối cảnh được phản ánh ngay lập tức",
+"Switch to Chinese": "Chuyển sang tiếng Trung",
+"Switch to Vietnamese": "Chuyển sang tiếng Việt",
+"Switch to English": "Chuyển sang tiếng Anh",
+"Switch to light": "Chuyển sang ánh sáng",
+"Switch to dark": "Chuyển sang màu tối",
+"Preserve scroll position across threads": "Giữ nguyên vị trí cuộn trên các chủ đề",
+"Automatically sends after clicking a suggestion. When off, it only fills the composer.": "Tự động gửi sau khi nhấp vào gợi ý. Khi tắt, nó chỉ lấp đầy nhà soạn nhạc.",
+"Just launched": "Vừa ra mắt",
+"Delete": "Xóa bỏ",
+"Deletion creates a local backup; if the Codex app is using this session, close the session window first.": "Việc xóa sẽ tạo bản sao lưu cục bộ; nếu ứng dụng Codex đang sử dụng phiên này, trước tiên hãy đóng cửa sổ phiên.",
+"Delete session": "Xóa phiên",
+"Delete provider": "Xóa nhà cung cấp",
+"Delete selected": "Xóa đã chọn",
+"Delete entry": "Xóa mục nhập",
+"Delete model": "Xóa mô hình",
+"Refresh": "Làm cho khỏe lại",
+"Refresh sessions": "Làm mới phiên",
+"Refresh list": "Làm mới danh sách",
+"Refresh marketplace": "Làm mới thị trường",
+"Refresh current page": "Làm mới trang hiện tại",
+"Refresh recommendations": "Làm mới đề xuất",
+"Refresh local": "Làm mới cục bộ",
+"Refresh projects": "Làm mới dự án",
+"Add to current workspace": "Thêm vào không gian làm việc hiện tại",
+"Includes version, paths, settings and platform info": "Bao gồm phiên bản, đường dẫn, cài đặt và thông tin nền tảng",
+"Protocol": "Giao thức",
+"Uninstall entrypoints": "Gỡ cài đặt điểm vào",
+"Remove Codex++ managed data on uninstall": "Xóa dữ liệu được quản lý Codex++ khi gỡ cài đặt",
+"Historical session repair": "Sửa chữa phiên lịch sử",
+"Historical session repair failed. Check the error message and retry.": "Sửa chữa phiên lịch sử không thành công. Kiểm tra thông báo lỗi và thử lại.",
+"Historical session repair progress": "Tiến trình sửa chữa phiên lịch sử",
+"Compaction context size": "Kích thước bối cảnh nén",
+"Native menu bar placement": "Vị trí thanh menu gốc",
+"Native menu localization": "Bản địa hóa menu gốc",
+"Report an issue": "Báo cáo sự cố",
+"Discovered": "Đã phát hiện",
+"Send a 'hi' test": "Gửi bài kiểm tra 'xin chào'",
+"Cancel": "Hủy bỏ",
+"Keeps only cross-provider config that isn't MCP/Skills/Plugins; tools and plugins are managed on a separate page.": "Chỉ giữ cấu hình của nhiều nhà cung cấp không phải là MCP/Kỹ năng/Plugins; các công cụ và plugin được quản lý trên một trang riêng.",
+"Fill in only the content under the header, for example:\ncommand = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]": "Chỉ điền nội dung dưới tiêu đề, ví dụ:\nlệnh = \"npx\"\nargs = [\"-y\", \"@upstash/context7-mcp\"]",
+"Only API providers with a Base URL / Key can be selected; aggregate providers can't be members.": "Chỉ có thể chọn nhà cung cấp API có URL / Khóa cơ sở; nhà cung cấp tổng hợp không thể là thành viên.",
+"Update available": "Đã có bản cập nhật",
+"Keeps one member per conversation; different conversations are assigned in turn.": "Giữ một thành viên cho mỗi cuộc trò chuyện; các cuộc trò chuyện khác nhau được chỉ định lần lượt.",
+"Sync Zed settings": "Đồng bộ cài đặt Zed",
+"Sync target": "Mục tiêu đồng bộ hóa",
+"Name": "Tên",
+"Appended after the default CDP arguments when launching the Codex app. Leave empty to keep default launch behavior.": "Được thêm vào sau các đối số CDP mặc định khi khởi chạy ứng dụng Codex. Để trống để giữ hành vi khởi chạy mặc định.",
+"Launch Codex++": "Khởi chạy Codex++",
+"Launch task": "Khởi động nhiệm vụ",
+"Auto-repair historical sessions before launch": "Tự động sửa chữa các phiên lịch sử trước khi ra mắt",
+"Localizes the Codex native menu via the local main-process debug port at launch; doesn't modify the install package. Requires restarting Codex.": "Bản địa hóa menu gốc Codex thông qua cổng gỡ lỗi quy trình chính cục bộ khi khởi chạy; không sửa đổi gói cài đặt. Yêu cầu khởi động lại Codex.",
+"Enable": "Cho phép",
+"Enable Codex image overlay": "Bật lớp phủ hình ảnh Codex",
+"Enable Codex enhancements": "Kích hoạt các cải tiến của Codex",
+"Enable Windows Computer Use Guard": "Kích hoạt tính năng bảo vệ sử dụng máy tính Windows",
+"Enable provider configuration switching": "Cho phép chuyển đổi cấu hình nhà cung cấp",
+"Enable this entry": "Kích hoạt mục này",
+"Enable goals feature": "Kích hoạt tính năng mục tiêu",
+"Image": "Hình ảnh",
+"Image overlay": "Lớp phủ hình ảnh",
+"Show a delete button on hover in the session list, with undo support.": "Hiển thị nút xóa khi di chuột trong danh sách phiên, có hỗ trợ hoàn tác.",
+"Show an export button in the session list to export timestamped Markdown.": "Hiển thị nút xuất trong danh sách phiên để xuất Markdown có dấu thời gian.",
+"Shows a draggable follow-up suggestion overlay in the Codex page. Suggestions are generated by a separate Stepwise API.": "Hiển thị lớp phủ đề xuất tiếp theo có thể kéo được trong trang Codex. Các đề xuất được tạo bởi API Stepwise riêng biệt.",
+"Show a short ID and UUIDv7 creation time before session titles in the sidebar to help locate past sessions.": "Hiển thị thời gian tạo ID và UUIDv7 ngắn trước tiêu đề phiên trong thanh bên để giúp xác định các phiên trước đây.",
+"Basic settings": "Cài đặt cơ bản",
+"Enter the relay service Base URL": "Nhập URL cơ sở của dịch vụ chuyển tiếp",
+"Copy": "Sao chép",
+"Copy ssh:// URL": "Sao chép URL ssh://",
+"Copy failed": "Sao chép không thành công",
+"Copy report": "Sao chép báo cáo",
+"Reuse window": "Cửa sổ tái sử dụng",
+"Multi-select": "Chọn nhiều lần",
+"Failed": "Thất bại",
+"Failover": "Chuyển đổi dự phòng",
+"Failover preserves member order, preferring the first available provider.": "Chuyển đổi dự phòng duy trì trật tự thành viên, ưu tiên nhà cung cấp sẵn có đầu tiên.",
+"If you use official mode or official mixed-API mode, you usually don't need plugin marketplace unlock.": "Nếu bạn sử dụng chế độ chính thức hoặc chế độ API hỗn hợp chính thức, bạn thường không cần mở khóa thị trường plugin.",
+"Install": "Cài đặt",
+"Install watcher": "cài đặt trình theo dõi",
+"Install entrypoints": "Cài đặt điểm vào",
+"Installer update failed. Check the error message and retry.": "Cập nhật trình cài đặt không thành công. Kiểm tra thông báo lỗi và thử lại.",
+"Installer update progress": "Tiến trình cập nhật trình cài đặt",
+"Install & maintenance": "Cài đặt & bảo trì",
+"Full enhancement": "Nâng cao đầy đủ",
+"Official": "Chính thức",
+"Official relay": "Tiếp sức chính thức",
+"Official mixed-in API Key": "Khóa API hỗn hợp chính thức",
+"Official mixed API should not store OPENAI_API_KEY in auth.json. Clear this provider's auth.json before switching.": "API hỗn hợp chính thức không được lưu trữ OPENAI_API_KEY trong auth.json. Xóa auth.json của nhà cung cấp này trước khi chuyển đổi.",
+"Official login": "Đăng nhập chính thức",
+"Official login mode": "Chế độ đăng nhập chính thức",
+"Centered conversation width": "Chiều rộng cuộc trò chuyện được căn giữa",
+"Import Codex++ provider": "Nhập nhà cung cấp Codex++",
+"Not refreshed yet": "Chưa được làm mới",
+"Recommendations not loaded yet": "Đề xuất chưa được tải",
+"Codex app path not checked yet.": "Đường dẫn ứng dụng Codex chưa được kiểm tra.",
+"GitHub Release not checked yet; updating downloads and launches the installer.": "Bản phát hành GitHub chưa được kiểm tra; cập nhật các bản tải xuống và khởi chạy trình cài đặt.",
+"No diagnostic report generated yet.": "Chưa có báo cáo chẩn đoán nào được tạo.",
+"Installer update has not run yet.": "Bản cập nhật trình cài đặt chưa chạy.",
+"Historical session repair hasn't run yet.": "Sửa chữa phiên lịch sử chưa chạy.",
+"Plugin marketplace repair hasn't run yet.": "Sửa chữa thị trường plugin chưa chạy.",
+"Official remote plugin cache has not been checked yet.": "Bộ đệm plugin từ xa chính thức chưa được kiểm tra.",
+"Checking embedded official remote plugin cache…": "Đang kiểm tra bộ nhớ đệm của plugin từ xa chính thức được nhúng…",
+"Extracting embedded remote plugin snapshot…": "Đang trích xuất ảnh chụp nhanh plugin từ xa được nhúng…",
+"Registering official remote plugin marketplace…": "Đăng ký thị trường plugin từ xa chính thức…",
+"Refreshing official remote plugin cache status…": "Đang làm mới trạng thái bộ đệm của plugin từ xa chính thức…",
+"Processing…": "Xử lý…",
+"Tools & plugins": "Công cụ & plugin",
+"Switched back to official login; Codex enhancements set to compatible.": "Chuyển về đăng nhập chính thức; Các cải tiến của Codex được đặt thành tương thích.",
+"Switched to pure API; Codex enhancements set to full.": "Đã chuyển sang API thuần túy; Các cải tiến của Codex được đặt ở mức đầy đủ.",
+"Switched to aggregate provider; real conversations rotate members per the chosen strategy.": "Chuyển sang nhà cung cấp tổng hợp; các cuộc trò chuyện thực sự xoay vòng thành viên theo chiến lược đã chọn.",
+"Refreshed Codex app, entrypoint and watcher status.": "Ứng dụng Codex, điểm truy cập và trạng thái người theo dõi được làm mới.",
+"Accepted": "Đã chấp nhận",
+"Installed": "Đã cài đặt",
+"Archived": "Đã lưu trữ",
+"Opened aggregate provider details; first add or complete the Base URL / Key of at least 1 regular API provider, then select it as a member.": "Đã mở chi tiết nhà cung cấp tổng hợp; trước tiên hãy thêm hoặc hoàn thành URL cơ sở/Khóa của ít nhất 1 nhà cung cấp API thông thường, sau đó chọn nhà cung cấp đó làm thành viên.",
+"Found": "Thành lập",
+"Using official login for this provider with the API Key mixed in; Codex enhancements set to compatible.": "Sử dụng thông tin đăng nhập chính thức cho nhà cung cấp này có kèm theo Khóa API; Các cải tiến của Codex được đặt thành tương thích.",
+"Switched back to official login for this provider; Codex enhancements set to compatible.": "Chuyển về đăng nhập chính thức cho nhà cung cấp này; Các cải tiến của Codex được đặt thành tương thích.",
+"Switched to pure API for this provider; Codex enhancements set to full.": "Đã chuyển sang API thuần túy cho nhà cung cấp này; Các cải tiến của Codex được đặt ở mức đầy đủ.",
+"Detected": "Đã phát hiện",
+"Registered": "Đăng ký",
+"Cached, not registered": "Đã lưu vào bộ nhớ đệm, chưa được đăng ký",
+"Saved path cleared; future launches fall back to auto-detection.": "Đã xóa đường dẫn đã lưu; các lần phóng trong tương lai sẽ quay trở lại chế độ tự động phát hiện.",
+"Logged in": "Đã đăng nhập",
+"Disabled": "Tàn tật",
+"Selected": "Đã chọn",
+"Marketplace status": "trạng thái thị trường",
+"Marketplace scripts": "Tập lệnh Marketplace",
+"Serialized fields": "Các trường được tuần tự hóa",
+"App path saved; future launches reuse it automatically.": "Đã lưu đường dẫn ứng dụng; những lần ra mắt trong tương lai sẽ tự động tái sử dụng nó.",
+"When the app path is empty, the saved path is used; with no saved path, auto-detection is used": "Khi đường dẫn ứng dụng trống, đường dẫn đã lưu sẽ được sử dụng; không có đường dẫn đã lưu, tính năng tự động phát hiện sẽ được sử dụng",
+"App path override": "Ghi đè đường dẫn ứng dụng",
+"On": "TRÊN",
+"When on, tidies up ownership tags of old conversations once before launching Codex through Codex++.": "Khi bật, hãy dọn dẹp các thẻ quyền sở hữu của các cuộc hội thoại cũ một lần trước khi khởi chạy Codex thông qua Codex++.",
+"Force Chinese UI": "Buộc giao diện người dùng Trung Quốc",
+"Forces the Codex app's built-in zh-CN language pack to avoid falling back to English when Statsig/VPN is unreachable. Requires restarting Codex to fully apply.": "Buộc gói ngôn ngữ zh-CN tích hợp của ứng dụng Codex tránh chuyển về tiếng Anh khi không thể truy cập Statsig/VPN. Yêu cầu khởi động lại Codex để áp dụng đầy đủ.",
+"Current": "Hiện hành",
+"current provider": "nhà cung cấp hiện tại",
+"Codex config.toml / auth.json won't be written right now. Turn on the provider configuration master switch before switching.": "Codex config.toml / auth.json sẽ không được viết ngay bây giờ. Bật công tắc chính cấu hình nhà cung cấp trước khi chuyển đổi.",
+"Currently ": "Hiện nay",
+"Currently in compatible enhancement mode; plugin marketplace unlock is not enabled, but other page features still work.": "Hiện đang ở chế độ nâng cao tương thích; tính năng mở khóa thị trường plugin chưa được bật nhưng các tính năng khác của trang vẫn hoạt động.",
+"Current session": "Phiên hiện tại",
+"Currently in use: backfilled from ~/.codex/auth.json when opened; saving stores it as this provider's auth archive": "Hiện đang được sử dụng: được chèn lấp từ ~/.codex/auth.json khi mở; lưu trữ nó dưới dạng kho lưu trữ xác thực của nhà cung cấp này",
+"The current provider's config.toml has no extractable common config.": "config.toml của nhà cung cấp hiện tại không có cấu hình chung có thể trích xuất được.",
+"Preview of what the current provider writes after switching; context toggles are reflected immediately": "Xem trước những gì nhà cung cấp hiện tại viết sau khi chuyển đổi; chuyển đổi bối cảnh được phản ánh ngay lập tức",
+"The current provider doesn't have a complete config.toml / API Key archive yet.": "Nhà cung cấp hiện tại chưa có kho lưu trữ config.toml/API Key hoàn chỉnh.",
+"There are currently ": "Hiện tại có",
+"Not logged into an official account, and no mixed-in API Base URL / Key configured.": "Chưa đăng nhập vào tài khoản chính thức và không có URL/Khóa cơ sở API hỗn hợp được định cấu hình.",
+"Not logged into an official account; after switching to official login mode you still need to log in via Codex/ChatGPT first.": "Chưa đăng nhập vào tài khoản chính thức; sau khi chuyển sang chế độ đăng nhập chính thức bạn vẫn cần đăng nhập qua Codex/ChatGPT trước.",
+"Not logged into an official account; official login with a mixed-in API Key requires logging into an official account first.": "Chưa đăng nhập vào tài khoản chính thức; đăng nhập chính thức bằng Khóa API hỗn hợp yêu cầu đăng nhập vào tài khoản chính thức trước.",
+"Currently in use": "Hiện đang được sử dụng",
+"Currently detected": "Hiện đã phát hiện",
+"The mixed-in API Base URL / Key hasn't been filled in yet.": "URL/Khóa cơ sở API hỗn hợp chưa được điền vào.",
+"Current process": "Quá trình hiện tại",
+"Currently configured provider": "Nhà cung cấp được cấu hình hiện tại",
+"Shortcut repair": "Sửa chữa lối tắt",
+"Shortcuts are written to the system's actual desktop location, not a hardcoded desktop path": "Các phím tắt được ghi vào vị trí màn hình thực tế của hệ thống, không phải đường dẫn màn hình được mã hóa cứng",
+"Fast startup": "Khởi động nhanh",
+"Total weight": "Tổng trọng lượng",
+"Member providers": "Nhà cung cấp thành viên",
+"Member count": "Số thành viên",
+" or ": "hoặc",
+"Manual": "Thủ công",
+"Manual launch": "Khởi chạy thủ công",
+"Open": "Mở",
+"Open JOJO Code": "Mở mã JOJO",
+"Open About": "Mở Giới thiệu",
+"Open link": "Mở liên kết",
+"Open project homepage": "Mở trang chủ dự án",
+"entry": "lối vào",
+"Bulk delete sessions": "Xóa phiên hàng loạt",
+"Insert the Codex++ menu into Codex's top native menu bar.": "Chèn menu Codex++ vào thanh menu gốc trên cùng của Codex.",
+"Constrain the main conversation and input box to a fixed max width, good for large-screen reading.": "Giới hạn cuộc trò chuyện chính và hộp nhập liệu ở độ rộng tối đa cố định, phù hợp để đọc trên màn hình lớn.",
+"Move a session to a regular conversation or another local project.": "Chuyển phiên sang cuộc trò chuyện thông thường hoặc dự án địa phương khác.",
+"Submit": "Nộp",
+"Drag to reorder": "Kéo để sắp xếp lại",
+"Per-conversation round-robin": "Vòng tròn cho mỗi cuộc trò chuyện",
+"Per-conversation round-robin keeps the same conversation on a fixed member where possible, reducing context drift.": "Vòng tròn trên mỗi cuộc trò chuyện sẽ giữ cùng một cuộc trò chuyện với một thành viên cố định nếu có thể, giúp giảm tình trạng lệch ngữ cảnh.",
+"Distribute requests by member weight; higher weight takes on more.": "Phân phối yêu cầu theo trọng lượng thành viên; trọng lượng cao hơn mất nhiều hơn.",
+"Request members in order, switching to the next provider on failure.": "Yêu cầu các thành viên theo thứ tự, chuyển sang nhà cung cấp tiếp theo nếu không thành công.",
+"Sorted by update time, newest first": "Sắp xếp theo thời gian cập nhật, mới nhất xếp trước",
+"Per-request round-robin": "Vòng tròn theo yêu cầu",
+"Per-request round-robin switches members request by request, suited to providers with similar capabilities.": "Theo yêu cầu, chuyển đổi vòng tròn các thành viên theo yêu cầu, phù hợp với các nhà cung cấp có khả năng tương tự.",
+"Access mode": "Chế độ truy cập",
+"Recommendations": "Khuyến nghị",
+"Extract current provider config": "Trích xuất cấu hình nhà cung cấp hiện tại",
+"Plugins": "Plugin",
+"Show full plugin list": "Hiển thị danh sách plugin đầy đủ",
+"Plugin marketplace repair": "Sửa chữa thị trường plugin",
+"Plugin marketplace repair failed. Check the error message and retry.": "Sửa chữa thị trường plugin không thành công. Kiểm tra thông báo lỗi và thử lại.",
+"Plugin marketplace repair progress": "Tiến trình sửa chữa thị trường plugin",
+"Plugin marketplace unlock": "Mở khóa thị trường plugin",
+"Official remote plugin cache": "Bộ đệm plugin từ xa chính thức",
+"Official remote plugin cache progress": "Tiến trình bộ nhớ đệm plugin từ xa chính thức",
+"Official remote plugin cache repair failed. Check the error message and retry.": "Sửa chữa bộ nhớ đệm plugin từ xa chính thức không thành công. Kiểm tra thông báo lỗi và thử lại.",
+"Use the embedded Codex++ snapshot to add remote plugins, so API mode can also show and install the Product Design plugin.": "Sử dụng ảnh chụp nhanh Codex++ được nhúng để thêm plugin từ xa, nhờ đó chế độ API cũng có thể hiển thị và cài đặt plugin Thiết kế Sản phẩm.",
+"Search providers…": "Tìm kiếm nhà cung cấp…",
+"Database": "Cơ sở dữ liệu",
+"Add ": "Thêm vào",
+"A new provider must be saved to the list first": "Nhà cung cấp mới phải được lưu vào danh sách trước",
+"On a new machine without a local plugin marketplace, initialize it into the current CODEX_HOME from openai/plugins.": "Trên máy mới không có thị trường plugin cục bộ, hãy khởi tạo nó thành CODEX_HOME hiện tại từ openai/plugin.",
+"New window": "Cửa sổ mới",
+"Logs refreshed": "Đã làm mới nhật ký",
+"Logs copied.": "Đã sao chép nhật ký.",
+"Time": "Thời gian",
+"Extract and register embedded cache": "Trích xuất và đăng ký bộ nhớ đệm nhúng",
+"Show the service-tier toggle button; Fast only supports gpt-5.4 / gpt-5.5, other models are sent as Standard.": "Hiển thị nút chuyển đổi cấp dịch vụ; Fast chỉ hỗ trợ gpt-5.4 / gpt-5.5, các mẫu khác được gửi dưới dạng Tiêu chuẩn.",
+"Regular recommendations": "Khuyến nghị thường xuyên",
+"None": "Không có",
+"No launch status yet.": "Chưa có trạng thái khởi chạy.",
+"No description.": "Không có mô tả.",
+"No logs.": "Không có nhật ký.",
+"No regular recommendations.": "Không có khuyến nghị thường xuyên.",
+"No status file": "Không có tập tin trạng thái",
+"No sponsor recommendations.": "Không có đề xuất nhà tài trợ.",
+"No projects.": "Không có dự án.",
+"More options": "Nhiều lựa chọn hơn",
+"Update": "Cập nhật",
+"Update install": "Cập nhật cài đặt",
+"Latest version": "Phiên bản mới nhất",
+"Recent launches": "Ra mắt gần đây",
+"Recently opened": "Mới mở gần đây",
+"Recent logs": "Nhật ký gần đây",
+"No importable providers found": "Không tìm thấy nhà cung cấp có thể nhập khẩu nào",
+"No user scripts found.": "Không tìm thấy tập lệnh người dùng.",
+"Untitled session": "Phiên không có tiêu đề",
+"Untitled provider": "Nhà cung cấp không có tiêu đề",
+"Untitled aggregate provider": "Nhà cung cấp tổng hợp không có tiêu đề",
+"Not filled in": "Không điền vào",
+"No URL filled in": "Không có URL nào được điền vào",
+"Not installed": "Chưa được cài đặt",
+"Not implemented": "Chưa được triển khai",
+"Not archived": "Chưa được lưu trữ",
+"Not checked": "Chưa được kiểm tra",
+"Not detected": "Không được phát hiện",
+"Codex app version not detected.": "Phiên bản ứng dụng Codex không được phát hiện.",
+"Cache not found": "Không tìm thấy bộ đệm",
+"Local cache not found. Click the button to extract and register the embedded Codex++ snapshot; no official-account pre-cache is required.": "Không tìm thấy bộ đệm cục bộ. Nhấp vào nút để trích xuất và đăng ký ảnh chụp nhanh Codex++ được nhúng; không yêu cầu bộ nhớ đệm trước của tài khoản chính thức.",
+"Unknown": "Không xác định",
+"Unknown author": "Tác giả không xác định",
+"Unknown source": "Nguồn không xác định",
+"Unknown version": "Phiên bản không xác định",
+"No path recorded": "Không có đường dẫn nào được ghi lại",
+"No project path recorded": "Không có đường dẫn dự án nào được ghi lại",
+"No local sessions read, or the current SQLite session database doesn't exist.": "Không có phiên cục bộ nào được đọc hoặc cơ sở dữ liệu phiên SQLite hiện tại không tồn tại.",
+"Local Codex enhancements, management tools and install package maintenance": "Cải tiến Codex cục bộ, công cụ quản lý và bảo trì gói cài đặt",
+"Local sessions": "Phiên cục bộ",
+"Local overall": "Tổng thể địa phương",
+"Local scripts": "Tập lệnh cục bộ",
+"Weight": "Cân nặng",
+"Weighted round-robin": "Vòng tròn có trọng số",
+"Weighted round-robin reads each member's weight; members with higher weight receive more requests.": "Vòng tròn có trọng số sẽ đọc cân nặng của từng thành viên; thành viên có trọng lượng cao hơn nhận được nhiều yêu cầu hơn.",
+"View, delete and repair Codex local sessions": "Xem, xóa và sửa chữa các phiên cục bộ Codex",
+"Check": "Kiểm tra",
+"Check & repair": "Kiểm tra & sửa chữa",
+"Check entrypoint, Codex app and watcher status": "Kiểm tra điểm vào, ứng dụng Codex và trạng thái người theo dõi",
+"Check configuration, model list and one real request to find why a provider is unavailable.": "Kiểm tra cấu hình, danh sách model và một yêu cầu thực tế để tìm hiểu lý do tại sao không có nhà cung cấp.",
+"Check complete": "Kiểm tra hoàn tất",
+"Check for updates": "Kiểm tra các bản cập nhật",
+"Check issues, launch and quick fixes": "Kiểm tra sự cố, khởi chạy và khắc phục nhanh",
+"Diagnose provider": "Nhà cung cấp chẩn đoán",
+"Detect": "Phát hiện",
+"OPENAI environment variables detected": "Đã phát hiện các biến môi trường OPENAI",
+"A provider config import request from the web was detected; confirming writes it to this machine's Codex++ manager.": "Đã phát hiện yêu cầu nhập cấu hình nhà cung cấp từ web; xác nhận ghi nó vào trình quản lý Codex++ của máy này.",
+"Overview": "Tổng quan",
+"The overview shows only key issues; specific configuration is handled on the relevant pages": "Phần tổng quan chỉ hiển thị các vấn đề chính; cấu hình cụ thể được xử lý trên các trang có liên quan",
+"Overview checked": "Đã kiểm tra tổng quan",
+"Model list": "Danh sách người mẫu",
+"Model name": "Tên mẫu",
+"Model whitelist unlock": "Mở khóa danh sách trắng mô hình",
+"Mode": "Cách thức",
+" mode.": "cách thức.",
+"Downloading installer…": "Đang tải xuống trình cài đặt…",
+"Downloading plugin marketplace snapshot…": "Đang tải xuống ảnh chụp nhanh thị trường plugin…",
+"Repairing…": "Đang sửa chữa…",
+"Repairing historical sessions": "Sửa chữa các phiên lịch sử",
+"Preparing installer download…": "Đang chuẩn bị tải xuống trình cài đặt…",
+"Launching installer…": "Đang khởi chạy trình cài đặt…",
+"Writing Codex config…": "Đang viết cấu hình Codex…",
+"Writing repairs and backups…": "Viết sửa chữa và sao lưu…",
+"Deleting…": "Đang xóa…",
+"Scanning historical sessions and indexes…": "Đang quét các phiên và chỉ mục lịch sử…",
+"Checking session provider tags…": "Đang kiểm tra thẻ nhà cung cấp phiên…",
+"Checking local plugin marketplace…": "Đang kiểm tra thị trường plugin địa phương…",
+"Fetching GitHub Release information…": "Đang tìm nạp thông tin phát hành GitHub…",
+"Extracting and verifying plugin files…": "Đang trích xuất và xác minh các tệp plugin…",
+"Connecting to openai/plugins…": "Đang kết nối với openai/plugin…",
+"OK": "ĐƯỢC RỒI",
+"This upstream is converted to the Responses API via local 127.0.0.1:57321, which requires launching Codex from Codex++.": "Luồng ngược dòng này được chuyển đổi thành API phản hồi thông qua 127.0.0.1:57321 cục bộ, yêu cầu khởi chạy Codex từ Codex++.",
+"This provider keeps official login mode and mixes the current API Key into requests; Codex enhancements stay in compatible mode.": "Nhà cung cấp này giữ chế độ đăng nhập chính thức và trộn Khóa API hiện tại vào các yêu cầu; Các cải tiến của Codex vẫn ở chế độ tương thích.",
+"This provider switches back to official login mode using the official ChatGPT account, without writing an API Key.": "Nhà cung cấp này chuyển về chế độ đăng nhập chính thức bằng tài khoản ChatGPT chính thức mà không cần viết Khóa API.",
+"This provider writes both config.toml and auth.json; the API Key is also injected into the provider bearer token.": "Nhà cung cấp này viết cả config.toml và auth.json; Khóa API cũng được đưa vào mã thông báo mang của nhà cung cấp.",
+"Switches members in order on each request, good for evenly spreading request volume.": "Chuyển đổi thành viên theo thứ tự trên mỗi yêu cầu, tốt cho việc phân bổ đều khối lượng yêu cầu.",
+"One argument per line, e.g. --force_high_performance_gpu. No need to include open or --args.": "Một đối số trên mỗi dòng, ví dụ: --force_high_performance_gpu. Không cần bao gồm open hoặc --args.",
+"One model per line; the context window can be": "Một mô hình trên mỗi dòng; cửa sổ ngữ cảnh có thể",
+"No providers matching “": "Không có nhà cung cấp nào phù hợp với “",
+"Light": "Ánh sáng",
+"Test model": "Mô hình thử nghiệm",
+"Message": "Tin nhắn",
+"Dark": "Tối tăm",
+"Mixed-in API": "API hỗn hợp",
+"Mix in API KEY": "Trộn vào API KEY",
+"Mix in API Key": "Kết hợp khóa API",
+"Add provider": "Thêm nhà cung cấp",
+"Add model": "Thêm mô hình",
+"Add aggregate provider": "Thêm nhà cung cấp tổng hợp",
+"Clear selection": "Xóa lựa chọn",
+"Clear saved path": "Xóa đường dẫn đã lưu",
+"Click Refresh Sessions to read the local database": "Bấm vào Làm mới phiên để đọc cơ sở dữ liệu cục bộ",
+"Click Refresh Marketplace to load remote scripts.": "Nhấp vào Làm mới Marketplace để tải tập lệnh từ xa.",
+"Version info, project links, GitHub Release updates, logs and diagnostics": "Thông tin phiên bản, liên kết dự án, Cập nhật phát hành GitHub, nhật ký và chẩn đoán",
+"Status": "Trạng thái",
+"Manage Codex's MCP, Skills and Plugins independently; they carry over whenever you switch providers.": "Quản lý MCP, Kỹ năng và Plugin của Codex một cách độc lập; họ sẽ chuyển tiếp bất cứ khi nào bạn chuyển đổi nhà cung cấp.",
+"Independently manage MCP, Skills and Plugins": "Quản lý độc lập MCP, Kỹ năng và Plugin",
+"Environment variables": "Biến môi trường",
+"Environment variable detection": "Phát hiện biến môi trường",
+"Environment variable cleanup": "Dọn dẹp biến môi trường",
+"User": "người dùng",
+"User environment": "Môi trường người dùng",
+"UI theme": "chủ đề giao diện người dùng",
+"Leave empty to keep unchanged, e.g. 160000": "Để trống để giữ nguyên, ví dụ: 160000",
+"Leave empty to keep unchanged, e.g. 200000": "Để trống để giữ nguyên, ví dụ: 200000",
+"Leave empty to use the default": "Để trống để sử dụng mặc định",
+"Login status": "Trạng thái đăng nhập",
+"Confirm delete": "Xác nhận xóa",
+"Confirm import": "Xác nhận nhập",
+"Disable": "Vô hiệu hóa",
+"Disable this entry": "Vô hiệu hóa mục này",
+"Remove watcher": "Xóa người theo dõi",
+"Remove from recent": "Xóa khỏi gần đây",
+"Repair historical sessions now": "Sửa chữa các phiên lịch sử ngay bây giờ",
+"Third party": "Bên thứ ba",
+"Strategy": "Chiến lược",
+"Manage API providers, protocols, keys and config files": "Quản lý nhà cung cấp API, giao thức, khóa và tệp cấu hình",
+"Manage Codex SSH projects and add them to a Zed workspace": "Quản lý các dự án Codex SSH và thêm chúng vào không gian làm việc của Zed",
+"Manager entrypoint": "Điểm vào của người quản lý",
+"Management console": "Bảng điều khiển quản lý",
+"Management console entrypoint": "Điểm vào bảng điều khiển quản lý",
+"Type": "Kiểu",
+"Paste fix": "Dán sửa lỗi",
+"Index": "chỉ mục",
+"Pure API": "API thuần túy",
+"Pure API ready: writes both config.toml and auth.json.": "API thuần túy đã sẵn sàng: ghi cả config.toml và auth.json.",
+"Pure API mode": "Chế độ API thuần túy",
+"Pure API config is incomplete: check whether this provider has OPENAI_API_KEY and whether config.toml includes model_provider / provider / base_url.": "Cấu hình API thuần túy chưa đầy đủ: hãy kiểm tra xem nhà cung cấp này có OPENAI_API_KEY hay không và config.toml có bao gồm model_provider/nhà cung cấp/base_url hay không.",
+"Maintain Codex++'s own recent list of remote projects.": "Duy trì danh sách các dự án từ xa gần đây của Codex++.",
+"Edit": "Biên tập",
+"After editing, save the list; the new config is used the next time you switch modes": "Sau khi chỉnh sửa, lưu danh sách; cấu hình mới sẽ được sử dụng vào lần tiếp theo bạn chuyển chế độ",
+"Edit entry": "Chỉnh sửa mục nhập",
+"Missing": "Mất tích",
+"When the Codex++ silent launch shortcut is missing, repair it on the Install & Maintenance page.": "Khi thiếu phím tắt khởi chạy im lặng Codex++, hãy sửa nó trên trang Cài đặt & Bảo trì.",
+"When the manager shortcut is missing, repair it on the Install & Maintenance page.": "Khi thiếu phím tắt trình quản lý, hãy sửa nó trên trang Cài đặt & Bảo trì.",
+"Aggregate": "Tổng hợp",
+"Aggregate/relay": "Tổng hợp / chuyển tiếp",
+"Aggregate provider": "Nhà cung cấp tổng hợp",
+"Aggregate providers rotate members in real conversations; test the member providers instead": "Các nhà cung cấp tổng hợp luân chuyển thành viên trong các cuộc trò chuyện thực tế; thay vào đó hãy kiểm tra các nhà cung cấp thành viên",
+"Aggregate providers only store member and strategy config drawn from existing API providers; once active, requests rotate through the local protocol proxy.": "Các nhà cung cấp tổng hợp chỉ lưu trữ cấu hình chiến lược và thành viên được lấy từ các nhà cung cấp API hiện có; sau khi hoạt động, các yêu cầu sẽ chuyển qua proxy giao thức cục bộ.",
+"An aggregate provider needs at least 1 selected API provider with a Base URL / Key filled in.": "Một nhà cung cấp tổng hợp cần có ít nhất 1 nhà cung cấp API được chọn có điền URL/Khóa cơ sở.",
+"Aggregate strategy": "Chiến lược tổng hợp",
+"Aggregate config only references existing providers; it doesn't copy keys or config files": "Cấu hình tổng hợp chỉ tham chiếu các nhà cung cấp hiện có; nó không sao chép khóa hoặc tập tin cấu hình",
+"Script marketplace": "Chợ kịch bản",
+"Auto-takeover": "Tự động tiếp quản",
+"Overlay image": "Hình ảnh lớp phủ",
+"Background fit mode": "Chế độ phù hợp với nền",
+"Fill": "Đổ đầy",
+"Fit": "Phù hợp",
+"Stretch": "Kéo dài",
+"Tile": "Ngói",
+"Center": "Trung tâm",
+"Record recently opened": "Bản ghi được mở gần đây",
+"Set as current": "Đặt như hiện tại",
+"Settings": "Cài đặt",
+"Settings saved": "Đã lưu cài đặt",
+"Settings loaded": "Đã tải cài đặt",
+"Settings reset": "Đặt lại cài đặt",
+"Diagnostics generated": "Đã tạo chẩn đoán",
+"Diagnostic report": "Báo cáo chẩn đoán",
+"Diagnostic report copied.": "Đã sao chép báo cáo chẩn đoán.",
+"Click to open the diagnostic dialog and check the provider step by step.": "Nhấp để mở hộp thoại chẩn đoán và kiểm tra nhà cung cấp từng bước.",
+"Diagnosing provider, please wait.": "Nhà cung cấp dịch vụ chẩn đoán, vui lòng đợi.",
+"Diagnosis complete.": "Chẩn đoán hoàn tất.",
+"Diagnosing": "Chẩn đoán",
+"Error": "Lỗi",
+"Complete": "Hoàn thành",
+"Configuration integrity": "Tính toàn vẹn của cấu hình",
+"Waiting to check Base URL / API Key.": "Đang chờ kiểm tra URL cơ sở/Khóa API.",
+"Waiting to check /v1/models.": "Đang chờ kiểm tra /v1/models.",
+"Real request": "Yêu cầu thực sự",
+"Waiting to send one test request.": "Đang chờ gửi một yêu cầu kiểm tra.",
+"Recommendation": "Sự giới thiệu",
+"Waiting to generate a recommendation.": "Đang chờ để tạo đề xuất.",
+"Checking configuration integrity…": "Đang kiểm tra tính toàn vẹn của cấu hình…",
+"This step was not run.": "Bước này không được chạy.",
+"Fill in or select an app path first.": "Trước tiên hãy điền hoặc chọn đường dẫn ứng dụng.",
+"Select the sessions to delete first.": "Chọn các phiên để xóa đầu tiên.",
+"Reads Codex's local SQLite session database; deletes database records and the corresponding rollout files": "Đọc cơ sở dữ liệu phiên SQLite cục bộ của Codex; xóa các bản ghi cơ sở dữ liệu và các tập tin triển khai tương ứng",
+"Failed to read cc-switch providers.": "Không đọc được nhà cung cấp cc-switch.",
+"Reading ~/.cc-switch/cc-switch.db": "Đọc ~/.cc-switch/cc-switch.db",
+"Call failed": "Cuộc gọi không thành công",
+"Asset": "Tài sản",
+"Sponsor recommendations": "Khuyến nghị của nhà tài trợ",
+"Sponsor and regular recommendations": "Nhà tài trợ và khuyến nghị thường xuyên",
+"Enter the relay service API Key": "Nhập Khóa API dịch vụ chuyển tiếp",
+"Running": "Đang chạy",
+"Back to list": "Quay lại danh sách",
+"These variables may override the config.toml / auth.json written by the current provider; CODEX_HOME won't be cleaned up.": "Các biến này có thể ghi đè config.toml/auth.json do nhà cung cấp hiện tại viết; CODEX_HOME sẽ không được dọn sạch.",
+"Automatically keep expanding 'More' on the plugins page to show the full plugin list at once.": "Tự động tiếp tục mở rộng 'Thêm' trên trang plugin để hiển thị danh sách plugin đầy đủ cùng một lúc.",
+"Progress": "Tiến triển",
+"Remote SSH file references can be opened directly with Zed Remote Development.": "Các tham chiếu tệp SSH từ xa có thể được mở trực tiếp bằng Zed Remote Development.",
+"Remote scripts": "Tập lệnh từ xa",
+"Suited to official login or official mixed-in API Key; keeps session deletion, export, project move and user scripts, while disabling plugin-marketplace-related enhancements.": "Phù hợp với đăng nhập chính thức hoặc Khóa API hỗn hợp chính thức; tiếp tục xóa phiên, xuất, di chuyển dự án và tập lệnh người dùng, đồng thời vô hiệu hóa các cải tiến liên quan đến thị trường plugin.",
+"Suited to pure API; enables all page capabilities including plugin marketplace, session deletion/export and project move.": "Phù hợp với API thuần túy; cho phép tất cả các khả năng của trang bao gồm thị trường plugin, xóa/xuất phiên và di chuyển dự án.",
+"Select Codex app directory": "Chọn thư mục ứng dụng Codex",
+"Select Codex.exe": "Chọn Codex.exe",
+"Select Codex.exe or Codex.app": "Chọn Codex.exe hoặc Codex.app",
+"Select Codex.exe, Codex.app, the app directory or the unpacked directory": "Chọn Codex.exe, Codex.app, thư mục ứng dụng hoặc thư mục đã giải nén",
+"Select png / jpg / webp / gif / bmp": "Chọn png/jpg/webp/gif/bmp",
+"Select session": "Chọn phiên",
+"Select image": "Chọn hình ảnh",
+"Select existing providers as members; saving writes them to the settings payload": "Chọn các nhà cung cấp hiện có làm thành viên; lưu ghi chúng vào tải trọng cài đặt",
+"Select app directory": "Chọn thư mục ứng dụng",
+"Select overlay image": "Chọn hình ảnh lớp phủ",
+"Common config file": "Tệp cấu hình chung",
+"Config": "Cấu hình",
+"Config file": "Tập tin cấu hình",
+"Config model": "Mô hình cấu hình",
+"Restart Codex++": "Khởi động lại Codex++",
+"Reinstall": "Cài đặt lại",
+"Regenerate": "tái sinh",
+"Reset background": "Đặt lại nền",
+"Silent launch entrypoint": "Điểm khởi động im lặng",
+"Project URL": "URL dự án",
+"Extra arguments": "Đối số bổ sung",
+"Advanced option, off by default; the current implementation doesn't actively modify Zed settings.": "Tùy chọn nâng cao, tắt theo mặc định; việc triển khai hiện tại không tích cực sửa đổi cài đặt Zed.",
+"Default relay": "Rơle mặc định",
+"Off by default; when on, launching Codex automatically preserves the config.toml, bundled plugins and notify config required by the official Computer Use plugin.": "Tắt theo mặc định; khi được bật, việc khởi chạy Codex sẽ tự động lưu giữ config.toml, các plugin đi kèm và cấu hình thông báo theo yêu cầu của plugin Sử dụng Máy tính chính thức.",
+"The model name used by default when launching Codex; don't include a suffix. Configure context windows per model in the “Model list” below.": "Tên model được sử dụng theo mặc định khi khởi chạy Codex; không bao gồm một hậu tố. Định cấu hình cửa sổ ngữ cảnh cho mỗi mô hình trong “Danh sách mô hình” bên dưới.",
+"Off by default; enable it without a VPN to let Statsig initialization fail fast and reduce launch time. Requires restarting Codex.": "Tắt theo mặc định; kích hoạt nó mà không cần VPN để quá trình khởi tạo Statsig không thành công nhanh chóng và giảm thời gian khởi chạy. Yêu cầu khởi động lại Codex.",
+"Default open strategy": "Chiến lược mở mặc định",
+" (": null,
+")": null,
+"; you can add them from the common config file or here.": "; bạn có thể thêm chúng từ tệp cấu hình chung hoặc tại đây.",
+"; leave empty to use Codex's default length.": "; để trống để sử dụng độ dài mặc định của Codex.",
+"; these entries are saved independently of providers and written to config.toml after switching to any provider.": "; các mục này được lưu độc lập với nhà cung cấp và được ghi vào config.toml sau khi chuyển sang bất kỳ nhà cung cấp nào.",
+"\n...and {0} more session(s)": "...và {0} phiên khác",
+"{0} · {1} member(s)": "{0} · {1} thành viên",
+"{0}": "{0}",
+"{0} project(s) recognized by Codex++, default strategy: {1}": "{0} (các) dự án được Codex++ công nhận, chiến lược mặc định: {1}",
+"{0} provider(s)": "{0} nhà cung cấp",
+"{0} provider configuration(s); drag to reorder, click edit for details": "{0} (các) cấu hình nhà cung cấp; kéo để sắp xếp lại, bấm chỉnh sửa để biết chi tiết",
+"{0} marketplace script(s), {1} installed, local overall {2}": "{0} (các) tập lệnh thị trường, {1} đã cài đặt, tổng thể cục bộ {2}",
+"{0} project(s)": "{0} dự án",
+"{0} copy": "{0} bản sao",
+"{0} item(s)": "{0} mặt hàng",
+"Provider {0}": "Nhà cung cấp {0}",
+"Provider “{0}” is missing its own config.toml, so the switch was stopped to avoid showing the previous config files. Save config.toml in this provider's details first.": "Nhà cung cấp “{0}” thiếu config.toml riêng nên quá trình chuyển đổi đã bị dừng để tránh hiển thị các tệp cấu hình trước đó. Trước tiên hãy lưu config.toml trong thông tin chi tiết của nhà cung cấp này.",
+"Delete session “{0}”? This deletes the local database record and rollout file, and creates a backup.": "Xóa phiên “{0}”? Thao tác này sẽ xóa bản ghi cơ sở dữ liệu cục bộ và tệp triển khai, đồng thời tạo bản sao lưu.",
+"Delete script “{0}”? This removes the local script file.": "Xóa tập lệnh “{0}”? Thao tác này sẽ xóa tệp tập lệnh cục bộ.",
+"Delete these environment variables?\n\n{0}\n\nA backup is written before deletion.": "Xóa các biến môi trường này?\n\n{0}\n\nMột bản sao lưu được viết trước khi xóa.",
+"Delete the {0} selected session(s)? This deletes the local database records and rollout files, and creates a backup for each session.\n\n{1}{2}": "Xóa {0} phiên đã chọn? Thao tác này sẽ xóa các bản ghi cơ sở dữ liệu cục bộ và các tệp triển khai, đồng thời tạo bản sao lưu cho mỗi phiên.\n\n{1}{2}",
+"Found {0} Codex provider(s)": "Đã tìm thấy {0} nhà cung cấp Codex",
+"New version {0} available": "Đã có phiên bản mới {0}",
+"Official login ready: {0}, the current API Key will be mixed in.": "Đăng nhập chính thức đã sẵn sàng: {0}, Khóa API hiện tại sẽ được trộn vào.",
+"Official account logged in: {0}.": "Tài khoản chính thức đã đăng nhập: {0}.",
+"Deleted {0} session(s).": "Đã xóa {0} phiên.",
+"Deleted {0}, failed {1}: {2}": "Đã xóa {0}, không thành công {1}: {2}",
+"Loaded {0} recommendation(s)": "Đã tải {0} đề xuất",
+"Synced to {0}: repaired {1} session file(s), updated {2} index row(s){3}.": "Đã đồng bộ hóa với {0}: đã sửa chữa {1} tệp phiên, đã cập nhật {2} hàng chỉ mục{3}.",
+"Installed {0}": "Đã cài đặt {0}",
+"Cached {0} plugin(s) / {1} skill(s).": "Đã lưu vào bộ nhớ đệm {0} plugin / {1} kỹ năng.",
+"Running for {0} minute(s)": "Chạy được {0} phút",
+"Running for {0} hour(s) {1} minute(s)": "Chạy trong {0} giờ {1} phút",
+"Marketplace · {0}": "Chợ · {0}",
+"Current version {0}": "Phiên bản hiện tại {0}",
+"Failed to open the picker: {0}": "Không mở được bộ chọn: {0}",
+"Syncing to {0}…": "Đang đồng bộ hóa với {0}…",
+"Manifest updated at: {0}": "Bản kê khai được cập nhật lúc: {0}",
+"Leave empty to use the default: {0}": "Để trống để sử dụng mặc định: {0}",
+"Aggregate provider {0}": "Nhà cung cấp tổng hợp {0}",
+"The aggregate provider is configured as {0} with {1} member(s); real conversations rotate through the local proxy.": "Nhà cung cấp tổng hợp được định cấu hình là {0} với {1} thành viên; các cuộc hội thoại thực sự xoay vòng qua proxy cục bộ.",
+"Process status: {0}. Restart?": "Trạng thái xử lý: {0}. Khởi động lại?",
+"Select session {0}": "Chọn phiên {0}",
+"Opacity {0}%": "Độ mờ {0}%",
+", skipped {0} locked file(s)": ", đã bỏ qua {0} tệp bị khóa",
+"Backend version loaded.": "Đã tải phiên bản phụ trợ.",
+"Launch arguments loaded.": "Khởi chạy các đối số đã được tải.",
+"Overview background task failed.": "Nhiệm vụ nền tổng quan không thành công.",
+"Overview loaded.": "Đã tải tổng quan.",
+"Launch task started in the background. Check overview status later.": "Nhiệm vụ khởi động bắt đầu ở chế độ nền. Kiểm tra trạng thái tổng quan sau.",
+"Settings loaded.": "Đã tải cài đặt.",
+"Failed to read settings": "Không đọc được cài đặt",
+"Failed to reload settings after save": "Không thể tải lại cài đặt sau khi lưu",
+"No new cc-switch provider configs to import.": "Không có cấu hình nhà cung cấp cc-switch mới nào để nhập.",
+"Failed to reload settings after importing provider config": "Không thể tải lại cài đặt sau khi nhập cấu hình nhà cung cấp",
+"Pending provider import loaded.": "Đang chờ nhập nhà cung cấp.",
+"No pending provider import.": "Không có nhà cung cấp đang chờ nhập.",
+"Provider import cancelled.": "Đã hủy nhập nhà cung cấp.",
+"Session ID must not be empty.": "ID phiên không được để trống.",
+"Recommendations loaded.": "Đã tải đề xuất.",
+"Script marketplace refreshed.": "Thị trường tập lệnh được làm mới.",
+"Script ID must not be empty.": "ID tập lệnh không được để trống.",
+"Script not found in marketplace manifest.": "Không tìm thấy tập lệnh trong bảng kê khai thị trường.",
+"Script installed.": "Đã cài đặt tập lệnh.",
+"Script key must not be empty.": "Khóa tập lệnh không được để trống.",
+"Script enabled.": "Đã bật tập lệnh.",
+"Script disabled.": "Tập lệnh bị vô hiệu hóa.",
+"Failed to toggle script": "Không thể chuyển đổi tập lệnh",
+"Script deleted.": "Kịch bản đã bị xóa.",
+"Failed to delete script": "Không xóa được tập lệnh",
+"Only http or https links can be opened.": "Chỉ có thể mở liên kết http hoặc https.",
+"Link opened in system browser.": "Liên kết được mở trong trình duyệt hệ thống.",
+"Failed to reload settings after repair": "Không thể tải lại cài đặt sau khi sửa chữa",
+"Plugin marketplace needs initialization or registration.": "Thị trường plugin cần khởi tạo hoặc đăng ký.",
+"Plugin marketplace is available.": "Thị trường plugin có sẵn.",
+"Plugin marketplace initialized and registered from openai/plugins.": "Thị trường plugin được khởi tạo và đăng ký từ openai/plugin.",
+"Local plugin marketplace registered.": "Đã đăng ký thị trường plugin địa phương.",
+"Plugin marketplace is available; no repair needed.": "Thị trường plugin có sẵn; không cần sửa chữa.",
+"Official remote plugin cache needs extraction or registration.": "Bộ đệm plugin từ xa chính thức cần trích xuất hoặc đăng ký.",
+"Official remote plugin cache is available.": "Bộ đệm plugin từ xa chính thức có sẵn.",
+"Embedded official remote plugin cache extracted and registered.": "Đã trích xuất và đăng ký bộ nhớ đệm plugin từ xa chính thức được nhúng.",
+"Official remote plugin cache registered.": "Đã đăng ký bộ nhớ đệm plugin từ xa chính thức.",
+"Official remote plugin cache is available; no repair needed.": "Bộ đệm plugin từ xa chính thức có sẵn; không cần sửa chữa.",
+"Update available.": "Cập nhật có sẵn.",
+"Already on the latest version.": "Đã có trên phiên bản mới nhất.",
+"Check for updates first and select a downloadable release asset.": "Trước tiên hãy kiểm tra các bản cập nhật và chọn nội dung phát hành có thể tải xuống.",
+"Installer downloaded and launched. Follow the setup wizard to finish updating.": "Trình cài đặt đã được tải xuống và khởi chạy. Làm theo trình hướng dẫn thiết lập để hoàn tất cập nhật.",
+"Logs loaded.": "Đã tải nhật ký.",
+"Diagnostics report generated.": "Đã tạo báo cáo chẩn đoán.",
+"Settings reset to defaults.": "Cài đặt lại về mặc định.",
+"Failed to reload settings after reset": "Không thể tải lại cài đặt sau khi đặt lại",
+"Image overlay settings reset.": "Đặt lại cài đặt lớp phủ hình ảnh.",
+"Failed to reload settings after image overlay reset": "Không thể tải lại cài đặt sau khi đặt lại lớp phủ hình ảnh",
+"ChatGPT login detected.": "Đã phát hiện đăng nhập ChatGPT.",
+"ChatGPT login not detected. Please log in to Codex/ChatGPT first.": "Không phát hiện đăng nhập ChatGPT. Vui lòng đăng nhập vào Codex/ChatGPT trước.",
+"Config file content loaded.": "Đã tải nội dung tệp cấu hình.",
+"No OPENAI environment variables found that would override the Codex provider config.": "Không tìm thấy biến môi trường OPENAI nào sẽ ghi đè cấu hình nhà cung cấp Codex.",
+"OPENAI environment variables detected that may override the Codex provider config.": "Các biến môi trường OPENAI được phát hiện có thể ghi đè cấu hình nhà cung cấp Codex.",
+"Environment variables deleted as confirmed. Restart Codex for changes to take effect.": "Các biến môi trường đã bị xóa như đã được xác nhận. Khởi động lại Codex để các thay đổi có hiệu lực.",
+"Config file saved.": "Đã lưu tập tin cấu hình.",
+"Provider switch lock is corrupted. Please restart the manager and try again.": "Khóa chuyển đổi nhà cung cấp bị hỏng. Vui lòng khởi động lại trình quản lý và thử lại.",
+"Provider switched.": "Nhà cung cấp đã chuyển đổi.",
+"The current provider is no longer in the config list. Switching stopped to avoid overwriting user changes.": "Nhà cung cấp hiện tại không còn trong danh sách cấu hình. Việc chuyển đổi đã dừng lại để tránh ghi đè những thay đổi của người dùng.",
+"Current provider config backfilled from live files.": "Cấu hình nhà cung cấp hiện tại được chèn lấp từ các tệp trực tiếp.",
+"Tools & plugins list loaded.": "Đã tải danh sách công cụ và plugin.",
+"Common config extracted using compatibility switching rules.": "Cấu hình chung được trích xuất bằng quy tắc chuyển đổi tương thích.",
+"Provider config master switch is off. Nothing written to config.toml / auth.json.": "Công tắc chính của cấu hình nhà cung cấp đang tắt. Không có gì được ghi vào config.toml/auth.json.",
+"Provider switched using compatibility rules.": "Nhà cung cấp đã chuyển đổi bằng cách sử dụng các quy tắc tương thích.",
+"ChatGPT login not detected": "Không phát hiện đăng nhập ChatGPT",
+"ChatGPT login not detected. Relay config not written.": "Không phát hiện đăng nhập ChatGPT. Cấu hình chuyển tiếp không được ghi.",
+"Relay config written. Keys are not shown in plaintext in the UI.": "Cấu hình chuyển tiếp được viết. Các khóa không được hiển thị dưới dạng văn bản gốc trong giao diện người dùng.",
+"Aggregate provider config written. Real requests will be rotated by the local proxy according to the strategy.": "Đã viết cấu hình nhà cung cấp tổng hợp. Các yêu cầu thực sự sẽ được proxy cục bộ luân chuyển theo chiến lược.",
+"Custom relay API mode cleared. Switched to official ChatGPT login mode.": "Đã xóa chế độ API chuyển tiếp tùy chỉnh. Đã chuyển sang chế độ đăng nhập ChatGPT chính thức.",
+"Pure API mode written: config.toml now has a custom provider, auth.json switched to the current provider.": "Chế độ API thuần túy được viết: config.toml hiện có nhà cung cấp tùy chỉnh, auth.json đã chuyển sang nhà cung cấp hiện tại.",
+"After writing pure API config, no complete custom provider was detected. Please check config.toml and the provider API Key.": "Sau khi viết cấu hình API thuần túy, không phát hiện thấy nhà cung cấp tùy chỉnh hoàn chỉnh nào. Vui lòng kiểm tra config.toml và Khóa API của nhà cung cấp.",
+"Failed to reload settings after provider import": "Không thể tải lại cài đặt sau khi nhập nhà cung cấp",
+"Diagnostics log written.": "Nhật ký chẩn đoán được viết.",
+"Unnamed provider": "Nhà cung cấp ẩn danh",
+"Response is empty": "Phản hồi trống",
+"Failed to launch silent entrypoint: $1": "Không thể khởi chạy điểm vào im lặng: $1",
+"Cannot launch $1: $2": "Không thể khởi chạy $1: $2",
+"Settings saved.$1": "Đã lưu cài đặt.$1",
+"Failed to save settings: $1": "Không lưu được cài đặt: $1",
+"Read $1 cc-switch Codex provider config(s).": "Đọc (các) cấu hình nhà cung cấp Codex $1 cc-switch.",
+"Failed to read cc-switch provider configs: $1": "Không đọc được cấu hình nhà cung cấp cc-switch: $1",
+"Imported $1 cc-switch provider config(s).": "Đã nhập (các) cấu hình nhà cung cấp cc-switch $1.",
+"Failed to save cc-switch provider configs: $1": "Không lưu được cấu hình nhà cung cấp cc-switch: $1",
+"Imported provider config: $1.": "Cấu hình nhà cung cấp đã nhập: $1.",
+"Provider config already exists: $1.": "Cấu hình nhà cung cấp đã tồn tại: $1.",
+"Failed to import provider config: $1": "Không thể nhập cấu hình nhà cung cấp: $1",
+"Failed to cancel provider import: $1": "Không hủy được việc nhập nhà cung cấp: $1",
+"Read $1 local session(s).": "Đọc (các) phiên địa phương $1.",
+"Failed to read some local sessions: $1": "Không đọc được một số phiên địa phương: $1",
+"Read $1 Zed remote project(s).": "Đọc (các) dự án từ xa $1 của Zed.",
+"Failed to read Zed remote projects.": "Không đọc được các dự án từ xa của Zed.",
+"Project opened in Zed Remote.": "Dự án đã mở trong Zed Remote.",
+"Cannot open project in Zed Remote.": "Không thể mở dự án trong Zed Remote.",
+"Failed to remove Zed remote project.": "Không thể xóa dự án từ xa Zed.",
+"Provider synced: $1 session file(s), $2 index row(s), skipped $3 locked file(s).": "Nhà cung cấp đã đồng bộ hóa: $1 tệp phiên, $2 hàng chỉ mục, bỏ qua $3 tệp bị khóa.",
+"Provider sync failed: $1": "Đồng bộ hóa nhà cung cấp không thành công: $1",
+"Failed to load recommendations: $1": "Không tải được đề xuất: $1",
+"Failed to load script marketplace: $1": "Không thể tải thị trường tập lệnh: $1",
+"Failed to install script: $1": "Không cài đặt được tập lệnh: $1",
+"Failed to toggle script: $1": "Không thể chuyển đổi tập lệnh: $1",
+"Failed to delete script: $1": "Không xóa được tập lệnh: $1",
+"Failed to open link: $1": "Không mở được liên kết: $1",
+"Plugin marketplace repair failed: $1": "Sửa chữa thị trường plugin không thành công: $1",
+"Official remote plugin cache repair failed: $1": "Sửa chữa bộ nhớ đệm plugin từ xa chính thức không thành công: $1",
+"Failed to check for updates: $1": "Không kiểm tra được bản cập nhật: $1",
+"Failed to install update: $1": "Không cài đặt được bản cập nhật: $1",
+"Failed to install watcher: $1": "Không cài đặt được trình theo dõi: $1",
+"Failed to remove watcher: $1": "Không xóa được người theo dõi: $1",
+"Failed to enable watcher: $1": "Không bật được trình theo dõi: $1",
+"Failed to disable watcher: $1": "Không tắt được trình theo dõi: $1",
+"Failed to read logs: $1": "Không đọc được nhật ký: $1",
+"Failed to reset settings: $1": "Không thể đặt lại cài đặt: $1",
+"Failed to reset image overlay: $1": "Không thể đặt lại lớp phủ hình ảnh: $1",
+"Failed to read config file: $1": "Không đọc được tệp cấu hình: $1",
+"Failed to delete environment variables: $1": "Không thể xóa các biến môi trường: $1",
+"Failed to save config file: $1": "Không lưu được tập tin cấu hình: $1",
+"Provider switch failed: $1": "Chuyển đổi nhà cung cấp không thành công: $1",
+"Failed to write diagnostics log: $1": "Không thể ghi nhật ký chẩn đoán: $1",
+"Failed to backfill current provider config: $1": "Không thể chèn lấp cấu hình nhà cung cấp hiện tại: $1",
+"Failed to read tools & plugins list: $1": "Không đọc được danh sách công cụ và plugin: $1",
+"Failed to read live tools & plugins: $1": "Không đọc được các công cụ và plugin trực tiếp: $1",
+"Failed to save tools & plugins: $1": "Không lưu được công cụ và plugin: $1",
+"Failed to read live config.toml: $1": "Không thể đọc config.toml trực tiếp: $1",
+"Failed to sync live tools & plugins: $1": "Không thể đồng bộ hóa các công cụ và plugin trực tiếp: $1",
+"Failed to create Codex config directory: $1": "Không tạo được thư mục cấu hình Codex: $1",
+"Failed to write live config.toml: $1": "Không thể ghi config.toml trực tiếp: $1",
+"Failed to read live tools & plugins after sync: $1": "Không thể đọc các công cụ và plugin trực tiếp sau khi đồng bộ hóa: $1",
+"Failed to delete tools & plugins: $1": "Không xóa được công cụ và plugin: $1",
+"Failed to extract common config: $1": "Không trích xuất được cấu hình chung: $1",
+"Sent hi to \"$1\" using model \"$2\", HTTP $3.$4": "Đã gửi lời chào tới \"$1\" bằng mô hình \"$2\", HTTP $3.$4",
+"Test \"$1\" failed: $2": "Kiểm tra \"$1\" không thành công: $2",
+"Fetched $2 model(s) from \"$1\".": "Đã tìm nạp (các) mẫu $2 từ \"$1\".",
+"Failed to fetch models from \"$1\": $2": "Không tìm nạp được mô hình từ \"$1\": $2",
+"Failed to switch full relay config: $1": "Không thể chuyển đổi cấu hình chuyển tiếp đầy đủ: $1",
+"Failed to write relay config: $1": "Không thể ghi cấu hình chuyển tiếp: $1",
+"Failed to write aggregate provider config: $1": "Không thể ghi cấu hình nhà cung cấp tổng hợp: $1",
+"Failed to switch to pure API config: $1": "Không thể chuyển sang cấu hình API thuần túy: $1",
+"Failed to write pure API mode: $1": "Không thể ghi chế độ API thuần túy: $1",
+"Failed to clear relay config: $1": "Không xóa được cấu hình chuyển tiếp: $1",
+"Unknown config file type: $1": "Loại tệp cấu hình không xác định: $1",
+"Failed to launch system browser: $1": "Không khởi chạy được trình duyệt hệ thống: $1",
+"Failed to serialize diagnostics report: $1": "Không thể tuần tự hóa báo cáo chẩn đoán: $1",
+"Response: $1": "Phản hồi: $1",
+"JOJO Code Monthly": "JOJO Code theo tháng"
+}
\ No newline at end of file