feat(settings): data-safe editors, deep-linked search, Data/About/Cost pages
- EditorModal loads once per path (a parent re-render no longer reloads the file over the user's typing), refuses Save after a failed load, opens a truncated (>256 KB) file read-only, and asks before overwriting a file that changed on disk or could not be re-read. - Settings/Hooks editors unset only keys from the snapshot taken at Edit, warn when the file changed underneath, keep a renamed key's value, and refuse a new key named like a redacted one (env) or a read-only hook event, which used to replace the secret/hooks. - Project scope shows its resolved folder and is disabled inside the plugin cache. Account-profile, pricing-row and pet deletes confirm; two-click actions disarm after 3 s; unsaved drafts ask before closing. - Search indexes every Claude Code / Codex sub-tab, opens it via ?tab= and scrolls to + highlights the row; the active config tab is in the URL. - General splits into General / Data / About; Pricing moves to a Cost group with one shared load; config tabs group as Content / Extensions / Config with arrow-key roving; Promise.allSettled per tab. - Data: browser-preferences export/import (allowlisted keys), per-section reset, housekeeping dry-run first, clear-all behind a typed phrase. Server: purge days must be a whole number >= 1 (INVALID_PURGE_DAYS) and dry_run returns exactly what the real run would delete. - Alerts can be edited; webhooks/alerts/remote-source failures toast; copies go through copyText; modals get dialog roles and useDialog. - Sagi: Ctrl/Cmd+B only when shown and not typing, default spot clear of row controls, arrow keys move it, reduced motion honoured; the dead /run launch link goes to the workspace.
This commit is contained in:
@@ -20,13 +20,46 @@
|
||||
"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…"
|
||||
"settings": "Cài đặt pet…",
|
||||
"hiddenToast": "Đã ẩn pet. Bật lại trong Cài đặt → Pet.",
|
||||
"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."
|
||||
"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": {
|
||||
@@ -62,8 +95,8 @@
|
||||
},
|
||||
"cacheWrite5m": "Ghi bộ nhớ đệm (5m)",
|
||||
"cacheWrite1h": "Ghi bộ nhớ đệm (1h)",
|
||||
"fastInput": "Fast Input",
|
||||
"fastOutput": "Fast Output",
|
||||
"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.",
|
||||
@@ -85,12 +118,17 @@
|
||||
}
|
||||
},
|
||||
"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."
|
||||
"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"
|
||||
"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",
|
||||
@@ -106,7 +144,16 @@
|
||||
"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"
|
||||
"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",
|
||||
@@ -127,7 +174,7 @@
|
||||
"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",
|
||||
"testTitle": "AgentHub",
|
||||
"title": "Thông báo",
|
||||
"turnComplete": "Claude trả lời xong",
|
||||
"sound": {
|
||||
@@ -140,7 +187,16 @@
|
||||
"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ử",
|
||||
@@ -230,7 +286,10 @@
|
||||
"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)"
|
||||
"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",
|
||||
@@ -238,7 +297,11 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"about": {
|
||||
"title": "Giới thiệu",
|
||||
@@ -322,7 +385,11 @@
|
||||
"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."
|
||||
"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",
|
||||
@@ -493,7 +560,8 @@
|
||||
"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"
|
||||
"remoteSourceBadgeTitle": "Được thu thập từ một máy từ xa",
|
||||
"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ộ).",
|
||||
"aiRouter": {
|
||||
@@ -579,7 +647,11 @@
|
||||
"darkThemes": "Theme tối",
|
||||
"lightThemes": "Theme sáng",
|
||||
"active": "· đang dùng",
|
||||
"default": "Mặc định"
|
||||
"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."
|
||||
},
|
||||
"gitCreds": {
|
||||
"title": "Git credentials",
|
||||
@@ -597,7 +669,9 @@
|
||||
"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"
|
||||
"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",
|
||||
@@ -660,7 +734,11 @@
|
||||
"missing": "File này chưa có",
|
||||
"save": "Lưu",
|
||||
"close": "Đóng",
|
||||
"saved": "Đã lưu. Bản sao lưu: {{backup}}"
|
||||
"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",
|
||||
@@ -669,12 +747,13 @@
|
||||
"general": "Chung",
|
||||
"agents": "Tác tử",
|
||||
"routing": "Định tuyến",
|
||||
"git": "Git"
|
||||
"git": "Git",
|
||||
"cost": "Chi phí"
|
||||
},
|
||||
"section": {
|
||||
"general": {
|
||||
"title": "Chung",
|
||||
"description": "Dọn dẹp workspace, dữ liệu và thông tin."
|
||||
"description": "Ngôn ngữ hiển thị của bảng điều khiển."
|
||||
},
|
||||
"appearance": {
|
||||
"title": "Giao diện",
|
||||
@@ -718,12 +797,23 @@
|
||||
"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."
|
||||
}
|
||||
}
|
||||
},
|
||||
"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}}”."
|
||||
"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",
|
||||
@@ -751,5 +841,15 @@
|
||||
"copyPath": "Sao chép đường dẫn",
|
||||
"enable": "Bật",
|
||||
"disable": "Tắt"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user