{ "title": "Cài đặt", "subtitle": "Quản lý định giá, thông báo, dữ liệu và hooks", "exportData": "Xuất dữ liệu", "acrossSessions": "Trên toàn bộ phiên đang được theo dõi", "basedOnUsage": "Dựa trên mức dùng token theo mô hình", "sagi": { "title": "Bạn đồng hành Sagi", "description": "Linh vật nổi phản ứng với các phiên trực tiếp của bạn.", "enable": "Hiện Sagi", "enableDesc": "Hiển thị bạn đồng hành ở góc trên toàn bảng điều khiển (⌘B để mở)" }, "pricing": { "title": "Định giá mô hình", "description": "Đơn giá theo một triệu token (USD). Dùng % làm ký tự đại diện trong mẫu. Một số mô hình có mức giá giới thiệu có thời hạn (hiển thị màu tím); usage vào hoặc trước ngày kết thúc tính theo mức đó, sau đó tính theo mức chuẩn.", "introNote": "Ưu đãi ${{input}}/${{output}} đến {{until}}", "introRatesTitle": "Giá giới thiệu", "introRatesHint": "Để trống ngày nếu không có ưu đãi", "introUntil": "Đến (ngày)", "introUntilInvalid": "Ngày kết thúc ưu đãi phải theo định dạng YYYY-MM-DD", "resetConfirm": "Xác nhận đặt lại", "resetDefaults": "Khôi phục mặc định", "resetResult": "Đã đặt lại về {{count}} quy tắc mặc định", "addModel": "Thêm mô hình", "pattern": "Mẫu", "patternPlaceholder": "claude-opus-4%", "namePlaceholder": "Claude Opus 4", "validationRequired": "Bắt buộc nhập mẫu và tên hiển thị", "lastUpdated": "Cập nhật lần cuối: ", "tooltip": { "title": "Cách hoạt động của định giá mô hình", "howItWorks": "Cách hoạt động", "howItWorksBody": "Khi một phiên báo cáo mức dùng, dashboard tìm quy tắc định giá đầu tiên có mẫu khớp với model id, rồi nhân (token đầu vào / 1 triệu) và (token đầu ra / 1 triệu) với các đơn giá bên dưới để tính chi phí. Quy tắc được duyệt từ trên xuống - quy tắc khớp đầu tiên sẽ được dùng.", "patternsTitle": "Cú pháp mẫu", "patternsBody": "Mẫu là dạng glob kiểu SQL. % là ký tự đại diện khớp với bất kỳ chuỗi nào. Ví dụ: claude-opus-4-7% khớp mọi model id bắt đầu bằng claude-opus-4-7 (ví dụ claude-opus-4-7, claude-opus-4-7-20260101). claude-%-haiku khớp mọi biến thể haiku. Một id chính xác như claude-sonnet-4-6 chỉ khớp với chính nó.", "manualUpdates": "Bạn phải cập nhật giá thủ công", "manualUpdatesBody": "Anthropic công bố thay đổi giá trên website của họ - không có nguồn dữ liệu trực tiếp. Khi có model mới ra mắt hoặc đơn giá thay đổi, hãy chỉnh sửa quy tắc tương ứng (hoặc thêm quy tắc mới ở phía trên quy tắc bao quát) để những phiên ghi nhận sau này được tính phí chính xác. Phiên đã lưu vẫn giữ nguyên giá đã áp dụng tại thời điểm nạp.", "apiPricing": "Chỉ để tham khảo - đơn giá API", "apiPricingBody": "Đây là đơn giá API trả theo lượng dùng. Nếu bạn dùng Claude Code theo gói thuê bao (Pro, Max, Team hoặc Enterprise), chi phí thực tế là phí cố định hàng tháng chứ không tính theo token - nên những con số ở đây thường cao hơn số tiền bạn thực trả. Hãy xem chi phí ở đây là ước tính mức dùng để tham khảo, không phải hóa đơn." }, "cacheWrite5m": "Ghi bộ nhớ đệm (5m)", "cacheWrite1h": "Ghi bộ nhớ đệm (1h)", "fastInput": "Fast Input", "fastOutput": "Fast Output" }, "claudeHome": { "title": "CLAUDE_HOME", "description": "Thư mục gốc chứa dữ liệu phiên Claude Code. Thay đổi sẽ cập nhật ngay đường dẫn quét cho transcript và import.", "save": "Lưu", "saving": "Đang lưu...", "current": "Hiện tại:", "placeholder": "/đường-dẫn/tới/claude-home", "saveFailed": "Cập nhật CLAUDE_HOME thất bại" }, "hooks": { "title": "Cấu hình hook", "description": "Hooks của Claude Code chuyển tiếp sự kiện về dashboard theo thời gian thực.", "allInstalled": "Đã cài đầy đủ hooks", "incomplete": "Hooks chưa đầy đủ", "reinstall": "Cài lại hooks", "success": "Cài hooks thành công", "failed": "Cài hooks thất bại" }, "lanesSection": { "title": "Lanes", "description": "Bảo trì toàn máy và cài đặt một lần cho pipeline ship-feature-lane.", "installSkill": "Cài skill ship-feature-lane", "installSkillSuccess": "Đã cài vào {{path}}", "runHousekeeping": "Chạy dọn dẹp", "dryRun": "Chạy thử (dry run)", "gcResult": "Đã dọn {{reaped}} tiến trình, cắt {{capped}} log" }, "notifications": { "awaitingInput": "Claude cần xác nhận", "blocked": "Đã chặn quyền", "description": "Thông báo trình duyệt cho các sự kiện quan trọng. Cần cấp quyền.", "disabledInfo": "Thông báo đang tắt - bật để nhận cảnh báo sự kiện phiên", "enable": "Bật thông báo trình duyệt", "granted": "Đã cấp quyền", "newSession": "Phiên mới bắt đầu", "notifyWhen": "Thông báo cho tôi khi...", "required": "Cần cấp quyền", "sendTest": "Gửi thông báo thử", "sessionComplete": "Phiên hoàn tất", "sessionError": "Phiên gặp lỗi", "subagentSpawned": "Subagent được tạo", "testBlocked": "Trình duyệt chưa cấp quyền thông báo.", "testBody": "Thông báo đang hoạt động!", "testFailed": "Không hiển thị được thông báo nào.", "testLocal": "Trình duyệt chưa đăng ký push nên thông báo được hiện tại chỗ. Web Push cần origin bảo mật (localhost hoặc HTTPS) và service worker đã đăng ký.", "testSent": "Đã gửi qua push — kiểm tra trung tâm thông báo.", "testTitle": "Agent Monitor", "title": "Thông báo", "turnComplete": "Claude trả lời xong" }, "import": { "title": "Nhập lịch sử", "description": "Đưa các phiên Claude Code hiện có vào dashboard. Số token, chi phí theo mô hình, lần nén ngữ cảnh, subagent, lượt dùng tool và thời lượng từng lượt được dựng lại từ chính các transcript JSONL gốc - y hệt cách phiên trực tiếp được ghi nhận.", "accuracyNote": "Chạy lại nhiều lần luôn an toàn. Phiên được khử trùng lặp theo session ID, và mốc nén ngữ cảnh đảm bảo tổng token không bao giờ bị tính trùng.", "supportedFiles": "Định dạng được hỗ trợ: .jsonl, .meta.json, .zip, .tar, .tar.gz, .tgz, .gz", "instructions": "Cách thu thập lịch sử của bạn", "stepLocate": "1. Tìm lịch sử Claude Code của bạn", "stepLocateBody": "Mỗi phiên Claude Code được lưu thành một transcript JSONL trong thư mục projects. Mỗi thư mục con được đặt tên theo thư mục làm việc nơi phiên bắt đầu (dấu / đổi thành -).", "stepArchive": "2. Đóng gói để chuyển (tuỳ chọn)", "stepArchiveBody": "Để chuyển lịch sử từ máy khác, hãy nén toàn bộ thư mục trước, rồi sao chép qua (AirDrop, scp, USB, lưu trữ đám mây):", "stepChoose": "3. Chọn chế độ nhập bên dưới", "stepChooseBody": "Quét lại vị trí mặc định, trỏ tới thư mục bạn đã giải nén lịch sử, hoặc tải tệp/lưu trữ trực tiếp.", "stepVerify": "4. Kiểm tra token và chi phí", "stepVerifyBody": "Sau khi nhập xong, mở Analytics → Cost để kiểm tra phân tích chi phí. Nhập lại cùng một phiên luôn an toàn.", "defaultLocation": "Vị trí mặc định trên máy này", "locationFound": "Đã tìm thấy thư mục", "locationMissing": "Không tìm thấy thư mục", "projectsLabel": "dự án", "jsonlLabel": "tệp JSONL", "modeRescan": "Quét lại thư mục mặc định", "modeRescanDesc": "Đọc lại ~/.claude/projects và nhập mọi thứ mới.", "modeFolder": "Quét một thư mục", "modeFolderDesc": "Quét bất kỳ thư mục nào trên máy để tìm transcript JSONL (đệ quy thư mục con).", "modeUpload": "Tải tệp lên", "modeUploadDesc": "Kéo thả tệp JSONL hoặc lưu trữ (.zip / .tar.gz) trực tiếp vào trình duyệt.", "modeBackup": "Khôi phục sao lưu", "modeBackupDesc": "Nhập tệp xuất của bảng điều khiển (.json) — gộp lịch sử từ máy khác vào.", "backupHint": "Kéo tệp .json đã xuất vào đây hoặc bấm để chọn", "backupSub": "Tệp do nút Xuất dữ liệu tạo ra (đầu trang Cài đặt)", "runRestore": "Khôi phục", "backupResult": { "title": "Khôi phục hoàn tất", "sessionsImported": "Phiên đã thêm: {{count}}", "sessionsSkipped": "Đã có sẵn: {{count}}", "events": "Sự kiện: {{count}}", "pricing": "Quy tắc giá: {{count}}", "detail": "{{agents}} agent · {{workflows}} quy trình · {{runs}} lần chạy · {{rules}} quy tắc cảnh báo" }, "folderPlaceholder": "/đường-dẫn-tuyệt-đối/tới/claude-history", "folderHelper": "Đường dẫn tuyệt đối. Ký tự ~ sẽ được mở rộng. Thư mục con được quét đệ quy.", "runRescan": "Quét lại ngay", "runScan": "Quét thư mục", "runUpload": "Tải lên & nhập", "dropzoneHint": "Kéo thả tệp vào đây hoặc bấm để chọn", "dropzoneSub": "Chấp nhận .jsonl, .meta.json, .zip, .tar, .tar.gz, .tgz, .gz", "filesSelected": "Đã chọn {{count}} tệp", "clearSelection": "Xóa lựa chọn", "copy": "Sao chép", "copied": "Đã sao chép", "progress": { "scan": "Đang quét thư mục...", "extract": "Đang giải nén ({{processed}}/{{total}})...", "parse": "Đang phân tích transcript ({{processed}}/{{total}})...", "complete": "Nhập hoàn tất", "error": "Nhập thất bại" }, "result": { "imported": "Đã nhập: {{count}}", "backfilled": "Đã làm giàu phiên cũ: {{count}}", "skipped": "Đã cập nhật trước đó: {{count}}", "errors": "Lỗi: {{count}}", "filesScanned": "Tệp đã quét: {{count}}", "title": "Kết quả nhập gần nhất" }, "errors": { "noFiles": "Chưa chọn tệp nào", "noJsonl": "Không tìm thấy tệp .jsonl trong nội dung tải lên", "pathRequired": "Cần nhập đường dẫn", "pathInvalid": "Đường dẫn phải là tuyệt đối", "pathNotFound": "Đường dẫn không tồn tại", "pathNotDir": "Đường dẫn không phải thư mục", "generic": "Nhập thất bại: {{message}}" } }, "data": { "title": "Quản lý dữ liệu", "description": "Thông tin cơ sở dữ liệu, nhập/xuất và dọn dẹp.", "dbOverview": "Tổng quan cơ sở dữ liệu", "dbSize": "Kích thước CSDL", "loadingDb": "Đang tải thông tin cơ sở dữ liệu...", "sessionCleanup": "Dọn dẹp phiên", "cleanupDesc": "Đánh dấu bỏ dở các phiên cũ và xóa dữ liệu cũ", "abandonAfter": "Đánh dấu bỏ dở phiên đang hoạt động cũ hơn", "purgeAfter": "Xóa phiên hoàn tất/lỗi cũ hơn", "confirmCleanup": "Xác nhận dọn dẹp", "runCleanup": "Chạy dọn dẹp", "nothingToClean": "Không có gì để dọn dẹp", "abandonedResult": " phiên đã bị bỏ dở", "purgedResult": " phiên đã xóa ({{events}} sự kiện, {{agents}} Agent)" }, "danger": { "title": "Vùng nguy hiểm", "description": "Các thao tác không thể hoàn tác, xóa dữ liệu vĩnh viễn", "warning": "Thao tác này sẽ xóa toàn bộ phiên, Agent, sự kiện và dữ liệu token. Bạn chắc chứ?", "yesClearAll": "Có, xóa tất cả", "clearAllData": "Xóa toàn bộ dữ liệu", "clearedResult": "Đã xóa {{count}} dòng" }, "about": { "title": "Giới thiệu", "description": "Thông tin runtime của máy chủ.", "release": "Phiên bản", "uiBuild": "UI build v{{version}} (hãy build lại client để khớp)", "uptime": "Thời gian chạy", "nodejs": "Node.js", "platform": "Nền tảng", "wsClients": "WS Clients", "loadingInfo": "Đang tải thông tin máy chủ..." }, "tables": { "sessions": "phiên", "agents": "Agent", "events": "sự kiện", "sessionsWithCost": "phiên có chi phí", "pricingRules": "quy tắc định giá" }, "messages": { "failedLoad": "Tải dữ liệu thất bại", "failedSave": "Lưu thất bại", "failedDelete": "Xóa thất bại", "unknownError": "Không xác định", "actionFailed": "Lỗi: {{message}}" }, "webhooks": { "title": "Thông báo Webhook", "description": "Chuyển tiếp cảnh báo đã kích hoạt tới Slack, Discord, Microsoft Teams hoặc bất kỳ endpoint HTTP nào. Gửi tự động, thử lại khi lỗi và không bao giờ chặn việc giám sát.", "count_one": "{{count}} đích", "count_other": "{{count}} đích", "add": "Thêm Webhook", "loading": "Đang tải webhook…", "empty": "Chưa cấu hình webhook nào. Thêm một cái để chuyển tiếp cảnh báo tới Slack, Discord, Teams hoặc endpoint tùy chỉnh.", "scopedTo_one": "{{count}} quy tắc", "scopedTo_other": "{{count}} quy tắc", "enabled": "Đã bật", "test": "Thử", "edit": "Sửa", "delete": "Xóa", "confirmDelete": "Xác nhận", "testOk": "Đã gửi (HTTP {{status}})", "testFail": "Thất bại: {{error}}", "addTitle": "Webhook mới", "editTitle": "Sửa Webhook", "fieldName": "Tên", "fieldNamePlaceholder": "vd: Slack nhóm #alerts", "fieldType": "Loại", "type": { "slack": "Slack", "discord": "Discord", "teams": "Microsoft Teams", "generic": "Tùy chỉnh (JSON)" }, "fieldUrl": "URL Webhook", "urlKeepHint": "để trống để giữ nguyên", "urlKeepPlaceholder": "•••••••• (không đổi)", "urlPlaceholder": { "slack": "https://hooks.slack.com/services/…", "discord": "https://discord.com/api/webhooks/…", "teams": "https://outlook.office.com/webhook/…", "generic": "https://example.com/webhook" }, "fieldSecret": "Khóa ký (tùy chọn)", "secretPlaceholder": "Khóa HMAC-SHA256", "secretKeepPlaceholder": "•••••••• (để trống để giữ nguyên)", "secretHint": "Khi đặt, yêu cầu được ký bằng header X-Webhook-Signature.", "fieldHeaders": "Header tùy chỉnh (tùy chọn)", "replaceHeaders": "Thay header", "headerKey": "Header", "headerValue": "Giá trị", "addHeader": "Thêm header", "scopeAll": "Nhận cảnh báo từ tất cả quy tắc", "enabledOnSave": "Bật", "save": "Lưu", "create": "Tạo", "cancel": "Hủy", "urlOptional": "ghi đè tùy chọn", "urlAuto": "URL được đặt tự động từ thông tin xác thực bên dưới.", "deleteTitle": "Xóa webhook?", "deleteMessage": "Xóa \"{{name}}\"? Cảnh báo sẽ ngừng được gửi tới đích này. Không thể hoàn tác.", "guideToggle": "Cách thiết lập {{provider}}", "guideDocs": "Tài liệu chính thức của {{provider}}", "guideStaleNote": "Giao diện thiết lập của nhà cung cấp thường thay đổi nên các bước này có thể đã lỗi thời - hãy luôn kiểm tra tài liệu chính thức." }, "alertsHub": { "title": "Cảnh báo", "description": "Định nghĩa quy tắc cảnh báo, định tuyến tới các kênh webhook và xem những gì đã kích hoạt - tất cả ở một nơi.", "tabRules": "Quy tắc", "tabChannels": "Kênh", "tabActivity": "Hoạt động", "rulesHint": "Điều kiện kích hoạt cảnh báo. Được đánh giá ở phía máy chủ trên luồng sự kiện trực tiếp.", "rulesEmptyHint": "Thêm quy tắc để bắt đầu cảnh báo về lỗi, không hoạt động, agent bị treo hoặc ngưỡng token." }, "jumpTo": "Chuyển tới", "webhookGuides": { "slack": { "steps": [ "Tạo hoặc mở một Slack app tại api.slack.com/apps.", "Bật 'Incoming Webhooks', rồi nhấn 'Add New Webhook to Workspace'.", "Chọn kênh để đăng và cấp quyền.", "Sao chép URL được tạo (https://hooks.slack.com/services/…) và dán vào ô trên." ] }, "discord": { "steps": [ "Mở server → Cài đặt máy chủ → Tích hợp → Webhook.", "Nhấn 'New Webhook', chọn kênh, đổi tên nếu muốn.", "Nhấn 'Copy Webhook URL' và dán vào ô trên." ] }, "teams": { "steps": [ "Trong kênh Teams mục tiêu, nhấn ⋯ → 'Workflows'.", "Chọn mẫu 'Post to a channel when a webhook request is received'.", "Hoàn tất luồng và sao chép URL HTTP POST được tạo.", "Dán vào ô trên. (Office 365 connector cũ đã ngừng năm 2025 - dùng Workflows.)" ] }, "google_chat": { "steps": [ "Mở không gian Google Chat → tên không gian → 'Ứng dụng & tích hợp'.", "Nhấn 'Webhooks' → 'Add webhook' và đặt tên.", "Sao chép URL webhook và dán vào ô trên." ] }, "mattermost": { "steps": [ "Menu chính → Tích hợp → Incoming Webhooks (quản trị viên phải bật webhook trước).", "Nhấn 'Add Incoming Webhook' và chọn kênh.", "Lưu, rồi sao chép URL webhook và dán vào ô trên." ] }, "rocketchat": { "steps": [ "Quản trị → Tích hợp → New → Incoming.", "Bật nó, chọn kênh và lưu.", "Sao chép 'Webhook URL' và dán vào ô trên." ] }, "telegram": { "steps": [ "Nhắn @BotFather, chạy /newbot và sao chép bot token.", "Thêm bot vào nhóm/kênh của bạn (hoặc nhắn riêng cho nó).", "Tìm chat ID: gửi một tin nhắn, mở https://api.telegram.org/bot/getUpdates, đọc result[].message.chat.id.", "Nhập Bot token và Chat ID ở trên - không cần URL." ] }, "pagerduty": { "steps": [ "Mở Service mục tiêu → Integrations → 'Add integration'.", "Chọn 'Events API v2'.", "Sao chép Integration Key (routing key).", "Nhập làm Routing key ở trên - URL Events API đã được điền sẵn." ] }, "opsgenie": { "steps": [ "Settings → Integrations → thêm tích hợp 'API'.", "Sao chép API key được tạo.", "Ghi nhớ vùng tài khoản (US hoặc EU).", "Nhập API key và vùng ở trên - URL cảnh báo được suy ra từ vùng." ] }, "splunk_oncall": { "steps": [ "Integrations → REST Endpoint, và bật nó.", "Sao chép REST URL - nó đã chứa API key của bạn.", "Thay '$routing_key' ở cuối bằng một routing key của bạn.", "Dán URL đầy đủ vào ô trên." ] }, "zapier": { "steps": [ "Tạo một Zap với trigger 'Webhooks by Zapier' → 'Catch Hook'.", "Sao chép URL webhook tùy chỉnh mà nó cấp.", "Dán vào ô trên. Cảnh báo đến dạng JSON: { event, alert }." ] }, "make": { "steps": [ "Thêm module 'Webhooks' → 'Custom webhook' làm bước đầu của scenario.", "Nhấn 'Add', tạo hook và sao chép URL.", "Dán vào ô trên, rồi chạy một lần để Make học cấu trúc payload." ] }, "n8n": { "steps": [ "Thêm node 'Webhook' vào workflow; đặt method là POST.", "Sao chép Production URL.", "Kích hoạt workflow và dán URL vào ô trên (http được phép cho bản tự host)." ] }, "pipedream": { "steps": [ "Tạo workflow với trigger 'HTTP / Webhook'.", "Sao chép URL endpoint duy nhất.", "Dán vào ô trên; xem các lần gửi trong trình kiểm tra sự kiện của Pipedream." ] }, "generic": { "steps": [ "Trỏ tới bất kỳ endpoint nào nhận JSON POST (https, hoặc http để thử cục bộ).", "Cấu trúc body: { event: 'alert.triggered', source, sent_at, alert: { … } }.", "Tùy chọn: đặt khóa ký (HMAC-SHA256 trên body → header X-Webhook-Signature) và header tùy chỉnh.", "Mẹo: dùng công cụ miễn phí như webhook.site để xem payload chính xác." ] } }, "remoteSources": { "title": "Nguồn dữ liệu từ xa", "description": "Thu thập mức sử dụng Claude Code từ các máy khác qua SSH - ví dụ một máy dev hoặc máy ảo trên cloud mà bạn điều khiển qua SSH trong khi chạy bảng điều khiển này cục bộ. Xác thực dùng cấu hình SSH của chính bạn (~/.ssh/config, khóa, agent); không có mật khẩu nào được lưu ở đây.", "scopeTitle": "Phạm vi dữ liệu", "scopeDesc": "Chọn dữ liệu của những máy nào sẽ hiển thị trên toàn bộ bảng điều khiển. Thay đổi được áp dụng ngay lập tức trên mọi trang — phiên, phân tích và chi phí.", "scopeAll": "Tất cả nguồn", "scopeAllDesc": "Máy này cùng với mọi nguồn từ xa đã cấu hình, kết hợp lại.", "scopeLocal": "Chỉ máy này", "scopeLocalDesc": "Chỉ các phiên được thu thập cục bộ — ẩn toàn bộ dữ liệu nguồn từ xa.", "scopeSelected": "Nguồn đã chọn", "scopeSelectedDesc": "Chọn chính xác những máy cần đưa vào, bên dưới.", "scopeSelectedCount": "Đã chọn {{n}} trong {{total}}", "scopePickMachines": "Máy cần đưa vào", "thisMachine": "Máy này", "listTitle": "Nguồn đã cấu hình", "add": "Thêm nguồn", "addTitle": "Thêm nguồn từ xa", "editTitle": "Sửa nguồn", "fieldLabel": "Nhãn", "fieldHost": "Máy chủ SSH", "fieldPort": "Cổng (tùy chọn)", "fieldIdentity": "Tệp danh tính (tùy chọn)", "fieldRemoteHome": "Thư mục Claude từ xa (tùy chọn)", "fieldRemoteHomeHint": "Linux/macOS: mặc định ~/.claude (hoặc đường dẫn tuyệt đối như /home/you/.claude). SSH vào Windows mà Claude chạy trong WSL: để trống (tự phát hiện) hoặc dùng wsl:~/.claude. Windows thuần: C:/Users/you/.claude.", "fieldEnabled": "Tự động đồng bộ ở chế độ nền", "empty": "Chưa có nguồn từ xa nào.", "emptyHint": "Thêm một máy bạn kết nối qua SSH để kéo dữ liệu sử dụng Claude Code của máy đó về.", "paused": "Tắt tự động đồng bộ", "sessionCount": "{{n}} phiên", "sessionCountLinked": "{{n}} đã liên kết", "sessionCountHint": "Phiên gắn với nguồn này (không phải mọi phiên bạn thấy khi phạm vi dữ liệu là Tất cả)", "lastSync": "Đồng bộ lần cuối: {{when}}", "neverSynced": "Chưa bao giờ đồng bộ", "imported": "Đã nhập {{n}}", "syncNew": "{{n}} mới", "syncOnRemote": "{{n}} trên máy từ xa", "test": "Kiểm tra", "syncNow": "Đồng bộ", "syncAll": "Đồng bộ tất cả", "enable": "Bật", "disable": "Tắt", "confirmDelete": "Xóa nguồn này?", "purgeData": "Đồng thời xóa các phiên đã nhập từ nguồn này (không thể hoàn tác)", "deleteAndPurge": "Xóa + xóa dữ liệu", "removeKeep": "Xóa (giữ dữ liệu)", "remoteSourceBadgeTitle": "Được thu thập từ một máy từ xa" }, "cursorPathsNote": "Chỉ mang tính thông tin: phiên Cursor cũng được tính — Cursor tình cờ dùng cùng đường dẫn ~/.claude với Claude Code (cục bộ và trên máy từ xa đã đồng bộ).", "tools": { "label": "Công cụ", "dashboard": "Dashboard", "claudeCode": "Claude Code", "codex": "Codex", "aiRouter": "AI Router" }, "aiRouter": { "title": "AI Router", "description": "Các endpoint đứng trước Claude Code và Codex — 9Router, OpenRouter, hoặc gateway tự dựng. Lưu ở đây rồi chọn lúc tạo lane.", "add": "Thêm profile", "edit": "Sửa", "remove": "Xoá", "empty": "Chưa lưu profile router nào. Native là chạy thẳng vào API của hãng.", "builtinHint": "Dựng sẵn — đây là API của chính hãng, không sửa và không xoá được.", "colLabel": "Profile", "colBaseUrl": "Endpoint", "colModel": "Model", "colKey": "API key", "keySet": "Đã lưu", "keyMissing": "Chưa có", "fieldLabel": "Tên", "fieldLabelHint": "Tên bạn sẽ thấy trong form tạo lane. Gõ tự do.", "fieldBaseUrl": "Base URL", "fieldBaseUrlHint": "Endpoint tương thích OpenAI/Anthropic của router, ví dụ http://localhost:20128/v1", "fieldApiKey": "API key", "fieldApiKeyHint": "Lưu trên máy này ở quyền 0600, không bao giờ gửi ngược về trình duyệt.", "fieldApiKeyKeep": "Để trống nếu muốn giữ key đã lưu.", "fieldModel": "Model", "fieldModelHint": "Dùng cho mọi bậc trừ khi bạn ghi đè bên dưới. Nhiều router chỉ cần một tên tượng trưng.", "perTier": "Ghi đè theo từng bậc", "perTierHint": "Để trống một ô là dùng model ở trên.", "tier": { "opus": "Opus", "sonnet": "Sonnet", "haiku": "Haiku", "smallFast": "Nhỏ / nhanh", "subagent": "Subagent" }, "save": "Lưu", "cancel": "Huỷ", "removeConfirm": "Xoá profile \"{{label}}\"? Mọi lane đang dùng nó sẽ được đưa về API gốc của hãng ngay lập tức — cả trên đĩa lẫn trong dashboard.", "loading": "Đang tải danh sách profile…", "lanesFailed": "Đã lưu, nhưng {{count}} lane không cập nhật được và vẫn đang giữ endpoint cũ: {{lanes}}", "test": "Kiểm tra", "testing": "Đang kiểm tra…", "testOk": "Endpoint đã trả lời — {{model}} dùng được với key này.", "testFailed": "Không trả lời ({{status}}): {{message}}" } }