Files
AgentHub/client/src/i18n/locales/vi/settings.json
T
nntrivi2001 9a54978eef feat: v2.5.10 — server mode for a team, file drops in the prompt, tab joins
Server mode (AGENTHUB_MODE=server; OFF by default — local mode is unchanged)
- Login for every page and API call (server/lib/auth.js, routes/auth.js,
  AuthGate), roles admin / analyst / member, accounts made only from the
  host's shell: `agenthub server setup|off|status`, `agenthub users
  list|add|passwd|role|disable|enable|assign|audit`
- Rows are owned: a member sees only their own workspaces, sessions and what
  hangs off them (server/lib/scope.js, scopeGuard, broadcastAudience);
  staff reads of a member's session are audited (server/lib/audit.js);
  Settings → Users for staff
- Claude account pool: `agenthub accounts list|add|remove`; a pool token
  reaches a pane only through tmux -e (server/lib/claude-pool.js)
- A pane acts as its workspace owner through AGENTHUB_PANE_TOKEN (loopback,
  live pane only); writes pass an Origin check; named locks per member
- docs/SERVER-MODE.md, docs/plans/server-mode/

Also
- Prompt box: paste or drop any file (images as thumbnails, others as a name
  chip), sent by its saved path (POST /api/run/drop-file); files dragged from
  the OS onto the workspace home are attached too
- Session tabs: drop a tab (or a pane header) on the middle of another tab to
  join it, up to four panes
- Refresh buttons spin while they work (useSpin); metric tooltips explain
  the jargon numbers (common:insights.help.*)
- Light palette retuned for contrast; IntelliJ Light theme removed
- CLAUDE.md sync marker trimmed; its history moved to docs/CLAUDE-SYNC-LOG.md

Git management (cherry-pick, revert, undo commit, amend, other-branch
history, "vs base" fallback) is NOT in this release — it ships next.

Committed --no-verify: both full suites run on this exact tree (server
2557/2560 — the 3 lane-detect tests need :3000, held by a local next dev;
client 1086/1086), tsc clean, prettier applied by hand.
2026-10-07 14:11:25 +07:00

967 lines
54 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"title": "Cài đặt",
"subtitle": "Quản lý giao diện, công cụ AI, thông báo và dữ liệu",
"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ở)",
"pet": {
"title": "Pet",
"hide": "Ẩn pet",
"size": "Kích thước",
"choose": "Chọn pet",
"featuredBy": "Của {{by}} trên codex-pets.net — tải về máy này ở lần chọn đầu",
"download": "Tải về",
"delete": "Xoá {{name}}",
"upload": "Tải ảnh của bạn lên…",
"import": "Nhập bundle .codex-pet…",
"browse": "Tìm thêm trên codex-pets.net",
"settings": "Cài đặt pet…",
"hiddenToast": "Đã ẩn pet. Bật lại trong Cài đặt → Giao diện.",
"deleteTitle": "Xoá {{name}}?",
"deleteMessage": "Các tệp của pet sẽ bị xoá khỏi bản cài này. Pet nổi bật có thể tải lại; ảnh bạn tải lên sẽ mất hẳn.",
"deleteConfirm": "Xoá pet",
"reset": "Khôi phục mặc định",
"resetDone": "Đã khôi phục cài đặt pet về mặc định.",
"hiddenNote": "Pet đang ẩn — kích thước và bong bóng lời thoại sẽ áp dụng khi hiện lại.",
"resetMessage": "Hiện lại pet, bật bong bóng lời thoại, kích thước 68 px và dùng Sagi. Các pet bạn đã tải lên hoặc tải về vẫn được giữ.",
"previewCapped": "Bản xem trước vẽ ở 120 px; pet thật có kích thước {{size}} px."
},
"bubbles": "Bong bóng lời thoại",
"bubblesDesc": "Cho pet bình luận về các session của bạn trong bong bóng",
"sizeDesc": "{{min}}–{{max}} px; bản xem trước tối đa 120 px",
"chooseDesc": "Pet nổi bật lấy từ codex-pets.net và được tải về máy ở lần đầu bạn chọn. Lựa chọn và kích thước được lưu trong trình duyệt này.",
"uploadHint": "Ảnh (PNG, JPEG, GIF, WebP — không nhận SVG) hiển thị tĩnh; file .codex-pet.zip (pet.json + spritesheet.webp 1536×1872) chuyển động theo tâm trạng.",
"panel": {
"label": "Trợ lý Sagi",
"live": "Trực tuyến",
"offline": "Ngoại tuyến",
"close": "Đóng Sagi",
"statLive": "đang chạy",
"statWaiting": "đang chờ",
"statErrored": "lỗi",
"runClaude": "Chạy Claude",
"activity": "Hoạt động",
"sessions": "Phiên",
"errored": "Phiên lỗi",
"mute": "Tắt tiếng",
"unmute": "Bật tiếng",
"clearAlerts": "Xoá cảnh báo",
"askPlaceholder": "Hỏi Sagi… (vd: có lỗi nào không?)",
"ask": "Hỏi Sagi",
"send": "Gửi"
},
"bubbleDismiss": "Đóng",
"open": "Mở trợ lý Sagi",
"closeAvatar": "Đóng Sagi",
"avatarTitle": "Sagi — Ctrl/⌘+B · kéo hoặc dùng phím mũi tên để di chuyển · chuột phải để chọn pet",
"startFailed": "Không khởi động được phiên: {{error}}"
},
"pricing": {
"vendor": {
"claude": "Anthropic (Claude)",
"openai": "OpenAI (Codex)",
"google": "Google (Gemini)"
},
"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",
"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ó.",
"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.",
"synced": "Giá được điền tự động",
"syncedBody": "Mọi model Claude, OpenAI và Gemini hiện hành được lấy giá từ bảng giá công khai của LiteLLM, kiểm tra mỗi ngày một lần; model khác cũng có giá ngay khi một phiên dùng tới. Dòng có nhãn Tự động sẽ theo bảng giá đó khi giá thay đổi; dòng bạn sửa trở thành của bạn và không bao giờ bị ghi đè, dòng bạn xoá sẽ không quay lại. Phiên đã lưu giữ nguyên giá đã áp dụng lúc ghi nhận.",
"apiPricingOtherBody": "Đây là giá API trả theo mức dùng. Nếu bạn dùng CLI này theo gói thuê bao, chi phí thực là một khoản cố định chứ không tính theo token, nên các con số ở đây thường cao hơn số tiền bạn thực trả. Hãy xem chúng là ước tính mức dùng, không phải hoá đơn."
},
"cacheWrite5m": "Ghi bộ nhớ đệm (5m)",
"cacheWrite1h": "Ghi bộ nhớ đệm (1h)",
"fastInput": "Đầu vào nhanh",
"fastOutput": "Đầu ra nhanh",
"showAll": "Hiện mọi model (thêm {{count}})",
"empty": {
"claude": "Chưa có giá model Claude. Nút Khôi phục mặc định sẽ đưa chúng trở lại.",
"openai": "Chưa có giá model OpenAI. Giá được thêm tự động từ bảng giá LiteLLM khi một phiên Codex dùng model đó, hoặc bạn tự thêm.",
"google": "Chưa có giá model Gemini. Giá được thêm tự động từ bảng giá LiteLLM khi một phiên Antigravity dùng model đó, hoặc bạn tự thêm."
},
"placeholders": {
"claude": {
"pattern": "claude-opus-4%",
"name": "Claude Opus 4"
},
"openai": {
"pattern": "gpt-5%",
"name": "GPT 5"
},
"google": {
"pattern": "gemini-3.8-flash%",
"name": "Gemini 3.8 Flash"
}
},
"autoBadge": "Tự động",
"autoBadgeTitle": "Tự cập nhật theo giá công bố (bảng giá LiteLLM, kiểm tra mỗi ngày). Sửa dòng này để giữ giá của riêng bạn.",
"deleteConfirmTitle": "Xoá quy tắc giá {{pattern}}?",
"deleteConfirmBody": "Các phiên dùng mô hình này sẽ được tính giá theo quy tắc khớp khác, hoặc không được tính. Đồng bộ giá tự động sẽ KHÔNG thêm lại mẫu này; nếu đổi ý, hãy tự thêm lại."
},
"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.",
"placeholder": "/đường-dẫn/tới/claude-home",
"note": "Không có gì bị di chuyển hay sao chép: AgentHub chỉ bắt đầu đọc transcript, cấu hình và hook từ thư mục mới. Phiên Cursor dùng cùng đường dẫn ~/.claude nên cũng theo thư mục này.",
"confirmTitle": "Đổi CLAUDE_HOME?",
"confirmBody": "Từ giờ AgentHub sẽ đọc phiên, cấu hình, skill và hook từ thư mục mới. Các phiên trong thư mục cũ sẽ không được nhập nữa cho tới khi bạn đổi lại. Không có gì bị di chuyển hay xoá."
},
"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": "Workspace",
"description": "Dọn dẹp workspace trên toàn máy.",
"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",
"explain": "Dọn dẹp sau các phiên của không gian làm việc: dừng các tiến trình máy chủ MCP mà phiên đã kết thúc còn để lại, và cắt bớt tệp nhật ký quá lớn. Không đụng tới kho mã của bạn.",
"preview": "Xem trước dọn dẹp",
"gcReapLine": "dừng tiến trình còn sót {{pid}}",
"gcCapLine": "cắt bớt {{path}} ({{size}})",
"gcNothing": "Không có gì để dọn — không còn tiến trình sót và không có nhật ký quá lớn.",
"gcConfirmTitle": "Chạy dọn dẹp?",
"gcConfirmBody": "Thao tác này sẽ:",
"gcMore": "và {{count}} mục khác",
"gcPreviewResult": "Chạy thử: sẽ dừng {{reaped}} tiến trình và cắt bớt {{capped}} tệp nhật ký"
},
"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": "AgentHub",
"title": "Thông báo",
"turnComplete": "Claude trả lời xong",
"sound": {
"title": "Âm thanh",
"description": "Phát kèm mỗi thông báo được hiển thị. Mỗi loại bên dưới có thể chọn âm riêng.",
"preview": "Phát thử",
"useDefault": "Mặc định",
"none": "Không",
"chime": "Chuông",
"pop": "Pop",
"alert": "Cảnh báo",
"forType": "Âm thanh cho loại này"
},
"scopeNote": "Các cài đặt thông báo này chỉ lưu trong trình duyệt này. Quy tắc cảnh báo và webhook bên dưới áp dụng cho toàn máy chủ: mọi người dùng bảng điều khiển này đều chịu ảnh hưởng.",
"insecureOrigin": "Trang này được phục vụ từ {{origin}}, không phải nguồn bảo mật. Trình duyệt chỉ hiện thông báo trên HTTPS hoặc localhost — hãy mở bảng điều khiển qua một trong hai cách đó.",
"unsupported": "Trình duyệt này không hỗ trợ thông báo.",
"deniedHelp": "Thông báo đang bị chặn cho trang này. Để cho phép lại, mở cài đặt trang (biểu tượng bên trái thanh địa chỉ), đặt Thông báo thành Cho phép, rồi tải lại trang.",
"pushFailed": "Thông báo đã bật nhưng không thiết lập được push ({{message}}). Thông báo vẫn hiện khi thẻ này đang mở.",
"reset": "Khôi phục mặc định",
"resetTitle": "Khôi phục cài đặt thông báo?",
"resetBody": "Mọi loại thông báo và âm thanh trở về mặc định. Trạng thái bật/tắt thông báo được giữ nguyên.",
"resetDone": "Đã khôi phục cài đặt thông báo."
},
"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)",
"wholeNumber": "Nhập số nguyên từ 1 trở lên (hoặc để trống để bỏ qua).",
"cleanupConfirmTitle": "Chạy dọn dẹp phiên?",
"cleanupConfirmBody": "Thao tác này đánh dấu {{abandoned}} phiên cũ là bị bỏ dở và xóa vĩnh viễn {{sessions}} phiên cũ cùng {{events}} sự kiện và {{agents}} tác tử. Phiên đã xóa không thể khôi phục — hãy xuất dữ liệu trước nếu có thể cần."
},
"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",
"dialogTitle": "Xóa toàn bộ dữ liệu?",
"exportFirst": "Hãy xuất dữ liệu trước.",
"typeToConfirm": "Gõ “{{phrase}}” để xác nhận:",
"phrase": "xóa toàn bộ dữ liệu"
},
"autostart": {
"title": "Khởi động",
"label": "Tự động khởi động AgentHub",
"desc_systemd": "Chạy dashboard bằng systemd --user service để nó tự bật khi khởi động máy, không cần mở Claude Code. Tắt đi thì server đang chạy vẫn giữ nguyên.",
"desc_launchd": "Chạy dashboard bằng LaunchAgent để nó tự bật khi đăng nhập, không cần mở Claude Code. Tắt đi thì server đang chạy vẫn giữ nguyên.",
"unavailable": "Không khả dụng ở đây: cần systemd --user trên Linux, hoặc phiên đăng nhập GUI trên macOS.",
"foreign": "Đã có một service tên agenthub không do AgentHub tạo — AgentHub không đụng vào."
},
"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.",
"loadFailed": "Không tải được danh sách webhook: {{error}}",
"toggleFailed": "Không thay đổi được webhook: {{error}}",
"deleteFailed": "Không xoá được webhook: {{error}}",
"pickRule": "Hãy chọn ít nhất một quy tắc, hoặc chọn tất cả quy tắ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<token>/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",
"fieldSyncCodex": "Kéo cả phiên Codex",
"fieldRemoteCodexHome": "Thư mục Codex trên máy từ xa (tùy chọn)",
"fieldRemoteCodexHomeHint": "Mặc định ~/.codex (wsl:~/.codex khi thư mục Claude nằm trong WSL). Thư mục sessions/ của nó được sao chép về, và các phiên hiện ra như phiên Codex của nguồn này, kèm token và chi phí.",
"codexOn": "+ Codex",
"syncCodex": "{{n}} Codex",
"fieldLabelPlaceholder": "Máy dev"
},
"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ộ).",
"aiProxy": {
"title": "AI Proxy",
"description": "Ví dụ 9Router, OpenRouter hoặc gateway tự dựng. Lưu ở đây rồi chọn cho từng session ở ô nhập prompt của workspace.",
"add": "Thêm profile",
"edit": "Sửa",
"remove": "Xoá",
"empty": "Chưa lưu profile proxy 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 ô chọn AI Proxy của session. Gõ tự do.",
"fieldBaseUrl": "Base URL",
"fieldBaseUrlHint": "URL gốc của proxy, không có /v1 — ví dụ http://localhost:20128. Claude Code tự thêm /v1/messages, Codex tự thêm /v1/responses; /v1 bạn gõ vào sẽ được bỏ đi.",
"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 proxy chỉ cần một tên tượng trưng.",
"fieldBehavesAs": "Hoạt động như (Claude Code)",
"fieldBehavesAsHint": "Không bắt buộc. Model id của Claude mà Claude Code dùng để hiểu các tên model của proxy này (mặc định effort, context window), ví dụ claude-opus-5-5. Điền khi Claude Code báo một model không có trong model catalog của nó, và chọn đúng model proxy thật sự chuyển tới. Khi đã đặt, nó thay thiết lập modelPicker của bạn trong các phiên này.",
"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}}\"? Các file session của nó bị xoá theo, và một session từng chạy trên nó sẽ resume bằng API gốc của hãng.",
"loading": "Đang tải danh sách profile…",
"test": "Kiểm tra",
"testing": "Đang kiểm tra…",
"testOk": "đã trả lời — {{model}} dùng được với key này.",
"testFailed": "không trả lời ({{status}}): {{message}}"
},
"aiTools": {
"title": "AI Tools",
"description": "Các CLI lập trình AI mà AgentHub chạy được trong workspace. Nhận diện qua PATH của máy; tool bị tắt sẽ ẩn khỏi Thêm workspace.",
"installed": "Đã cài ({{count}} tool)",
"available": "Có thể cài ({{count}})",
"refresh": "Làm mới",
"noneInstalled": "Chưa tìm thấy AI tool nào trong PATH. Cài một tool rồi bấm Làm mới.",
"default": "Mặc định",
"setDefault": "Đặt mặc định",
"enabled": "Đang bật",
"disabled": "Đang tắt",
"enabledOf": "Bật {{tool}}",
"homepage": "Trang chủ",
"homepageOf": "Trang chủ {{tool}}",
"install": "Cài đặt",
"update": "Cập nhật",
"updateAll": "Cập nhật tất cả ({{count}})",
"runScript": "Tải {{url}} và chạy bằng bash",
"confirmInstall": "Cài {{tool}}?",
"confirmUpdate": "Cập nhật {{tool}}?",
"confirmUpdateAll": "Cập nhật các AI tool?",
"confirmBody": "AgentHub sẽ chạy trên máy này:",
"run": "Chạy",
"cancel": "Huỷ",
"jobRunning": "Đang chạy…",
"jobOk": "Xong",
"jobFailed": "Lỗi (exit {{code}})",
"showLog": "Xem log",
"hideLog": "Ẩn log"
},
"appearance": {
"title": "Giao diện",
"description": "Chế độ màu và theme. Chỉ lưu trong trình duyệt này.",
"mode": "Chế độ",
"modes": {
"dark": "Tối",
"light": "Sáng",
"system": "Theo hệ thống"
},
"darkThemes": "Theme tối",
"lightThemes": "Theme sáng",
"active": "· đang dùng",
"default": "Mặc định",
"reset": "Khôi phục mặc định",
"resetTitle": "Khôi phục giao diện?",
"resetBody": "Chế độ trở về Tối và cả hai chế độ trở về giao diện mặc định.",
"resetDone": "Đã khôi phục giao diện.",
"theme": "Theme",
"pet": "Pet",
"petDescription": "Linh vật ở góc màn hình: hiện/ẩn, kích thước, bong bóng lời thoại và pet đang dùng."
},
"gitCreds": {
"title": "Git credentials",
"description": "Mỗi host một tài khoản, dùng chung cho mọi người dùng AgentHub này. Token đã lưu sẽ không hiển thị lại.",
"add": "Thêm tài khoản",
"replace": "Thay token",
"remove": "Xoá",
"removeConfirm": "Xoá tài khoản git này? Fetch/pull/push tới host đó từ dashboard sẽ hỏi đăng nhập lại.",
"save": "Lưu",
"cancel": "Huỷ",
"fieldHost": "URL máy chủ",
"fieldUser": "Tên đăng nhập",
"fieldToken": "Mật khẩu hoặc access token",
"colHost": "Host",
"colUser": "Tên đăng nhập",
"colSaved": "Đã lưu",
"empty": "Chưa lưu tài khoản git nào. Thanh git sẽ hỏi khi một host cần đăng nhập.",
"badUrl": "Nhập máy chủ dạng URL, ví dụ https://git.example.com",
"saved": "Đã lưu thông tin đăng nhập cho {{host}}.",
"loading": "Đang tải…"
},
"homeDir": {
"save": "Lưu",
"saving": "Đang lưu...",
"current": "Hiện tại:",
"saveFailed": "Không lưu được thư mục",
"envOwned": "Biến này được đặt bởi môi trường lúc khởi động dashboard, hoặc bởi file .env của bản checkout, và nguồn đó luôn được ưu tiên mỗi lần khởi động: giá trị lưu ở đây chỉ giữ đến lần khởi động lại tiếp theo."
},
"codexHome": {
"title": "CODEX_HOME",
"description": "Thư mục gốc chứa config và nhật ký phiên của Codex. Dashboard đọc từ đây, ghi layer AI Proxy vào đây, và mở mọi workspace codex với thư mục này.",
"restartNote": "Workspace codex đang chạy vẫn dùng thư mục cũ, và hiện là idle, cho tới khi được khởi động lại.",
"placeholder": "/đường-dẫn/tới/codex-home"
},
"codexHooks": {
"title": "Hook của Codex",
"description": "Cho Codex báo về AgentHub trong lúc làm việc: từng lần gọi công cụ trong dòng thời gian của phiên, \"Codex cần bạn cho phép\" trên thẻ workspace và qua thông báo, và trạng thái chạy/nghỉ ngay khi một lượt bắt đầu hay kết thúc. Token và chi phí vẫn lấy từ nhật ký của Codex dù có hook hay không.",
"notInstalled": "Chưa cài",
"untrusted": "Đã cài — đang chờ bạn tin cậy trong Codex",
"trusted": "Đã cài và được tin cậy",
"trustNote": "Codex chỉ chạy một hook sau khi bạn tin cậy nó. Lần tới Codex khởi động, nó sẽ hỏi bạn xem lại các hook mới: chọn Trust all and continue (hoặc gõ /hooks). Trước đó Codex bỏ qua chúng.",
"install": "Cài đặt",
"reinstall": "Cài lại",
"refresh": "Làm mới",
"remove": "Gỡ bỏ",
"eventTrusted": "Đã được tin cậy trong Codex",
"eventUntrusted": "Chưa được tin cậy trong Codex",
"eventMissing": "Chưa cài",
"unsupported": "Hook của Codex từ AgentHub cần một shell POSIX nên không dùng được trên Windows.",
"unreadable": "AgentHub không đọc được {{path}}: {{error}}",
"failed": "Không đổi được hook của Codex: {{message}}"
},
"antigravityHooks": {
"title": "Hook của Antigravity",
"description": "Cho CLI của Antigravity (agy) báo về AgentHub trong lúc làm việc: từng lần gọi công cụ trong dòng thời gian của phiên, và trạng thái chạy/nghỉ ngay khi một lượt bắt đầu hay kết thúc. Token và chi phí vẫn lấy từ file hội thoại của agy dù có hook hay không.",
"notInstalled": "Chưa cài",
"installed": "Đã cài",
"disabled": "Đã cài nhưng đang tắt trong hooks.json",
"note": "agy nạp hook ở lần khởi động tiếp theo và không hỏi tin cậy. File này dùng chung, nên Antigravity IDE cũng chạy hook; AgentHub bỏ qua những gì IDE gửi. agy không có hook cho lời hỏi quyền, nên workspace Antigravity không thể hiện \"cần bạn cấp quyền\".",
"install": "Cài đặt",
"reinstall": "Cài lại",
"refresh": "Làm mới",
"remove": "Gỡ bỏ",
"eventInstalled": "Đã cài",
"eventMissing": "Chưa cài",
"unsupported": "Hook của Antigravity từ AgentHub cần một shell POSIX nên không dùng được trên Windows.",
"unreadable": "AgentHub không đọc được {{path}}: {{error}}",
"failed": "Không đổi được hook của Antigravity: {{message}}"
},
"toolTab": {
"update": "Cập nhật…",
"usage_one": "{{count}} phiên · ${{cost}}",
"usage_other": "{{count}} phiên · ${{cost}}",
"lanes": "Workspace:",
"defaultModel": "Model mặc định",
"defaultModelHint": "Model mà một session mới trên công cụ này dùng. Ô nhập prompt của workspace vẫn đổi được.",
"saveDefaultModel": "Lưu model mặc định",
"config": "File cấu hình",
"configHint": "Các file cấu hình của chính công cụ này. Khi lưu, cú pháp được kiểm tra, bản cũ được sao lưu vào thư mục dữ liệu của AgentHub, và sẽ không lưu nếu file đã đổi từ lúc mở.",
"missing": "File này chưa có",
"save": "Lưu",
"close": "Đóng",
"saved": "Đã lưu. Bản sao lưu: {{backup}}",
"defaultModelSaved": "Đã lưu mô hình mặc định.",
"staleBody": "Tệp đã thay đổi trên đĩa kể từ lúc bạn mở nên chưa lưu gì. Hãy sao chép bản của bạn nếu cần, rồi tải lại.",
"copyMine": "Sao chép bản của tôi",
"reloadDiscard": "Tải lại (bỏ bản của tôi)"
},
"settingsNav": {
"label": "Các mục cài đặt",
"back": "Quay lại Không gian làm việc",
"group": {
"general": "Chung",
"agents": "Tác tử",
"routing": "Định tuyến",
"git": "Git",
"cost": "Chi phí"
},
"section": {
"appearance": {
"title": "Giao diện",
"description": "Ngôn ngữ, chế độ màu và theme, và linh vật ở góc màn hình."
},
"notifications": {
"title": "Thông báo",
"description": "Thông báo trình duyệt, quy tắc cảnh báo và webhook."
},
"agents": {
"title": "AI tools",
"description": "Các CLI lập trình AI mà AgentHub chạy được: bật, đặt mặc định, cài và cập nhật."
},
"claudeCode": {
"title": "Claude Code",
"description": "Cấu hình của Claude Code và những gì AgentHub đọc từ đó."
},
"codex": {
"title": "Codex",
"description": "Cấu hình của Codex và những gì AgentHub đọc từ đó."
},
"tool": {
"description": "{{tool}}: đường dẫn, mức dùng, mô hình mặc định và file cấu hình."
},
"aiProxy": {
"title": "AI Proxy",
"description": "Các endpoint đứng trước Claude Code và Codex."
},
"pricing": {
"title": "Định giá",
"description": "Giá mô hình của mọi nhà cung cấp, dùng để ước tính chi phí. Đơn giá theo một triệu token (USD); % là ký tự đại diện trong mẫu; giá giới thiệu hiển thị màu tím."
},
"gitCredentials": {
"title": "Git credentials",
"description": "Thông tin đăng nhập AgentHub đưa cho git khi fetch, pull hoặc push từ dashboard."
},
"worktrees": {
"title": "Worktree",
"description": "Những git worktree chưa theo dõi được gợi ý khi thêm thư mục cho workspace."
},
"data": {
"title": "Dữ liệu",
"description": "Tổng quan chi phí và cơ sở dữ liệu, nhập, nguồn từ xa, xuất, dọn dẹp và vùng nguy hiểm."
},
"about": {
"title": "Giới thiệu",
"description": "Phiên bản máy chủ, thời gian hoạt động và môi trường chạy."
},
"snapshots": {
"title": "Snapshot",
"description": "Các bản sao chỉ đọc, đã đóng băng của phiên, mỗi bản có liên kết riêng."
},
"reports": {
"title": "Báo cáo",
"description": "Bản tóm tắt phân tích ghi ra theo lịch, dạng HTML hoặc JSON."
},
"users": {
"title": "Người dùng",
"description": "Tài khoản, mức dùng và nhật ký truy cập."
}
},
"backPrevious": "Quay lại",
"unknownSection": "Không có trang cài đặt “{{section}}” — đang hiển thị trang Chung."
},
"search": {
"placeholder": "Tìm cài đặt",
"noMatch": "Không có cài đặt nào khớp “{{query}}”.",
"results": "Kết quả tìm kiếm"
},
"worktrees": {
"title": "Gợi ý worktree",
"description": "Khi thêm thư mục cho một workspace, các worktree của repo chưa có workspace sẽ được gợi ý. Chỉ lưu trong trình duyệt này.",
"showUntracked": "Hiện worktree chưa theo dõi",
"showUntrackedDesc": "Gợi ý các worktree của repo chưa có workspace.",
"claude": "Worktree của Claude Code",
"claudeDesc": "Worktree dưới <repo>/.claude/worktrees/, do agent của Claude Code tạo.",
"agenthub": "Worktree do AgentHub quản lý",
"agenthubDesc": "Worktree AgentHub tạo dưới thư mục gốc workspace của nó."
},
"language": {
"title": "Ngôn ngữ",
"description": "Ngôn ngữ của toàn bộ dashboard, được ghi nhớ trong trình duyệt này.",
"label": "Ngôn ngữ giao diện",
"names": {
"en": "English",
"vi": "Tiếng Việt"
}
},
"rowMenu": {
"copyHost": "Sao chép host",
"copyUrl": "Sao chép endpoint",
"copyPattern": "Sao chép mẫu mô hình",
"copyPath": "Sao chép đường dẫn",
"enable": "Bật",
"disable": "Tắt"
},
"snapshots": {
"title": "Snapshot phiên",
"description": "Tạo từ trang của phiên bằng nút Snapshot. Chúng vẫn còn sau khi Xóa dữ liệu; xóa chúng ở đây.",
"empty": "Chưa có snapshot nào.",
"events": "{{n}} sự kiện",
"redacted": "Đã che đường dẫn",
"open": "Mở",
"copyLink": "Sao chép liên kết",
"delete": "Xóa",
"deleteTitle": "Xóa snapshot này?",
"deleteBody": "Liên kết của nó sẽ không dùng được nữa. Bản thân phiên không bị ảnh hưởng.",
"cancel": "Hủy"
},
"pushIngest": {
"title": "Đẩy dữ liệu về (push ingest)",
"description": "Cho máy mà dashboard không SSH tới được: máy đó tự đẩy hook của nó tới POST /api/hooks/ingest-batch bằng token tạo ở đây. Các phiên được gắn tên máy gửi lên (push:<tên>) và có trạng thái, sự kiện trực tiếp; chi phí token cần transcript, thứ chỉ nguồn SSH mang về.",
"on": "Đang bật — đã có token",
"off": "Đang tắt — chưa có token",
"create": "Tạo token",
"rotate": "Đổi token",
"revoke": "Thu hồi",
"rotateConfirm": "Tạo token mới? Token hiện tại ngừng hoạt động ngay.",
"revokeConfirm": "Thu hồi token và tắt push ingest?",
"shownOnce": "Hãy sao chép token này ngay: chỉ bản băm của nó được lưu, nên nó không bao giờ hiện lại.",
"copy": "Sao chép",
"envOwned": "AGENTHUB_PUSH_TOKEN_SHA256 được đặt bởi môi trường khởi động dashboard; hãy đổi nó ở đó.",
"reachHint": "Máy kia phải truy cập được dashboard này: khởi động với DASHBOARD_HOST (và DASHBOARD_ALLOWED_HOSTS cho tên của nó). Qua http thường, token đi trên mạng ở dạng đọc được — chỉ dùng trong mạng tin cậy, hoặc sau TLS. Script chuyển tiếp dưới đây giữ token trong một tệp header, không bao giờ trên dòng lệnh:",
"limits": "Tối đa 500 sự kiện và 1 MB mỗi yêu cầu. Hook cho phiên thuộc nguồn khác bị từ chối; đường dẫn transcript bị bỏ (chúng trỏ tới tệp trên máy gửi). Nhận hook Codex; không nhận hook Antigravity."
},
"privacy": {
"title": "Quyền riêng tư",
"description": "Những gì AgentHub giữ lại từ hook và lịch sử nhập vào. Cả hai mặc định tắt và chỉ áp dụng cho dữ liệu mới.",
"redact": "Che bí mật trước khi lưu",
"redactHint": "Khóa API và token có dạng đã biết, header bearer, khóa riêng và giá trị password=/TOKEN= trong payload và tóm tắt sự kiện được thay bằng [redacted]. Transcript trên đĩa là tệp của chính CLI và không bị thay đổi.",
"ignore": "Thư mục bỏ qua",
"ignoreHint": "Mỗi dòng một đường dẫn tuyệt đối. Hook từ các thư mục này, và mọi thứ bên trong, bị bỏ hoàn toàn; việc nhập lịch sử và bộ đọc Codex cũng bỏ qua phiên của chúng. AGENTHUB_IGNORE_CWD đặt cùng danh sách này.",
"envOwned": "Một giá trị ở đây do môi trường khởi động dashboard đặt, và không thể đổi từ trang này."
},
"reports": {
"title": "Báo cáo định kỳ",
"description": "Bản tóm tắt những ngày gần nhất — phiên, sự kiện, token, chi phí theo model và theo công cụ AI, công cụ dùng nhiều nhất, ngân sách — ghi ra HTML hoặc JSON theo lịch. Báo cáo và lịch sử chạy được giữ lại khi Xóa dữ liệu.",
"add": "Báo cáo mới",
"defaultName": "Tóm tắt hằng tuần",
"empty": "Chưa có báo cáo định kỳ nào.",
"name": "Tên",
"windowDays": "Số ngày",
"frequency": "Tần suất",
"daily": "Hằng ngày",
"weekly": "Hằng tuần",
"weekday": "Ngày",
"hour": "Giờ",
"windowHint": "Báo cáo gồm các ngày trọn vẹn trước ngày chạy, theo múi giờ của trình duyệt này.",
"save": "Lưu",
"cancel": "Hủy",
"enabled": "Bật",
"runNow": "Chạy ngay",
"history": "Lịch sử",
"edit": "Sửa",
"delete": "Xóa",
"everyDay": "Mỗi ngày lúc {{time}}",
"everyWeek": "Mỗi {{day}} lúc {{time}}",
"window_one": "{{count}} ngày gần nhất",
"window_other": "{{count}} ngày gần nhất",
"lastRun": "Lần chạy gần nhất {{at}}",
"noRuns": "Chưa chạy lần nào.",
"trigger": {
"schedule": "Theo lịch",
"manual": "Thủ công"
},
"download": "Tải {{format}}",
"deleteTitle": "Xóa báo cáo này?",
"deleteBody": "Lịch chạy, lịch sử chạy và các tệp nó đã ghi sẽ bị xóa."
},
"prefsBackup": {
"title": "Tùy chọn của trình duyệt này",
"description": "Giao diện, ngôn ngữ, cài đặt thông báo, thú cưng, thanh bên và bố cục không gian làm việc được lưu trong trình duyệt này. Lưu chúng ra tệp để chuyển sang trình duyệt khác, hoặc khôi phục từ tệp.",
"export": "Xuất tùy chọn",
"import": "Nhập tùy chọn…",
"importTitle": "Nhập tùy chọn?",
"importBody": "Tùy chọn trong tệp sẽ thay thế tùy chọn của trình duyệt này, sau đó trang tải lại.",
"imported": "Đã nhập {{count}} tùy chọn. Đang tải lại…",
"badFile": "Tệp này không phải tệp tùy chọn của AgentHub."
},
"users": {
"title": "Người dùng",
"description": "Mọi tài khoản trên server này, cùng workspace, session và mức dùng gần đây.",
"name": "Người dùng",
"role": "Vai trò",
"workspaces": "Workspace",
"sessions": "Session",
"last7d": "7 ngày",
"last30d": "30 ngày",
"disabled": "đã khoá",
"tokens": "{{n}} token",
"manageHint": "Thêm, khoá hoặc sửa người dùng trên máy chủ: agenthub users …",
"auditTitle": "Nhật ký truy cập",
"auditDescription": "Mỗi lần admin hoặc analyst mở một session của member.",
"auditEmpty": "Chưa có lượt đọc nào."
}
}