diff --git a/AGENTS.md b/AGENTS.md index 89a1686..636d13b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ donutbrowser/ │ ├── app/ # App router (page.tsx, layout.tsx) │ ├── components/ # 50+ React components (dialogs, tables, UI) │ ├── hooks/ # Event-driven React hooks -│ ├── i18n/locales/ # Translations (en, es, fr, ja, pt, ru, zh) +│ ├── i18n/locales/ # Translations (en, es, fr, ja, ko, pt, ru, vi, zh) │ ├── lib/ # Utilities (themes, toast, browser-utils) │ └── types.ts # Shared TypeScript interfaces ├── src-tauri/ # Rust backend (Tauri) @@ -66,12 +66,12 @@ donutbrowser/ - Never write user-facing strings as raw English literals in JSX, toast messages, dialog titles/descriptions, button labels, placeholders, table headers, tooltips, or empty-state text. Always go through `t("namespace.key")` from `useTranslation()`. - This applies to every component under `src/` — including new ones. If a component doesn't already import `useTranslation`, add it. -- Adding a new string means adding the key to ALL seven locale files in `src/i18n/locales/` (en, es, fr, ja, pt, ru, zh) — not just `en.json`. The English version alone is incomplete work. +- Adding a new string means adding the key to ALL nine locale files in `src/i18n/locales/` (en, es, fr, ja, ko, pt, ru, vi, zh) — not just `en.json`. The English version alone is incomplete work. - Reuse existing keys (`common.buttons.*`, `common.labels.*`, `createProfile.*`, etc.) before creating new namespaces. Check `en.json` first. - Strings excluded from this rule: `console.log/warn/error`, dev-only debug labels, internal IDs, CSS class names, type names. If unsure whether a string renders to the user, assume it does and translate it. - **Never use `t(key, "fallback")` with a default-value second argument.** The 2-arg form is forbidden — every key must exist in every locale file before the call site lands. Fallbacks mask missing translations: a key missing from `ru.json` will silently render the English fallback to Russian users, so the bug never surfaces in CI or review. Only call `t("namespace.key")`. If a translation is missing for any locale, that's a bug to fix at the JSON, not a hole to paper over at the call site. - Empty-string values in non-English locales are also forbidden — a locale either has the right translation or it has the same content as English; never `""`. If a particular language doesn't need a particular phrase (e.g. a suffix that doesn't grammatically apply), refactor the JSX to use a single interpolated key (`t("foo.bar", { name })` with `"...{{name}}..."` in each locale) instead of splitting prefix/suffix. -- When adding or removing keys across all seven locales, use a one-shot Python script in `/tmp/` that loads each `*.json`, mutates it, and writes it back. Seven sequential `Edit` calls drift (typos, ordering differences) and burn tokens; a single script keeps the locales in lockstep and is easy to throw away. +- When adding or removing keys across all nine locales, use a one-shot Python script in `/tmp/` that loads each `*.json`, mutates it, and writes it back. Nine sequential `Edit` calls drift (typos, ordering differences) and burn tokens; a single script keeps the locales in lockstep and is easy to throw away. ## Backend error codes (mandatory) @@ -85,7 +85,7 @@ User-facing errors returned from a Tauri command MUST be JSON `{ "code": "FOO_BA ``` 2. Add `"FOO_BAR"` to the `BackendErrorCode` union in `src/lib/backend-errors.ts`. 3. Add a `case "FOO_BAR":` in the switch that returns `t("backendErrors.fooBar", …)`. -4. Add `backendErrors.fooBar` to all seven locale files. +4. Add `backendErrors.fooBar` to all nine locale files. Raw error strings reach the user untranslated; that's the bug pattern this rule blocks. @@ -138,7 +138,7 @@ Reference implementations: `proxy-management-dialog.tsx`, `extension-management- All app-wide shortcuts live in `src/lib/shortcuts.ts`: -- `SHORTCUTS[]` — one entry per shortcut (id, label translation key, group, key, modifier flags). The label key must exist in all seven locales. +- `SHORTCUTS[]` — one entry per shortcut (id, label translation key, group, key, modifier flags). The label key must exist in all nine locales. - `formatShortcut(s)` returns platform-correct token strings (`["⌘", "K"]` on mac, `["Ctrl", "K"]` elsewhere) — used by both the shortcuts page and the command palette. - `matchesShortcut(s, event)` matches a real `KeyboardEvent` and rejects the wrong-platform modifier so Ctrl+K on macOS never fires a `mod: true` shortcut. - `matchesGroupDigit(event)` returns 1–9 if Mod+digit was pressed — group switching is dynamic (driven by `orderedGroupTargets` in `page.tsx`) and isn't in the `SHORTCUTS` table. @@ -148,7 +148,7 @@ Dispatch: the global `keydown` listener and the `runShortcut` callback both live 1. Append to `SHORTCUTS` in `src/lib/shortcuts.ts`. Add the `ShortcutId` variant. 2. Add a `case "yourId":` in `runShortcut` in `page.tsx`. 3. Add the icon mapping in `src/components/command-palette.tsx::ICONS`. -4. Add `shortcuts.yourId` (label) to all seven locale files. +4. Add `shortcuts.yourId` (label) to all nine locale files. The command palette (Mod+K) is built on the shadcn `Command` primitive with a token-AND fuzzy filter — `fuzzyFilter` in `command-palette.tsx`. The `CommandDialog` wrapper now forwards `filter`/`shouldFilter` to the inner `Command` for callers that need custom matching. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6659250..df55d38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,7 @@ codeql database analyze /tmp/codeql-rust --format=sarifv2.1.0 --output=/tmp/rust ## Key Rules -- **Translations**: Any UI text changes must be reflected in all 7 locale files (`src/i18n/locales/`) +- **Translations**: Any UI text changes must be reflected in all 9 locale files (`src/i18n/locales/`) - **Tauri commands**: If you modify Tauri commands, the `test_no_unused_tauri_commands` test will catch unused ones - **No hardcoded colors**: Use theme CSS variables (see `src/lib/themes.ts`), never Tailwind color classes like `text-red-500` - **No lock file changes**: Don't update `pnpm-lock.yaml` or `Cargo.lock` unless updating dependencies is the purpose of the PR diff --git a/src/components/settings-dialog.tsx b/src/components/settings-dialog.tsx index c2a8998..46f1fcb 100644 --- a/src/components/settings-dialog.tsx +++ b/src/components/settings-dialog.tsx @@ -483,7 +483,8 @@ export function SettingsDialog({ | "zh" | "ja" | "ko" - | "ru"), + | "ru" + | "vi"), ); setOriginalLanguage(selectedLanguage); } diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 35e2f8b..53893e3 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -8,6 +8,7 @@ import ja from "./locales/ja.json"; import ko from "./locales/ko.json"; import pt from "./locales/pt.json"; import ru from "./locales/ru.json"; +import vi from "./locales/vi.json"; import zh from "./locales/zh.json"; export const SUPPORTED_LANGUAGES = [ @@ -19,6 +20,7 @@ export const SUPPORTED_LANGUAGES = [ { code: "ja", name: "Japanese", nativeName: "日本語" }, { code: "ko", name: "Korean", nativeName: "한국어" }, { code: "ru", name: "Russian", nativeName: "Русский" }, + { code: "vi", name: "Vietnamese", nativeName: "Tiếng Việt" }, ] as const; export type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number]["code"]; @@ -36,6 +38,7 @@ export const LANGUAGE_FALLBACKS: Record = { "es-ES": ["es", "en"], "fr-CA": ["fr", "en"], "fr-FR": ["fr", "en"], + "vi-VN": ["vi", "en"], }; export function getLanguageWithFallback(systemLocale: string): string { @@ -65,6 +68,7 @@ const resources = { ja: { translation: ja }, ko: { translation: ko }, ru: { translation: ru }, + vi: { translation: vi }, }; i18n.use(initReactI18next).init({ diff --git a/src/i18n/locales/vi.json b/src/i18n/locales/vi.json new file mode 100644 index 0000000..1331598 --- /dev/null +++ b/src/i18n/locales/vi.json @@ -0,0 +1,1922 @@ +{ + "common": { + "buttons": { + "save": "Lưu", + "cancel": "Hủy", + "close": "Đóng", + "delete": "Xóa", + "create": "Tạo", + "back": "Quay lại", + "retry": "Thử lại", + "download": "Tải xuống", + "confirm": "Xác nhận", + "apply": "Áp dụng", + "reset": "Đặt lại", + "add": "Thêm", + "edit": "Chỉnh sửa", + "copy": "Sao chép", + "clear": "Xóa trắng", + "search": "Tìm kiếm", + "select": "Chọn", + "grant": "Cấp quyền", + "start": "Khởi động", + "stop": "Dừng", + "enable": "Bật", + "disable": "Tắt", + "import": "Nhập", + "export": "Xuất", + "refresh": "Làm mới", + "loading": "Đang tải...", + "saveSettings": "Lưu cài đặt", + "moreInfo": "Thêm thông tin", + "downloading": "Đang tải xuống...", + "minimize": "Thu nhỏ", + "saving": "Đang lưu…", + "saved": "Đã lưu", + "copied": "Đã sao chép" + }, + "status": { + "active": "Đang hoạt động", + "inactive": "Không hoạt động", + "running": "Đang chạy", + "stopped": "Đã dừng", + "enabled": "Đã bật", + "disabled": "Đã tắt", + "granted": "Đã cấp", + "notGranted": "Chưa cấp", + "connected": "Đã kết nối", + "disconnected": "Đã ngắt kết nối", + "synced": "Đã đồng bộ", + "syncing": "Đang đồng bộ", + "pending": "Đang chờ", + "error": "Lỗi" + }, + "labels": { + "name": "Tên", + "type": "Loại", + "status": "Trạng thái", + "actions": "Thao tác", + "description": "Mô tả", + "none": "Không có", + "default": "Mặc định", + "custom": "Tùy chỉnh", + "optional": "Tùy chọn", + "required": "Bắt buộc", + "unknownProfile": "Không xác định", + "mode": "Chế độ", + "never": "Không bao giờ" + }, + "time": { + "days": "ngày", + "hours": "giờ", + "minutes": "phút", + "seconds": "giây", + "remaining": "còn lại" + }, + "aria": { + "selectAll": "Chọn tất cả", + "selectRow": "Chọn hàng", + "selectProfile": "Chọn hồ sơ", + "copy": "Sao chép vào clipboard", + "copied": "Đã sao chép", + "showToken": "Hiện token", + "hideToken": "Ẩn token" + }, + "keys": { + "escape": "Escape" + }, + "errors": { + "unknown": "Đã xảy ra lỗi không xác định" + }, + "window": { + "minimize": "Thu nhỏ" + }, + "commandPalette": { + "title": "Bảng lệnh", + "description": "Tìm lệnh để chạy..." + }, + "noResults": "Không tìm thấy kết quả.", + "srOnly": { + "copy": "Sao chép", + "copied": "Đã sao chép" + } + }, + "settings": { + "title": "Cài đặt", + "appearance": { + "title": "Giao diện", + "theme": "Chủ đề", + "themeDescription": "Chọn chủ đề bạn muốn hoặc theo cài đặt hệ thống. Thay đổi chủ đề tùy chỉnh chỉ được áp dụng khi bạn lưu.", + "themePreset": "Mẫu chủ đề", + "customColors": "Tùy chỉnh màu sắc", + "selectTheme": "Chọn chủ đề", + "selectThemePreset": "Chọn mẫu chủ đề", + "yourOwn": "Của riêng bạn", + "light": "Sáng", + "dark": "Tối", + "system": "Theo hệ thống" + }, + "language": { + "title": "Ngôn ngữ", + "description": "Chọn ngôn ngữ hiển thị cho giao diện ứng dụng.", + "systemDefault": "Mặc định hệ thống", + "selectLanguage": "Chọn ngôn ngữ", + "interface": "Ngôn ngữ giao diện" + }, + "defaultBrowser": { + "title": "Trình duyệt mặc định", + "setAsDefault": "Đặt làm trình duyệt mặc định", + "alreadyDefault": "Đã là trình duyệt mặc định", + "description": "Khi được đặt làm mặc định, Donut Browser sẽ xử lý các liên kết web và cho phép bạn chọn hồ sơ để sử dụng." + }, + "permissions": { + "title": "Quyền hệ thống", + "loading": "Đang tải quyền...", + "description": "Các quyền này cho phép trình duyệt được khởi chạy từ Donut Browser truy cập tài nguyên hệ thống. Mỗi trang web vẫn sẽ yêu cầu quyền riêng lẻ.", + "microphone": "Micro", + "microphoneDescription": "Quyền truy cập micro cho ứng dụng trình duyệt", + "camera": "Camera", + "cameraDescription": "Quyền truy cập camera cho ứng dụng trình duyệt", + "accessRequested": "Yêu cầu quyền truy cập {{permission}}" + }, + "integrations": { + "title": "Tích hợp", + "description": "Cấu hình Local API và MCP (Model Context Protocol) để tích hợp với công cụ bên ngoài và trợ lý AI.", + "openSettings": "Mở cài đặt tích hợp" + }, + "encryption": { + "title": "Mã hóa đồng bộ", + "description": "Đặt mật khẩu để bật mã hóa đầu cuối (E2E) cho đồng bộ. Nếu mất mật khẩu này, các hồ sơ đã mã hóa sẽ không thể khôi phục.", + "passwordSet": "Đang hoạt động", + "passwordSetDescription": "Mật khẩu mã hóa E2E đã được thiết lập", + "noPassword": "Chưa đặt mật khẩu", + "passwordPlaceholder": "Mật khẩu (tối thiểu 8 ký tự)", + "confirmPlaceholder": "Xác nhận mật khẩu", + "setPassword": "Đặt mật khẩu", + "changePassword": "Đổi mật khẩu", + "removePassword": "Xóa mật khẩu", + "removed": "Đã xóa mật khẩu mã hóa", + "passwordSaved": "Đã thiết lập mật khẩu mã hóa", + "passwordMismatch": "Mật khẩu không khớp", + "passwordTooShort": "Mật khẩu phải có ít nhất 8 ký tự", + "requiresProOrOwner": "Mã hóa hồ sơ chỉ dành cho người dùng Pro và chủ nhóm.", + "validatePassword": "Xác thực", + "validateDialog": { + "title": "Xác thực mật khẩu mã hóa", + "description": "Nhập mật khẩu mã hóa để xác minh khớp với mật khẩu được lưu trên thiết bị này.", + "submit": "Xác thực", + "matchToast": "Mật khẩu chính xác", + "mismatchToast": "Mật khẩu không khớp" + } + }, + "commercial": { + "title": "Giấy phép thương mại", + "trialActive": "Dùng thử: còn {{days}} ngày, {{hours}} giờ", + "trialActiveDescription": "Sử dụng thương mại miễn phí trong thời gian dùng thử. Khi hết hạn, tất cả tính năng vẫn hoạt động — sử dụng cá nhân miễn phí, chỉ sử dụng thương mại mới cần giấy phép.", + "trialExpired": "Đã hết hạn dùng thử", + "trialExpiredDescription": "Sử dụng cá nhân vẫn miễn phí. Sử dụng thương mại cần giấy phép.", + "subscriptionActive": "Đã đăng ký — gói {{plan}}", + "subscriptionActiveDescription": "Đăng ký Donut Browser của bạn đang hoạt động. Sử dụng thương mại được cấp phép trong thời hạn gói." + }, + "advanced": { + "title": "Nâng cao", + "clearCache": "Xóa toàn bộ bộ nhớ đệm phiên bản", + "clearCacheDescription": "Xóa tất cả dữ liệu phiên bản trình duyệt đã lưu và làm mới từ nguồn. Thao tác này sẽ buộc tải lại thông tin phiên bản cho tất cả trình duyệt.", + "clearCacheFailed": "Xóa bộ nhớ đệm thất bại", + "copyLogs": "Sao chép nhật ký", + "openLogDir": "Mở thư mục nhật ký", + "copyLogsSuccess": "Đã sao chép nhật ký vào clipboard", + "copyLogsDescription": "Đóng gói các file nhật ký gần nhất (tối đa 5 MB) vào clipboard để chia sẻ trong báo cáo lỗi." + }, + "disableAutoUpdates": "Tắt tự động cập nhật ứng dụng", + "disableAutoUpdatesDescription": "Ngăn ứng dụng tự động kiểm tra và cài đặt bản cập nhật Donut Browser. Cập nhật trình duyệt không bị ảnh hưởng.", + "keepDecryptedProfilesInRam": "Giữ hồ sơ đã giải mã trong RAM", + "keepDecryptedProfilesInRamDescription": "Giữ bản sao đã giải mã trong RAM của hồ sơ được bảo vệ bằng mật khẩu giữa các lần khởi chạy để khởi động nhanh hơn. Bản sao trên ổ đĩa vẫn được mã hóa." + }, + "header": { + "searchPlaceholder": "Tìm kiếm hồ sơ...", + "clearSearch": "Xóa tìm kiếm", + "moreActions": "Thêm thao tác", + "createProfile": "Tạo hồ sơ mới", + "menu": { + "settings": "Cài đặt", + "proxies": "Proxy & VPN", + "groups": "Nhóm", + "syncService": "Tài khoản", + "integrations": "Tích hợp", + "importProfile": "Nhập hồ sơ", + "extensions": "Tiện ích mở rộng" + }, + "newProfile": "Mới", + "donutLogo": "Logo Donut Browser", + "scrollGroupsLeft": "Cuộn nhóm sang trái", + "scrollGroupsRight": "Cuộn nhóm sang phải" + }, + "profiles": { + "title": "Hồ sơ", + "empty": "Chưa có hồ sơ nào", + "emptyDescription": "Tạo hồ sơ trình duyệt đầu tiên để bắt đầu.", + "createFirst": "Tạo hồ sơ", + "noResults": "Không tìm thấy hồ sơ", + "noResultsDescription": "Không có hồ sơ nào khớp với tiêu chí tìm kiếm.", + "table": { + "name": "Tên", + "browser": "Trình duyệt", + "status": "Trạng thái", + "actions": "Thao tác", + "note": "Ghi chú", + "group": "Nhóm", + "proxy": "Proxy / VPN", + "lastLaunch": "Lần chạy cuối", + "empty": "Không tìm thấy hồ sơ.", + "notSelected": "Chưa chọn", + "ext": "TIỆN ÍCH", + "dns": "DNS", + "extDefault": "Mặc định", + "dnsLevel": "Danh sách chặn DNS: {{level}}", + "extSearch": "Tìm kiếm nhóm…", + "extEmpty": "Không có nhóm tiện ích" + }, + "actions": { + "launch": "Khởi chạy", + "stop": "Dừng", + "edit": "Chỉnh sửa", + "delete": "Xóa", + "copyCookies": "Sao chép Cookie", + "configure": "Cấu hình", + "clone": "Nhân bản hồ sơ", + "viewNetwork": "Xem mạng", + "syncSettings": "Cài đặt đồng bộ", + "assignToGroup": "Gán vào nhóm", + "changeFingerprint": "Đổi vân tay", + "copyCookiesToProfile": "Sao chép Cookie sang hồ sơ", + "launchHook": "URL Hook khởi chạy", + "setPassword": "Đặt mật khẩu", + "changePassword": "Đổi mật khẩu", + "removePassword": "Xóa mật khẩu" + }, + "synchronizer": { + "launchWithSync": "Khởi chạy với trình đồng bộ", + "stopLeader": "Dừng hồ sơ này và tất cả hồ sơ đi theo", + "stopFollower": "Đang đi theo hành động của {{leaderName}}", + "desyncedTooltip": "Đồng bộ thất bại tại {{url}}", + "paidFeature": "Trình đồng bộ là tính năng trả phí", + "wayfernOnly": "Chỉ hồ sơ Wayfern mới có thể đồng bộ", + "selectFollowers": "Chọn hồ sơ đi theo", + "selectFollowersDesc": "Chọn các hồ sơ sẽ phản chiếu hành động của hồ sơ dẫn đầu. Chỉ hồ sơ Wayfern đã dừng mới có thể chọn.", + "leader": "Dẫn đầu", + "follower": "Đi theo", + "startSession": "Bắt đầu phiên đồng bộ", + "noFollowers": "Chọn ít nhất một hồ sơ đi theo", + "flakyBadge": "KHÔNG ỔN ĐỊNH", + "flakyTooltip": "Hồ sơ này có độ phân giải màn hình khác với hồ sơ dẫn đầu. Bố cục trang có thể khác, khiến nhấp chuột và tương tác có thể sai lệch." + }, + "ephemeral": "Tạm thời", + "ephemeralDescription": "Trình duyệt buộc ghi dữ liệu hồ sơ vào bộ nhớ thay vì ổ đĩa. Lưu ý rằng hệ điều hành có thể chuyển một phần bộ nhớ sang ổ đĩa khi tải nặng, nên dấu vết của phiên vẫn có thể bị khôi phục.", + "ephemeralBadge": "Tạm thời", + "bulkDelete": { + "title": "Xóa các hồ sơ đã chọn", + "description": "Hành động này không thể hoàn tác. Thao tác này sẽ xóa vĩnh viễn {{count}} hồ sơ và tất cả dữ liệu liên quan.", + "confirmButton": "Xóa {{count}} hồ sơ" + }, + "note": { + "empty": "Không có ghi chú", + "placeholder": "Thêm ghi chú..." + }, + "aria": { + "profileInfo": "Thông tin hồ sơ" + }, + "delete": { + "title": "Xóa hồ sơ", + "description": "Hành động này không thể hoàn tác. Thao tác này sẽ xóa vĩnh viễn hồ sơ \"{{profileName}}\" và tất cả dữ liệu liên quan.", + "confirmButton": "Xóa hồ sơ" + }, + "actionBar": { + "assignToGroup": "Gán vào nhóm", + "assignProxy": "Gán Proxy", + "assignExtensionGroup": "Gán nhóm tiện ích", + "copyCookies": "Sao chép Cookie" + }, + "passwordProtectedBadge": "Được bảo vệ bằng mật khẩu", + "launchHook": { + "placeholder": "https://example.com/track-launch" + } + }, + "createProfile": { + "title": "Tạo hồ sơ mới", + "configureTitle": "Tạo hồ sơ {{browser}} mới", + "antiDetect": { + "title": "Trình duyệt chống phát hiện", + "description": "Chọn trình duyệt có khả năng chống phát hiện", + "chromium": "Wayfern", + "firefox": "Camoufox", + "badge": "Trình duyệt chống phát hiện" + }, + "regular": { + "title": "Trình duyệt thông thường", + "description": "Chọn từ các trình duyệt thông thường được hỗ trợ", + "badge": "Trình duyệt thông thường" + }, + "profileName": "Tên hồ sơ", + "profileNamePlaceholder": "Nhập tên hồ sơ", + "proxy": { + "title": "Proxy / VPN", + "addProxy": "Thêm Proxy", + "noProxy": "Không dùng proxy / VPN", + "noProxiesAvailable": "Chưa có proxy hoặc VPN nào. Hãy thêm một proxy để định tuyến lưu lượng của hồ sơ này.", + "search": "Tìm kiếm proxy hoặc VPN...", + "notFound": "Không tìm thấy proxy hoặc VPN.", + "searchWithCountries": "Tìm kiếm proxy, VPN hoặc quốc gia..." + }, + "launchHook": { + "label": "URL Hook khởi chạy", + "placeholder": "https://example.com/hooks/profile-launch" + }, + "version": { + "fetching": "Đang lấy danh sách phiên bản...", + "fetchError": "Không thể lấy danh sách phiên bản trình duyệt. Vui lòng kiểm tra kết nối mạng và thử lại.", + "needsDownload": "Phiên bản {{browser}} ({{version}}) cần được tải xuống", + "available": "Phiên bản {{browser}} ({{version}}) đã sẵn sàng", + "downloading": "Đang tải xuống {{browser}} phiên bản ({{version}})...", + "latestNeedsDownload": "Phiên bản mới nhất ({{version}}) cần được tải xuống", + "latestAvailable": "Phiên bản mới nhất ({{version}}) đã sẵn sàng", + "latestDownloading": "Đang tải xuống phiên bản ({{version}})..." + }, + "chromiumLabel": "Chromium", + "chromiumSubtitle": "Dựa trên Wayfern", + "firefoxLabel": "Firefox", + "firefoxSubtitle": "Dựa trên Camoufox", + "camoufoxWarning": "Firefox (Camoufox) được duy trì bởi bên thứ ba. Đối với sử dụng trong môi trường sản xuất, vui lòng dùng Chromium.", + "platformUnavailable": "{{browser}} chưa khả dụng trên nền tảng của bạn.", + "passwordProtect": { + "label": "Bảo vệ hồ sơ bằng mật khẩu", + "description": "Mã hóa dữ liệu hồ sơ trên ổ đĩa. Yêu cầu mật khẩu để khởi chạy." + } + }, + "deleteDialog": { + "title": "Xóa hồ sơ", + "description": "Bạn có chắc chắn muốn xóa hồ sơ này? Hành động này không thể hoàn tác.", + "profilesTitle": "Xóa hồ sơ", + "profilesDescription": "Bạn có chắc chắn muốn xóa các hồ sơ đã chọn? Hành động này không thể hoàn tác.", + "profilesToDelete": "Các hồ sơ sẽ bị xóa:" + }, + "proxies": { + "title": "Proxy", + "management": { + "description": "Quản lý cấu hình proxy và VPN để tái sử dụng giữa các hồ sơ", + "tabProxies": "Proxy", + "tabVpns": "VPN", + "create": "Tạo", + "loading": "Đang tải proxy...", + "noneCreated": "Chưa có proxy nào. Tạo proxy đầu tiên bằng nút phía trên.", + "usage": "Sử dụng", + "syncCol": "Đồng bộ", + "syncCannotDisable": "Không thể tắt đồng bộ khi proxy này đang được sử dụng bởi các hồ sơ đã đồng bộ", + "enableSync": "Bật đồng bộ", + "disableSync": "Tắt đồng bộ", + "editProxy": "Chỉnh sửa proxy", + "deleteProxy": "Xóa proxy", + "cannotDelete_one": "Không thể xóa: đang được {{count}} hồ sơ sử dụng", + "cannotDelete_other": "Không thể xóa: đang được {{count}} hồ sơ sử dụng", + "syncEnabled": "Đã bật đồng bộ", + "syncDisabled": "Đã tắt đồng bộ", + "updateSyncFailed": "Cập nhật đồng bộ thất bại", + "deleteSuccess": "Đã xóa proxy thành công", + "deleteFailed": "Xóa proxy thất bại", + "deleteTitle": "Xóa proxy", + "deleteDescription": "Hành động này không thể hoàn tác. Thao tác này sẽ xóa vĩnh viễn proxy \"{{name}}\".", + "newProxy": "Proxy mới", + "newVpn": "VPN mới", + "protocolCol": "Giao thức", + "title": "Proxy & VPN" + }, + "add": "Thêm Proxy", + "edit": "Chỉnh sửa Proxy", + "delete": "Xóa Proxy", + "import": "Nhập", + "export": "Xuất", + "noProxies": "Chưa cấu hình proxy", + "noProxiesDescription": "Thêm proxy để định tuyến lưu lượng trình duyệt qua đó.", + "form": { + "name": "Tên", + "namePlaceholder": "Nhập tên proxy", + "type": "Loại", + "host": "Host", + "hostPlaceholder": "proxy.example.com", + "port": "Cổng", + "portPlaceholder": "8080", + "username": "Tên đăng nhập", + "usernamePlaceholder": "Tùy chọn", + "password": "Mật khẩu", + "passwordPlaceholder": "Tùy chọn", + "cipher": "Cipher", + "cipherPlaceholder": "aes-256-gcm", + "nameRequired": "Tên proxy là bắt buộc", + "hostPortRequired": "Host và cổng là bắt buộc", + "ssCipherRequired": "Cipher và mật khẩu là bắt buộc cho Shadowsocks", + "selectType": "Chọn loại proxy", + "saveFailed": "Lưu proxy thất bại: {{error}}" + }, + "types": { + "http": "HTTP", + "https": "HTTPS", + "socks4": "SOCKS4", + "socks5": "SOCKS5", + "ss": "Shadowsocks" + }, + "tabs": { + "regular": "Thông thường", + "dynamic": "Động" + }, + "dynamic": { + "description": "Proxy động lấy thông tin kết nối từ URL mỗi khi hồ sơ được khởi chạy.", + "url": "URL Proxy", + "urlPlaceholder": "https://api.example.com/proxy", + "urlRequired": "URL proxy động là bắt buộc", + "format": "Định dạng phản hồi", + "formatJson": "JSON", + "formatText": "Văn bản", + "formatJsonHint": "Yêu cầu JSON: {\"ip\": \"...\", \"port\": ..., \"username\": \"...\", \"password\": \"...\"}", + "formatTextHint": "Yêu cầu văn bản dạng: host:port:username:password hoặc protocol://user:pass@host:port", + "testUrl": "Kiểm tra URL", + "testing": "Đang kiểm tra...", + "testSuccess": "Proxy hoạt động: {{host}}:{{port}}", + "testFailed": "Kiểm tra proxy thất bại: {{error}}", + "fetchFailed": "Không thể lấy proxy động: {{error}}" + }, + "check": { + "checking": "Đang kiểm tra proxy...", + "valid": "Proxy hợp lệ", + "invalid": "Proxy không hợp lệ", + "lastChecked": "Kiểm tra lần cuối: {{time}}" + }, + "sync": { + "enabled": "Đã bật đồng bộ", + "disabled": "Đã tắt đồng bộ" + }, + "exportDialog": { + "title": "Xuất proxy", + "description": "Xuất cấu hình proxy của bạn ra file", + "format": "Định dạng xuất", + "json": "JSON", + "txt": "TXT (định dạng URL)", + "preview": "Xem trước", + "noProxies": "Không có proxy để xuất", + "downloaded": "Đã tải xuống {{filename}}", + "failed": "Xuất proxy thất bại", + "copied": "Đã sao chép" + }, + "importDialog": { + "title": "Nhập proxy", + "descDropzone": "Nhập proxy từ file JSON hoặc TXT", + "descPreview": "Xem lại các proxy sẽ nhập", + "descAmbiguous": "Một số proxy có định dạng không rõ ràng. Vui lòng chọn định dạng đúng.", + "descResult": "Nhập hoàn tất", + "dropzonePrompt": "Thả file cấu hình proxy vào đây", + "dropzoneFormats": "(.json, .txt)", + "pasteHint": "Dán từ clipboard bằng {{modKey}}+V", + "wrongFileType": "Vui lòng thả file .json hoặc .txt", + "fileReadError": "Đọc file thất bại", + "fileProcessError": "Xử lý file thất bại", + "noValidProxies": "Không tìm thấy proxy hợp lệ trong file", + "namePrefix": "Tiền tố tên", + "namePrefixDefault": "Đã nhập", + "namePrefixHint": "Các proxy sẽ được đặt tên \"{{prefix}} Proxy 1\", \"{{prefix}} Proxy 2\", v.v.", + "proxiesToImport": "Proxy sẽ nhập ({{count}})", + "invalidCount": "({{count}} không hợp lệ)", + "ambiguousIntro": "Các proxy sau có định dạng không rõ ràng. Vui lòng chọn cách diễn giải đúng cho từng proxy.", + "imported": "Đã nhập:", + "skippedDuplicates": "Bỏ qua (trùng lặp):", + "errors": "Lỗi", + "importButton": "Nhập {{count}} proxy", + "continueButton": "Tiếp tục", + "doneButton": "Hoàn tất", + "failed": "Nhập proxy thất bại" + }, + "bulkDelete": { + "proxiesTitle": "Xóa các proxy đã chọn", + "proxiesDescription": "Hành động này không thể hoàn tác. Thao tác này sẽ xóa vĩnh viễn {{count}} proxy: {{names}}.", + "vpnsTitle": "Xóa các VPN đã chọn", + "vpnsDescription": "Hành động này không thể hoàn tác. Thao tác này sẽ xóa vĩnh viễn {{count}} VPN: {{names}}.", + "confirmButton": "Xóa {{count}}" + } + }, + "groups": { + "title": "Nhóm", + "management": "Quản lý nhóm", + "add": "Thêm nhóm", + "edit": "Chỉnh sửa nhóm", + "delete": "Xóa nhóm", + "moveToDefault": "Xóa profile khỏi nhóm", + "noGroupDescription": "Profile không thuộc nhóm nào sẽ hiển thị trong bộ lọc \"Tất cả\".", + "assignSuccess": "Đã gán thành công {{count}} profile vào {{group}}", + "noGroups": "Chưa tạo nhóm nào", + "noGroupsDescription": "Tạo một nhóm để sắp xếp các profile của bạn.", + "form": { + "name": "Tên", + "namePlaceholder": "Nhập tên nhóm" + }, + "profileCount": "{{count}} profile", + "profileCount_plural": "{{count}} profile", + "assignProfiles": "Gán profile", + "sync": { + "enabled": "Đã bật đồng bộ", + "disabled": "Đã tắt đồng bộ" + }, + "createTitle": "Tạo nhóm mới", + "createDescription": "Tạo một nhóm mới để sắp xếp các profile trình duyệt của bạn.", + "editTitle": "Chỉnh sửa nhóm", + "editDescription": "Cập nhật tên nhóm của bạn.", + "createSuccess": "Tạo nhóm thành công", + "createFailed": "Tạo nhóm thất bại", + "updateSuccess": "Cập nhật nhóm thành công", + "updateFailed": "Cập nhật nhóm thất bại", + "deleteTitle": "Xóa nhóm", + "deleteDescription": "Hành động này không thể hoàn tác. Nhóm sẽ bị xóa vĩnh viễn.", + "deleteSuccess": "Xóa nhóm thành công", + "deleteFailed": "Xóa nhóm thất bại", + "loadingProfiles": "Đang tải profile liên kết...", + "associatedProfiles": "Profile liên kết ({{count}})", + "whatToDoWithProfiles": "Những profile này sẽ như thế nào?", + "deleteAlongWithGroup": "Xóa profile cùng với nhóm", + "noAssociatedProfiles": "Nhóm này không có profile liên kết nào.", + "deleteGroup": "Xóa nhóm", + "deleteGroupAndProfiles": "Xóa nhóm và profile", + "loadProfilesFailed": "Tải profile thất bại", + "unknownGroup": "Nhóm không xác định", + "profileGroupsAriaLabel": "Nhóm profile", + "loading": "Đang tải nhóm...", + "all": "Tất cả", + "noGroup": "Không có nhóm", + "pageTitle": "Nhóm profile", + "pageDescription": "Nhóm profile giúp bạn sắp xếp trình duyệt theo khách hàng, môi trường hoặc mục đích sử dụng. Đồng bộ nhóm giữa các thiết bị để chia sẻ." + }, + "sync": { + "mode": { + "title": "Đồng bộ profile", + "description": "Quản lý cài đặt đồng bộ cho \"{{name}}\"", + "disabled": "Tắt", + "regular": "Đồng bộ thường", + "encrypted": "Đồng bộ mã hóa E2E", + "disabledDescription": "Không đồng bộ profile này", + "regularDescription": "Đồng bộ nhanh, không mã hóa", + "encryptedDescription": "Mã hóa trước khi tải lên. Máy chủ không bao giờ thấy dữ liệu dạng văn bản thuần.", + "noPasswordWarning": "Chưa đặt mật khẩu E2E. Vui lòng đặt mật khẩu trong Cài đặt.", + "passwordRequired": "Chưa đặt mật khẩu E2E. Vui lòng đặt mật khẩu trong Cài đặt trước.", + "enabledToast": "Đã bật đồng bộ", + "disabledToast": "Đã tắt đồng bộ", + "syncQueued": "Đã đưa đồng bộ vào hàng đợi", + "syncNow": "Đồng bộ ngay", + "lastSynced": "Lần đồng bộ cuối", + "notConfigured": "Chưa cấu hình dịch vụ đồng bộ.", + "configureService": "Cấu hình dịch vụ đồng bộ" + }, + "title": "Tài khoản", + "config": { + "serverUrlRequired": "Vui lòng nhập URL máy chủ", + "connectionSuccess": "Kết nối thành công!", + "serverError": "Máy chủ trả về lỗi", + "connectFailed": "Kết nối máy chủ thất bại", + "settingsSaved": "Đã lưu cài đặt đồng bộ", + "saveFailed": "Lưu cài đặt thất bại", + "disconnected": "Đã ngắt kết nối đồng bộ", + "disconnectFailed": "Ngắt kết nối thất bại" + }, + "serverUrl": "URL máy chủ", + "serverUrlPlaceholder": "https://sync.example.com", + "token": "Token đồng bộ", + "tokenPlaceholder": "Nhập token đồng bộ của bạn", + "status": { + "connected": "Đã kết nối", + "disconnected": "Đã ngắt kết nối", + "syncing": "Đang đồng bộ...", + "error": "Lỗi đồng bộ" + }, + "description": "Kết nối với máy chủ đồng bộ để đồng bộ profile, proxy và nhóm giữa các thiết bị.", + "cloud": { + "tabLabel": "Đám mây", + "selfHostedTabLabel": "Tự lưu trữ", + "email": "Email", + "deviceLinkInstructions": "Nhấn \"Đăng nhập\" để mở trang đăng nhập trong trình duyệt. Sau khi đăng nhập, sao chép mã hiển thị và dán vào bên dưới.", + "openLogin": "Đăng nhập", + "linkCodeLabel": "Mã đăng nhập", + "linkCodePlaceholder": "Dán mã từ trang web", + "signInTitle": "Đăng nhập", + "verifyAndLogin": "Xác minh và đăng nhập", + "loggingIn": "Đang đăng nhập...", + "connected": "Đã kết nối", + "plan": "Gói", + "profiles": "Profile", + "profileUsage": "{{used}} / {{limit}}", + "manageAccount": "Quản lý tài khoản", + "logout": "Đăng xuất", + "logoutConfirm": "Bạn có chắc muốn đăng xuất? Đồng bộ đám mây sẽ dừng lại.", + "loginSuccess": "Đăng nhập thành công!", + "logoutSuccess": "Đăng xuất thành công." + }, + "team": { + "title": "Nhóm", + "name": "Tên nhóm", + "role": "Vai trò", + "roleOwner": "Chủ sở hữu", + "roleAdmin": "Quản trị viên", + "roleMember": "Thành viên", + "manageOnWeb": "Quản lý nhóm trên bảng điều khiển web", + "profileLocked": "Đang được sử dụng bởi {{email}}", + "profileLockedShort": "Đang sử dụng", + "cannotLaunchLocked": "Không thể khởi chạy — profile đang được sử dụng bởi {{email}}", + "createdBy": "Được tạo bởi {{email}}" + }, + "disabled": "Tắt", + "toast": { + "profileSynced": "Đã đồng bộ profile '{{name}}' thành công", + "profileSyncFailed": "Đồng bộ profile '{{name}}' thất bại", + "profileSyncFailedWithError": "Đồng bộ profile '{{name}}' thất bại: {{error}}" + } + }, + "integrations": { + "title": "Tích hợp", + "api": { + "title": "API cục bộ", + "description": "Bật máy chủ API cục bộ để tích hợp bên ngoài.", + "enabled": "Đã bật API", + "disabled": "Đã tắt API", + "port": "Cổng", + "token": "Token API", + "copyToken": "Sao chép token", + "regenerateToken": "Tạo lại token" + }, + "mcp": { + "title": "Máy chủ MCP", + "description": "Bật máy chủ MCP (Model Context Protocol) để tích hợp trợ lý AI.", + "enabled": "Đã bật MCP", + "disabled": "Đã tắt MCP", + "port": "Cổng", + "token": "Token xác thực", + "tokenCopied": "Đã sao chép token", + "url": "URL máy chủ MCP", + "urlCopied": "Đã sao chép URL", + "config": "Cấu hình MCP", + "copyConfig": "Sao chép cấu hình", + "clientsLabel": "Ứng dụng khách", + "connected": "Đã kết nối", + "add": "Thêm", + "addedToClient": "Đã thêm vào {{name}}", + "removedFromClient": "Đã xóa khỏi {{name}}", + "removeAriaLabel": "Xóa khỏi {{name}}", + "category": { + "desktopApp": "Ứng dụng desktop", + "cli": "CLI", + "editor": "Trình soạn thảo", + "editorExt": "Tiện ích editor" + } + }, + "tabApi": "API cục bộ", + "tabMcp": "MCP (Trợ lý AI)", + "apiEnableLabel": "Bật máy chủ API cục bộ", + "apiEnableDescription": "Cho phép quản lý profile, nhóm và proxy qua REST API.", + "apiPortLabel": "Cổng", + "apiTokenLabel": "Token xác thực", + "apiTokenHint": "Thêm vào header Authorization: Bearer {{tokenSlot}}", + "apiInvalidPort": "Cổng không hợp lệ", + "apiInvalidPortDescription": "Cổng phải từ 1 đến 65535", + "apiPortInUse": "Cổng {{port}} đang được sử dụng", + "apiFallbackPort": "Máy chủ đã khởi động ở cổng dự phòng {{port}}", + "apiStarted": "Máy chủ API đã khởi động trên cổng {{port}}", + "apiRunning": "Máy chủ API đang chạy trên cổng {{port}}", + "apiStopped": "Máy chủ API đã dừng", + "apiToggleFailed": "Bật/tắt máy chủ API thất bại", + "apiStartFailed": "Khởi động máy chủ API thất bại", + "apiUnknownError": "Lỗi không xác định", + "tokenCopied": "Đã sao chép token", + "mcpEnableLabel": "Bật máy chủ MCP (Model Context Protocol)", + "mcpEnableDescription": "Cho phép trợ lý AI như Claude Desktop điều khiển trình duyệt.", + "mcpAcceptTermsFirst": "(Chấp nhận điều khoản Wayfern trong Cài đặt trước)", + "mcpStarted": "Máy chủ MCP đã khởi động trên cổng {{port}}", + "mcpStopped": "Máy chủ MCP đã dừng", + "mcpToggleFailed": "Bật/tắt máy chủ MCP thất bại", + "openSettings": "Mở cài đặt tích hợp", + "apiRunningOn": "Đang chạy trên", + "apiExampleRequest": "Ví dụ yêu cầu" + }, + "import": { + "title": "Nhập profile", + "description": "Nhập một profile trình duyệt hiện có từ hệ thống của bạn.", + "selectProfile": "Chọn profile để nhập", + "noProfiles": "Không phát hiện profile nào", + "noProfilesDescription": "Không phát hiện profile trình duyệt nào trên hệ thống của bạn.", + "importing": "Đang nhập profile...", + "success": "Nhập profile thành công", + "error": "Nhập profile thất bại" + }, + "config": { + "camoufox": { + "title": "Cấu hình Camoufox", + "fingerprint": { + "title": "Vân tay", + "randomize": "Tạo ngẫu nhiên khi khởi chạy", + "randomizeDescription": "Tạo vân tay mới mỗi khi khởi chạy trình duyệt.", + "osCpuPlaceholder": "ví dụ: Intel Mac OS X 10.15", + "webglRendererPlaceholder": "ví dụ: llvmpipe, hoặc tương tự" + }, + "os": { + "title": "Hệ điều hành", + "description": "Hệ điều hành mô phỏng để tạo vân tay.", + "windows": "Windows", + "macos": "macOS", + "linux": "Linux" + }, + "screen": { + "title": "Kích thước màn hình", + "minWidth": "Chiều rộng tối thiểu", + "maxWidth": "Chiều rộng tối đa", + "minHeight": "Chiều cao tối thiểu", + "maxHeight": "Chiều cao tối đa" + }, + "geoip": { + "title": "GeoIP", + "auto": "Tự động (dựa trên proxy)", + "manual": "Thủ công", + "disabled": "Tắt" + }, + "blocking": { + "title": "Chặn", + "images": "Chặn hình ảnh", + "webrtc": "Chặn WebRTC", + "webgl": "Chặn WebGL" + } + }, + "wayfern": { + "title": "Cấu hình Wayfern", + "fingerprint": { + "title": "Vân tay", + "randomize": "Tạo ngẫu nhiên khi khởi chạy", + "randomizeDescription": "Tạo vân tay mới mỗi khi khởi chạy trình duyệt.", + "platformPlaceholder": "ví dụ: Win32, MacIntel, Linux x86_64", + "timezoneOffsetPlaceholder": "ví dụ: 300 cho EST (UTC-5)", + "webglRendererPlaceholder": "ví dụ: Intel(R) HD Graphics" + }, + "os": { + "title": "Hệ điều hành", + "description": "Hệ điều hành mô phỏng để tạo vân tay.", + "windows": "Windows", + "macos": "macOS", + "linux": "Linux", + "android": "Android", + "ios": "iOS" + }, + "screen": { + "title": "Kích thước màn hình", + "minWidth": "Chiều rộng tối thiểu", + "maxWidth": "Chiều rộng tối đa", + "minHeight": "Chiều cao tối thiểu", + "maxHeight": "Chiều cao tối đa" + }, + "blocking": { + "title": "Chặn", + "webrtc": "Chặn WebRTC", + "webgl": "Chặn WebGL" + } + }, + "shared": { + "browserBehavior": "Hành vi trình duyệt", + "allowAddonsOpenTabs": "Cho phép tiện ích trình duyệt tự động mở tab mới" + } + }, + "cookies": { + "title": "Cookie", + "copy": { + "title": "Sao chép cookie", + "description": "Chọn cookie để sao chép sang profile khác.", + "selectSource": "Chọn profile nguồn", + "selectTarget": "Chọn profile đích", + "selectCookies": "Chọn cookie", + "allDomains": "Tất cả tên miền", + "selectedCount": "Đã chọn {{count}} cookie", + "selectedCount_plural": "Đã chọn {{count}} cookie", + "dialogDescription_one": "Sao chép cookie từ profile nguồn sang {{count}} profile đã chọn.", + "dialogDescription_other": "Sao chép cookie từ profile nguồn sang {{count}} profile đã chọn.", + "sourceProfile": "Profile nguồn", + "sourcePlaceholder": "Chọn profile để sao chép cookie từ", + "running": "(đang chạy)", + "targetProfiles": "Profile đích ({{count}})", + "noOtherTargets": "Chưa chọn profile Wayfern/Camoufox nào khác", + "selectSourceFirst": "Hãy chọn profile nguồn trước", + "selectionStatus": "(đã chọn {{selected}}/{{total}})", + "searchPlaceholder": "Tìm kiếm tên miền hoặc cookie...", + "noMatching": "Không tìm thấy cookie khớp", + "noFound": "Không tìm thấy cookie nào", + "replaceNote": "Cookie hiện có cùng tên và tên miền sẽ bị thay thế. Các cookie khác sẽ được giữ nguyên.", + "cannotCopyRunningOne": "Không thể sao chép cookie: {{names}} vẫn đang chạy", + "cannotCopyRunningMany": "Không thể sao chép cookie: {{names}} vẫn đang chạy", + "someErrors": "Đã xảy ra một số lỗi: {{errors}}", + "successMessage": "Đã sao chép thành công {{copied}} cookie (đã thay thế {{replaced}})", + "failedMessage": "Sao chép cookie thất bại: {{error}}", + "copyButton_one": "Sao chép {{count}} cookie", + "copyButton_other": "Sao chép {{count}} cookie", + "copyButtonEmpty": "Sao chép cookie" + }, + "success": "Sao chép cookie thành công", + "error": "Sao chép cookie thất bại", + "management": { + "title": "Quản lý cookie", + "menuItem": "Quản lý cookie", + "tabImport": "Nhập", + "tabExport": "Xuất", + "importDescription": "Nhập cookie từ tệp định dạng Netscape hoặc JSON.", + "dropPrompt": "Nhấn để chọn tệp cookie", + "fileFormats": "(.txt, .cookies, hoặc .json)", + "cookiesFound": "Tìm thấy {{count}} cookie", + "importedSuccess": "Đã nhập thành công {{imported}} cookie (đã thay thế {{replaced}})", + "linesSkipped": "Đã bỏ qua {{count}} dòng", + "fileReadError": "Đọc tệp thất bại", + "loadFailed": "Tải cookie thất bại: {{error}}", + "cookiesLabel": "Cookie", + "selectionStatus": "(đã chọn {{selected}}/{{total}})", + "selectAll": "Chọn tất cả", + "deselectAll": "Bỏ chọn tất cả", + "noCookies": "Không tìm thấy cookie trong profile này", + "doneButton": "Xong", + "importButton": "Nhập", + "exportButton": "Xuất", + "backButton": "Quay lại" + }, + "import": { + "title": "Nhập cookie", + "description": "Nhập cookie từ tệp định dạng Netscape hoặc JSON.", + "selectFile": "Chọn tệp", + "preview": "Tìm thấy {{count}} cookie", + "success": "Đã nhập thành công {{imported}} cookie (đã thay thế {{replaced}})", + "error": "Nhập cookie thất bại", + "proFeature": "Nhập cookie là tính năng Pro" + }, + "export": { + "title": "Xuất cookie", + "description": "Xuất cookie từ profile này.", + "formatLabel": "Định dạng", + "netscape": "Netscape TXT", + "json": "JSON", + "success": "Xuất cookie thành công", + "error": "Xuất cookie thất bại" + } + }, + "toasts": { + "success": { + "profileCreated": "Tạo profile thành công", + "profileDeleted": "Xóa profile thành công", + "profileUpdated": "Cập nhật profile thành công", + "profileLaunched": "Khởi chạy profile thành công", + "proxyCreated": "Tạo proxy thành công", + "proxyDeleted": "Xóa proxy thành công", + "proxyUpdated": "Cập nhật proxy thành công", + "groupCreated": "Tạo nhóm thành công", + "groupDeleted": "Xóa nhóm thành công", + "groupUpdated": "Cập nhật nhóm thành công", + "settingsSaved": "Lưu cài đặt thành công", + "copied": "Đã sao chép vào clipboard", + "permissionRequested": "Đã yêu cầu quyền truy cập {{permission}}", + "downloadComplete": "Đã tải xuống {{browser}} {{version}} thành công!", + "importSuccess": "Đã nhập thành công {{count}} mục", + "exportSuccess": "Đã xuất thành công {{count}} mục", + "syncSuccess": "Đồng bộ hoàn tất", + "profileSynced": "Đã đồng bộ profile '{{name}}' thành công", + "cacheCleared": "Xóa bộ nhớ đệm thành công" + }, + "error": { + "profileCreateFailed": "Tạo profile thất bại", + "profileDeleteFailed": "Xóa profile thất bại", + "profileUpdateFailed": "Cập nhật profile thất bại", + "profileLaunchFailed": "Khởi chạy profile thất bại", + "proxyCreateFailed": "Tạo proxy thất bại", + "proxyDeleteFailed": "Xóa proxy thất bại", + "proxyUpdateFailed": "Cập nhật proxy thất bại", + "groupCreateFailed": "Tạo nhóm thất bại", + "groupDeleteFailed": "Xóa nhóm thất bại", + "groupUpdateFailed": "Cập nhật nhóm thất bại", + "settingsSaveFailed": "Lưu cài đặt thất bại", + "copyFailed": "Sao chép vào clipboard thất bại", + "downloadFailed": "Tải xuống {{browser}} thất bại", + "importFailed": "Nhập thất bại", + "exportFailed": "Xuất thất bại", + "syncFailed": "Đồng bộ thất bại", + "profileSyncFailed": "Đồng bộ profile '{{name}}' thất bại", + "cacheClearFailed": "Xóa bộ nhớ đệm thất bại", + "unknown": "Đã xảy ra lỗi không xác định" + }, + "loading": { + "downloading": "Đang tải xuống {{browser}} {{version}}", + "extracting": "Đang giải nén {{browser}} {{version}}", + "verifying": "Đang xác minh {{browser}} {{version}}", + "syncing": "Đang đồng bộ...", + "syncingProfile": "Đang đồng bộ profile '{{name}}'...", + "syncingProfileWithProgress": "{{count}} tệp ({{size}})", + "updatingVersions": "Đang cập nhật phiên bản trình duyệt..." + } + }, + "errors": { + "required": "Trường này là bắt buộc", + "invalidUrl": "Vui lòng nhập URL hợp lệ", + "invalidPort": "Vui lòng nhập số cổng hợp lệ (1-65535)", + "invalidEmail": "Vui lòng nhập địa chỉ email hợp lệ", + "minLength": "Phải có ít nhất {{min}} ký tự", + "maxLength": "Tối đa {{max}} ký tự", + "networkError": "Lỗi mạng. Vui lòng kiểm tra kết nối của bạn.", + "serverError": "Lỗi máy chủ. Vui lòng thử lại sau.", + "unknownError": "Đã xảy ra lỗi không xác định. Vui lòng thử lại.", + "noProfilesForUrl": "Không có profile nào. Vui lòng tạo profile trước khi mở URL.", + "updateCamoufoxConfigFailed": "Cập nhật cấu hình camoufox thất bại: {{error}}", + "updateWayfernConfigFailed": "Cập nhật cấu hình wayfern thất bại: {{error}}", + "createProfileFailed": "Tạo profile thất bại: {{error}}", + "launchBrowserFailed": "Khởi chạy trình duyệt thất bại: {{error}}", + "cannotDeleteRunningProfile": "Không thể xóa profile khi trình duyệt đang chạy. Vui lòng dừng trình duyệt trước.", + "deleteProfileFailed": "Xóa profile thất bại: {{error}}", + "renameProfileFailed": "Đổi tên profile thất bại: {{error}}", + "killBrowserFailed": "Dừng trình duyệt thất bại: {{error}}", + "deleteSelectedProfilesFailed": "Xóa các profile đã chọn thất bại: {{error}}", + "cookieCopyUnsupportedBrowser": "Sao chép cookie chỉ hoạt động với profile Wayfern và Camoufox", + "updateSyncSettingsFailed": "Cập nhật cài đặt đồng bộ thất bại", + "cloneProfileFailed": "Nhân bản profile thất bại: {{error}}", + "loadSupportedBrowsersFailed": "Tải danh sách trình duyệt hỗ trợ thất bại", + "setupExtensionListenersFailed": "Thiết lập trình lắng nghe sự kiện tiện ích thất bại: {{error}}", + "loadGroupsFailed": "Tải nhóm thất bại: {{error}}", + "setupGroupListenersFailed": "Thiết lập trình lắng nghe sự kiện nhóm thất bại: {{error}}", + "loadProfilesFailed": "Tải profile thất bại: {{error}}", + "setupProfileListenersFailed": "Thiết lập trình lắng nghe sự kiện profile thất bại: {{error}}", + "loadProxiesFailed": "Tải proxy thất bại: {{error}}", + "setupProxyListenersFailed": "Thiết lập trình lắng nghe sự kiện proxy thất bại: {{error}}", + "loadVpnConfigsFailed": "Tải cấu hình VPN thất bại: {{error}}", + "setupVpnListenersFailed": "Thiết lập trình lắng nghe sự kiện VPN thất bại: {{error}}", + "themeNotFound": "Không tìm thấy chủ đề Tokyo Night", + "setProfilePasswordFailed": "Đặt mật khẩu profile thất bại: {{error}}" + }, + "browser": { + "camoufox": "Camoufox", + "wayfern": "Wayfern" + }, + "fingerprint": { + "crossOsWarning": "Giả mạo vân tay cho hệ điều hành khác kém tin cậy hơn vì không thể mô phỏng hoàn hảo tất cả thành phần nền tảng. Hãy sử dụng thận trọng.", + "crossOsLimitations": "Giả mạo vân tay xuyên hệ điều hành có giới hạn. Các API cấp hệ thống vẫn có thể phản ánh hệ điều hành thực tế của bạn, và một số tính năng có thể bị giảm hiệu suất.", + "osLabel": "Vân tay hệ điều hành", + "selectOSPlaceholder": "Chọn hệ điều hành", + "generateRandomOnLaunch": "Tạo vân tay ngẫu nhiên mỗi lần khởi chạy", + "generateRandomDescription": "Khi bật, vân tay mới sẽ được tạo mỗi khi khởi chạy trình duyệt.", + "generateRandomDescriptionAuto": "Khi bật, vân tay mới sẽ được tạo mỗi khi khởi chạy trình duyệt. Vân tay tạo ra sẽ được lưu để tham khảo.", + "autoLocationDescription": "Tự động cấu hình thông tin vị trí dựa trên cấu hình proxy hoặc kết nối của bạn nếu không có proxy", + "editingDisabledRunning": "Chỉnh sửa vân tay bị tắt vì profile đang chạy. Dừng profile để thực hiện thay đổi.", + "editingDisabledRandomized": "Chỉnh sửa vân tay bị tắt vì tính năng tạo vân tay ngẫu nhiên đang bật. Tắt tùy chọn ở trên để chỉnh sửa thủ công cấu hình vân tay.", + "advancedWarning": "Cảnh báo: Chỉ chỉnh sửa các tham số này nếu bạn biết mình đang làm gì. Giá trị không đúng có thể khiến trang web bị lỗi, bị phát hiện, và gây ra lỗi khó gỡ.", + "basicWarning": "Cảnh báo: Chỉ chỉnh sửa các tham số này nếu bạn biết mình đang làm gì.", + "automatic": "Tự động", + "manual": "Thủ công", + "blockingOptions": "Tùy chọn chặn", + "blockImages": "Chặn hình ảnh", + "blockWebRTC": "Chặn WebRTC", + "blockWebGL": "Chặn WebGL", + "navigatorProperties": "Thuộc tính Navigator", + "userAgent": "User Agent", + "userAgentAndPlatform": "User Agent và nền tảng", + "platform": "Nền tảng", + "platformVersion": "Phiên bản nền tảng", + "appVersion": "Phiên bản ứng dụng", + "osCpu": "CPU hệ điều hành", + "hardwareConcurrency": "Số luồng phần cứng", + "maxTouchPoints": "Số điểm chạm tối đa", + "doNotTrack": "Không theo dõi", + "selectDntPlaceholder": "Chọn giá trị DNT", + "dntAllowed": "0 (cho phép theo dõi)", + "dntNotAllowed": "1 (không cho phép theo dõi)", + "dntUnspecified": "không xác định", + "language": "Ngôn ngữ", + "primaryLanguage": "Ngôn ngữ chính (navigator.language)", + "languages": "Ngôn ngữ (mảng JSON)", + "languageAndLocale": "Ngôn ngữ và vùng", + "screenProperties": "Thuộc tính màn hình", + "screenWidth": "Chiều rộng màn hình", + "screenHeight": "Chiều cao màn hình", + "availableWidth": "Chiều rộng khả dụng", + "availableHeight": "Chiều cao khả dụng", + "colorDepth": "Độ sâu màu", + "pixelDepth": "Độ sâu pixel", + "devicePixelRatio": "Tỷ lệ pixel thiết bị", + "windowProperties": "Thuộc tính cửa sổ", + "outerWidth": "Chiều rộng ngoài", + "outerHeight": "Chiều cao ngoài", + "innerWidth": "Chiều rộng trong", + "innerHeight": "Chiều cao trong", + "screenX": "Screen X", + "screenY": "Screen Y", + "geolocation": "Vị trí địa lý", + "timezoneAndGeolocation": "Múi giờ và vị trí địa lý", + "timezoneGeolocationDescription": "Các giá trị này ghi đè API múi giờ và vị trí địa lý của trình duyệt.", + "latitude": "Vĩ độ", + "longitude": "Kinh độ", + "timezone": "Múi giờ", + "timezoneIana": "Múi giờ (IANA)", + "timezoneOffset": "Độ lệch (phút từ UTC)", + "accuracy": "Độ chính xác (mét)", + "locale": "Vùng", + "region": "Khu vực", + "script": "Chữ viết", + "webglProperties": "Thuộc tính WebGL", + "webglVendor": "Nhà cung cấp WebGL", + "webglRenderer": "Trình kết xuất WebGL", + "webglParameters": "Tham số WebGL", + "webglParametersJson": "Tham số WebGL (JSON)", + "webgl2Parameters": "Tham số WebGL2", + "webglShaderPrecisionFormats": "Độ chính xác shader WebGL", + "webgl2ShaderPrecisionFormats": "Độ chính xác shader WebGL2", + "canvasFingerprint": "Vân tay Canvas", + "canvasNoiseSeed": "Hạt giống nhiễu Canvas", + "canvasNoiseSeedDescription": "Hạt giống này được dùng để tạo vân tay canvas nhất quán nhưng độc đáo. Mỗi profile nên có hạt giống khác nhau.", + "fonts": "Phông chữ", + "fontsJson": "Phông chữ (mảng JSON)", + "battery": "Pin", + "charging": "Đang sạc", + "chargingTime": "Thời gian sạc", + "dischargingTime": "Thời gian xả", + "batteryLevel": "Mức pin (0-1)", + "screenResolution": "Độ phân giải màn hình", + "maxWidth": "Chiều rộng tối đa", + "maxHeight": "Chiều cao tối đa", + "minWidth": "Chiều rộng tối thiểu", + "minHeight": "Chiều cao tối thiểu", + "hardwareProperties": "Thuộc tính phần cứng", + "deviceMemory": "Bộ nhớ thiết bị (GB)", + "audioProperties": "Thuộc tính âm thanh", + "sampleRate": "Tần số lấy mẫu", + "maxChannelCount": "Số kênh tối đa", + "vendorInfo": "Thông tin nhà cung cấp", + "vendor": "Nhà cung cấp", + "vendorSub": "Nhà cung cấp phụ", + "productSub": "Phụ phẩm", + "brand": "Thương hiệu", + "brandVersion": "Phiên bản thương hiệu", + "proFeature": "Đây là tính năng Pro", + "generateFingerprint": "Tạo vân tay", + "refreshFingerprint": "Làm mới vân tay", + "canvasNoiseSeedPlaceholder": "Nhập chuỗi hạt giống cho vân tay canvas", + "addFontsPlaceholder": "Thêm phông chữ...", + "enterAsJson": "Nhập {{title}} dưới dạng JSON" + }, + "warnings": { + "windowResizeTitle": "Kích thước cửa sổ tùy chỉnh", + "windowResizeDescription": "Thay đổi kích thước cửa sổ trình duyệt có thể tăng khả năng bị trang web phát hiện thông tin trình duyệt bị giả mạo.", + "windowResizeCamoufoxTitle": "Cửa sổ xem bị khóa bởi Camoufox", + "windowResizeCamoufoxDescription": "Camoufox khóa cửa sổ xem theo kích thước màn hình giả mạo để chống vân tay. Thay đổi kích thước cửa sổ có thể gây ra vùng bị cắt xén hoặc xám. Đây là hành vi bình thường.", + "dontShowAgain": "Không hiển thị lại", + "continue": "Tiếp tục", + "cancel": "Hủy" + }, + "syncAll": { + "title": "Bật đồng bộ cho các mục hiện có", + "description": "Bạn có các mục chưa được đồng bộ. Bạn có muốn bật đồng bộ cho tất cả không?", + "enableAll": "Bật tất cả", + "skip": "Bỏ qua", + "success": "Đã bật đồng bộ cho tất cả mục", + "labels": { + "proxies": "Proxy", + "vpns": "VPN", + "groups": "Nhóm", + "extensions": "Tiện ích", + "extensionGroups": "Nhóm tiện ích" + } + }, + "crossOs": { + "viewOnly": "Profile này được tạo trên {{os}} và không được hỗ trợ trên hệ thống này", + "cannotLaunch": "Profile này được tạo trên {{os}} và không được hỗ trợ trên hệ thống này", + "cannotModify": "Không thể chỉnh sửa cài đặt đồng bộ cho profile đa hệ điều hành" + }, + "profileInfo": { + "title": "Chi tiết profile", + "tabs": { + "info": "Thông tin", + "settings": "Cài đặt" + }, + "fields": { + "profileId": "ID profile", + "browser": "Trình duyệt", + "releaseType": "Loại phát hành", + "proxyVpn": "Proxy / VPN", + "launchHook": "Hook khởi chạy", + "group": "Nhóm", + "tags": "Thẻ", + "note": "Ghi chú", + "syncStatus": "Trạng thái đồng bộ", + "lastLaunched": "Lần khởi chạy cuối", + "hostOs": "HĐH chủ", + "ephemeral": "Tạm thời", + "extensionGroup": "Nhóm tiện ích", + "totalSessions": "Tổng số phiên", + "syncMode": "Chế độ đồng bộ", + "proxy": "PROXY", + "vpn": "VPN", + "cookieCount": "Cookie đã lưu", + "localDataTransfer": "Truyền dữ liệu cục bộ" + }, + "values": { + "none": "Không có", + "never": "Chưa bao giờ", + "copied": "Đã sao chép!", + "yes": "Có", + "activeNow": "Đang hoạt động", + "direct": "Trực tiếp", + "loading": "Đang tải…" + }, + "network": { + "bypassRules": "Quy tắc bỏ qua proxy", + "bypassRulesTitle": "Quy tắc bỏ qua proxy", + "bypassRulesDescription": "Yêu cầu khớp với các quy tắc này sẽ kết nối trực tiếp, bỏ qua proxy.", + "addRule": "Thêm quy tắc", + "rulePlaceholder": "ví dụ: example.com, 192.168.1.*, .*\\.local", + "noRules": "Chưa cấu hình quy tắc bỏ qua nào.", + "ruleTypes": "Hỗ trợ tên máy chủ, địa chỉ IP và biểu thức chính quy." + }, + "launchHook": { + "title": "URL hook khởi chạy", + "label": "URL hook khởi chạy", + "description": "Donut Browser sẽ gửi yêu cầu GET đến URL này mỗi khi profile được khởi chạy.", + "placeholder": "https://example.com/hooks/profile-launch", + "invalidUrlHint": "Nhập URL http:// hoặc https:// hợp lệ." + }, + "actions": { + "manageCookies": "Quản lý cookie", + "assignExtensionGroup": "Gán nhóm tiện ích" + }, + "clone": { + "title": "Nhân bản profile", + "description": "Nhập tên cho profile nhân bản", + "namePlaceholder": "Tên profile", + "button": "Nhân bản" + }, + "duplicate": "Nhân bản", + "breadcrumbRoot": "Profile", + "openDialog": "Mở cài đặt", + "sections": { + "overview": "Tổng quan", + "fingerprint": "Vân tay", + "network": "Mạng", + "cookies": "Cookie", + "extensions": "Tiện ích", + "sync": "Đồng bộ", + "automation": "Tự động hóa", + "security": "Bảo mật", + "delete": "Xóa profile", + "activity": "Hoạt động", + "launchHook": "Hook khởi chạy" + }, + "sectionDesc": { + "fingerprint": "Cấu hình cách profile này hiển thị với các script vân tay.", + "network": "Quản lý proxy hoặc VPN mà profile này sử dụng để truy cập internet.", + "cookies": "Nhập, sao chép hoặc xóa cookie cho profile này.", + "extensions": "Chọn tiện ích nào được tải khi profile này khởi chạy.", + "sync": "Cấu hình cách profile này được phản chiếu sang các thiết bị khác của bạn.", + "automation": "Chạy lệnh hoặc script mỗi khi profile này khởi chạy.", + "security": "Mã hóa dữ liệu profile bằng mật khẩu.", + "launchHook": "Gửi yêu cầu GET đến URL này mỗi khi profile khởi chạy." + }, + "badges": { + "locked": "ĐÃ KHÓA", + "active": "ĐANG HOẠT ĐỘNG" + }, + "cookies": { + "runningNotice": "Không thể đọc cookie khi trình duyệt đang chạy. Hãy đóng profile này trước.", + "domainsHeader": "Tên miền ({{count}})" + }, + "security": { + "protected": "Profile này đã được mã hóa bằng mật khẩu.", + "unprotected": "Profile này chưa được mã hóa. Đặt mật khẩu để mã hóa dữ liệu khi lưu trữ.", + "cannotWhileRunning": "Dừng profile trước khi thay đổi mật khẩu." + }, + "fingerprint": { + "notSupported": "Chỉnh sửa vân tay chỉ khả dụng cho profile Camoufox và Wayfern." + } + }, + "extensions": { + "title": "Tiện ích", + "description": "Quản lý tiện ích trình duyệt và nhóm tiện ích cho profile của bạn.", + "upload": "Tải lên", + "delete": "Xóa", + "extensionsTab": "Tiện ích", + "groupsTab": "Nhóm", + "managedNotice": "Tiện ích được quản lý tại đây sẽ thay thế bất kỳ tiện ích nào được cài đặt thủ công trong profile khi khởi chạy.", + "proRequired": "Quản lý tiện ích là tính năng Pro", + "empty": "Chưa tải lên tiện ích nào.", + "noGroups": "Chưa tạo nhóm tiện ích nào.", + "createGroup": "Tạo nhóm", + "newGroup": "Nhóm mới", + "addToGroup": "Thêm tiện ích...", + "removeFromGroup": "Xóa khỏi nhóm", + "deleteGroup": "Xóa nhóm", + "extensionGroup": "Nhóm tiện ích", + "compatibility": { + "label": "Tương thích", + "chromium": "Chromium", + "firefox": "Firefox", + "both": "Chromium và Firefox" + }, + "selectedFile": "Tệp đã chọn", + "namePlaceholder": "Tên tiện ích", + "groupNamePlaceholder": "Tên nhóm", + "uploadSuccess": "Tải lên tiện ích thành công", + "deleteSuccess": "Xóa tiện ích thành công", + "groupCreateSuccess": "Tạo nhóm tiện ích thành công", + "groupUpdateSuccess": "Cập nhật nhóm tiện ích thành công", + "groupDeleteSuccess": "Xóa nhóm tiện ích thành công", + "deleteConfirmTitle": "Xóa tiện ích", + "deleteConfirmDescription": "Bạn có chắc muốn xóa \"{{name}}\"? Hành động này không thể hoàn tác.", + "deleteGroupConfirmTitle": "Xóa nhóm tiện ích", + "deleteGroupConfirmDescription": "Bạn có chắc muốn xóa nhóm \"{{name}}\"? Hành động này không thể hoàn tác.", + "invalidFileType": "Loại tệp không hợp lệ. Vui lòng tải lên tệp .crx, .xpi hoặc .zip.", + "readError": "Đọc tệp tiện ích thất bại.", + "assignTitle": "Gán nhóm tiện ích", + "assignDescription": "Gán {{count}} profile đã chọn vào nhóm tiện ích.", + "noGroup": "Không có (Không có nhóm tiện ích)", + "assignSuccess": "Gán nhóm tiện ích thành công", + "editExtension": "Chỉnh sửa tiện ích", + "updateSuccess": "Cập nhật tiện ích thành công", + "reupload": "Tải lên lại", + "version": "Phiên bản", + "author": "Tác giả", + "homepage": "Trang chủ", + "editGroup": "Chỉnh sửa nhóm", + "editGroupDescription": "Cập nhật tên nhóm và quản lý tiện ích trong nhóm.", + "groupExtensions": "Tiện ích trong nhóm này", + "noExtensionsInGroup": "Chưa thêm tiện ích nào", + "editExtensionDescription": "Cập nhật tên tiện ích, xem metadata hoặc tải lên lại tệp tiện ích.", + "metadata": "Metadata", + "noMetadata": "Không có metadata từ manifest.", + "selectFile": "Chọn tệp", + "syncEnabled": "Đã bật đồng bộ", + "syncDisabled": "Đã tắt đồng bộ", + "syncEnableTooltip": "Bật đồng bộ", + "syncDisableTooltip": "Tắt đồng bộ", + "loadGroupsFailed": "Tải nhóm tiện ích thất bại", + "assignGroupFailed": "Gán nhóm tiện ích thất bại", + "bulkDelete": { + "extensionsTitle": "Xóa tiện ích", + "extensionsDescription": "Xóa {{count}} tiện ích? {{names}}", + "groupsTitle": "Xóa nhóm tiện ích", + "groupsDescription": "Xóa {{count}} nhóm tiện ích? {{names}}", + "confirmButton": "Xóa" + } + }, + "pro": { + "badge": "PRO", + "fingerprintLocked": "Chỉnh sửa vân tay là tính năng Pro", + "cookieCopyLocked": "Sao chép cookie là tính năng Pro", + "cookieImportLocked": "Nhập cookie là tính năng Pro", + "cookieExportLocked": "Xuất cookie là tính năng Pro", + "cookieManagementLocked": "Quản lý cookie là tính năng Pro" + }, + "dnsBlocklist": { + "title": "Danh sách chặn DNS", + "none": "Không", + "light": "Nhẹ", + "normal": "Bình thường", + "pro": "Pro", + "proPlus": "Pro++", + "ultimate": "Tối đa", + "settingsDescription": "Danh sách chặn DNS chặn quảng cáo, trình theo dõi và tên miền độc hại ở cấp proxy. Danh sách được tự động làm mới mỗi 12 giờ.", + "manageLists": "Quản lý danh sách chặn DNS", + "refreshAll": "Làm mới tất cả danh sách", + "refreshFailed": "Làm mới danh sách chặn DNS thất bại", + "domains": "tên miền", + "fresh": "Mới", + "stale": "Cũ", + "notCached": "Chưa lưu bộ nhớ đệm" + }, + "vpns": { + "form": { + "titleEdit": "Chỉnh sửa VPN", + "titleCreate": "Tạo VPN WireGuard", + "descEdit": "Cập nhật tên cấu hình VPN của bạn.", + "descCreate": "Nhập thông tin giao diện và peer WireGuard của bạn.", + "name": "Tên", + "namePlaceholder": "ví dụ: WireGuard nhà", + "privateKey": "Khóa riêng tư", + "privateKeyPlaceholder": "Khóa riêng tư mã hóa Base64", + "address": "Địa chỉ", + "addressPlaceholder": "ví dụ: 10.0.0.2/24", + "dnsOptional": "DNS (tùy chọn)", + "dnsPlaceholder": "ví dụ: 1.1.1.1", + "mtuOptional": "MTU (tùy chọn)", + "mtuPlaceholder": "ví dụ: 1420", + "peerPublicKey": "Khóa công khai peer", + "peerPublicKeyPlaceholder": "Khóa công khai peer mã hóa Base64", + "peerEndpoint": "Điểm cuối peer", + "peerEndpointPlaceholder": "ví dụ: vpn.example.com:51820", + "allowedIps": "IP được phép", + "allowedIpsPlaceholder": "ví dụ: 0.0.0.0/0, ::/0", + "keepaliveOptional": "Keepalive liên tục (tùy chọn)", + "keepalivePlaceholder": "ví dụ: 25", + "presharedKeyOptional": "Khóa chia sẻ trước (tùy chọn)", + "presharedKeyPlaceholder": "Khóa chia sẻ trước mã hóa Base64", + "updateButton": "Cập nhật VPN", + "createButton": "Tạo VPN", + "nameRequired": "Tên VPN là bắt buộc", + "privateKeyRequired": "Khóa riêng tư là bắt buộc", + "addressRequired": "Địa chỉ là bắt buộc", + "peerPublicKeyRequired": "Khóa công khai peer là bắt buộc", + "peerEndpointRequired": "Điểm cuối peer là bắt buộc", + "updated": "Cập nhật VPN thành công", + "created": "Tạo VPN WireGuard thành công", + "updateFailed": "Cập nhật VPN thất bại: {{error}}", + "createFailed": "Tạo VPN thất bại: {{error}}" + }, + "import": { + "title": "Nhập cấu hình VPN", + "descDropzone": "Nhập tệp cấu hình WireGuard (.conf)", + "descPreview": "Xem lại cấu hình VPN để nhập", + "descResult": "Nhập VPN hoàn tất", + "dropzonePrompt": "Kéo thả tệp WireGuard .conf vào đây hoặc nhấn để duyệt", + "pasteHint": "Dán từ clipboard bằng {{modKey}}+V", + "invalidContent": "Nội dung không giống cấu hình VPN hợp lệ", + "fileReadError": "Đọc tệp thất bại", + "wrongFileType": "Vui lòng thả tệp WireGuard .conf", + "configurationLabel": "Cấu hình {{type}}", + "endpointLabel": "Điểm cuối: {{endpoint}}", + "vpnNameLabel": "Tên VPN", + "vpnNamePlaceholder": "VPN của tôi", + "configPreview": "Xem trước cấu hình", + "importedSuccess": "Nhập VPN thành công", + "importFailed": "Nhập thất bại", + "importButton": "Nhập VPN", + "doneButton": "Xong", + "failedGeneric": "Nhập cấu hình VPN thất bại", + "defaultName": "VPN {{type}}" + }, + "management": { + "loading": "Đang tải VPN...", + "noneCreated": "Chưa tạo cấu hình VPN nào. Nhập hoặc tạo một VPN bằng các nút phía trên.", + "editVpn": "Chỉnh sửa VPN", + "deleteVpn": "Xóa VPN", + "cannotDelete_one": "Không thể xóa: đang được sử dụng bởi {{count}} profile", + "cannotDelete_other": "Không thể xóa: đang được sử dụng bởi {{count}} profile", + "syncCannotDisable": "Không thể tắt đồng bộ khi VPN này được sử dụng bởi profile đã đồng bộ", + "deleteSuccess": "Xóa VPN thành công", + "deleteFailed": "Xóa VPN thất bại", + "deleteTitle": "Xóa VPN", + "deleteDescription": "Hành động này không thể hoàn tác. VPN \"{{name}}\" sẽ bị xóa vĩnh viễn." + } + }, + "importProfile": { + "title": "Nhập profile trình duyệt", + "autoDetect": "Tự động phát hiện", + "manualImport": "Nhập thủ công", + "detectedProfilesTitle": "Profile trình duyệt đã phát hiện", + "scanning": "Đang quét profile trình duyệt...", + "noneFound": "Không tìm thấy profile trình duyệt nào trên hệ thống của bạn.", + "noneFoundHint": "Thử tùy chọn nhập thủ công nếu bạn có profile ở vị trí tùy chỉnh.", + "selectProfile": "Chọn profile:", + "selectProfilePlaceholder": "Chọn profile đã phát hiện", + "pathLabel": "Đường dẫn:", + "browserLabel": "Trình duyệt:", + "newProfileName": "Tên profile mới:", + "newProfileNamePlaceholder": "Nhập tên cho profile được nhập", + "manualTitle": "Nhập profile thủ công", + "browserType": "Loại trình duyệt:", + "loadingBrowsers": "Đang tải trình duyệt...", + "selectBrowserType": "Chọn loại trình duyệt", + "profileFolderPath": "Đường dẫn thư mục profile:", + "profileFolderPlaceholder": "Nhập đường dẫn đầy đủ đến thư mục profile", + "browseFolderTitle": "Duyệt thư mục", + "examplePaths": "Đường dẫn ví dụ:", + "selectFolderTitle": "Chọn thư mục profile trình duyệt", + "folderDialogFailed": "Mở hộp thoại thư mục thất bại", + "detectFailed": "Phát hiện profile trình duyệt hiện có thất bại", + "fillFields": "Vui lòng điền đầy đủ các trường", + "selectAndName": "Vui lòng chọn profile và cung cấp tên", + "profileNotFound": "Không tìm thấy profile đã chọn", + "importedSuccess": "Đã nhập thành công profile \"{{name}}\"", + "notInstalled": "{{browser}} chưa được cài đặt. Vui lòng tải xuống {{browser}} trước từ cửa sổ chính, sau đó thử nhập lại.", + "importFailed": "Nhập profile thất bại: {{error}}", + "proxyOptional": "Proxy (Tùy chọn)", + "noProxy": "Không có proxy", + "nextButton": "Tiếp theo", + "importButton": "Nhập", + "importedAs": "Profile này sẽ được nhập dưới dạng profile {{browser}}." + }, + "syncTooltips": { + "syncing": "Đang đồng bộ...", + "syncedAt": "Đã đồng bộ {{time}}", + "synced": "Đã đồng bộ", + "waiting": "Đang chờ đồng bộ", + "errorWith": "Lỗi đồng bộ: {{error}}", + "error": "Lỗi đồng bộ", + "notSynced": "Chưa đồng bộ", + "enable": "Bật đồng bộ", + "disable": "Tắt đồng bộ", + "lockedInUse": "Đồng bộ bị khóa khi đang được sử dụng bởi profile đã đồng bộ", + "bulkToggle": "Bật/tắt đồng bộ" + }, + "groupManagement": { + "description": "Quản lý nhóm profile của bạn", + "createGroup": "Tạo nhóm", + "noGroups": "Chưa tạo nhóm nào. Tạo nhóm đầu tiên bằng nút phía trên.", + "loading": "Đang tải nhóm...", + "profileCount_one": "{{count}} profile", + "profileCount_other": "{{count}} profile", + "groupsLabel": "Nhóm", + "profilesCol": "Profile", + "syncCannotDisable": "Không thể tắt đồng bộ khi nhóm này được sử dụng bởi profile đã đồng bộ", + "editGroupTooltip": "Chỉnh sửa nhóm", + "deleteGroupTooltip": "Xóa nhóm", + "loadFailed": "Tải nhóm thất bại", + "bulkDelete": { + "title": "Xóa nhóm", + "description": "Bạn có chắc muốn xóa {{count}} nhóm? {{names}}. Profile sẽ được chuyển về Mặc định.", + "description_one": "Bạn có chắc muốn xóa {{count}} nhóm? {{names}}. Profile sẽ được chuyển về Mặc định.", + "confirmButton": "Xóa nhóm" + } + }, + "proxyAssignment": { + "title": "Gán proxy / VPN", + "description_one": "Gán proxy hoặc VPN cho {{count}} profile đã chọn.", + "description_other": "Gán proxy hoặc VPN cho {{count}} profile đã chọn.", + "selectLabel": "Proxy / VPN", + "placeholder": "Chọn proxy hoặc VPN", + "noProxy": "Không có proxy / VPN", + "searchPlaceholder": "Tìm kiếm proxy hoặc VPN...", + "notFound": "Không tìm thấy proxy hoặc VPN nào.", + "assignButton": "Gán", + "success": "Đã gán proxy/VPN thành công cho {{count}} profile", + "failed": "Gán proxy/VPN thất bại", + "selectedProfilesLabel": "Profile đã chọn:", + "assignProxyVpnLabel": "Gán Proxy / VPN:", + "noneOption": "Không có", + "noValidProfiles": "Chưa chọn profile hợp lệ nào.", + "vpnGroupHeading": "VPN", + "failedFallback": "Gán proxy/VPN cho profile thất bại" + }, + "groupAssignment": { + "title": "Gán nhóm", + "description_one": "Gán nhóm cho {{count}} profile đã chọn.", + "description_other": "Gán nhóm cho {{count}} profile đã chọn.", + "selectLabel": "Nhóm", + "placeholder": "Chọn nhóm", + "noGroup": "Không có nhóm (Mặc định)", + "assignButton": "Gán", + "success": "Đã gán nhóm thành công cho {{count}} profile", + "failed": "Gán nhóm thất bại", + "selectedProfilesLabel": "Profile đã chọn:", + "assignGroupLabel": "Gán vào nhóm:", + "noValidProfiles": "Chưa chọn profile hợp lệ nào.", + "failedFallback": "Gán nhóm cho profile thất bại" + }, + "profileSelector": { + "title": "Chọn profile", + "description": "Chọn profile để khởi chạy với URL này", + "searchPlaceholder": "Tìm kiếm profile...", + "noProfiles": "Không có profile nào", + "noResults": "Không có profile nào khớp với tìm kiếm", + "selectButton": "Chọn", + "launching": "Đang khởi chạy...", + "chooseProfileTitle": "Chọn profile", + "openingUrl": "Đang mở URL:", + "urlCopied": "Đã sao chép URL vào clipboard!", + "selectProfileLabel": "Chọn profile:", + "noneAvailableShort": "Không có profile nào. Vui lòng tạo profile trước.", + "noneAvailableLong": "Đóng hộp thoại này và tạo profile từ cửa sổ chính để bắt đầu.", + "chooseAProfile": "Chọn một profile", + "badgeProxy": "Proxy", + "badgeRunning": "Đang chạy", + "badgeUnavailable": "Không khả dụng", + "openButton": "Mở" + }, + "locationProxy": { + "title": "Proxy vị trí nhanh", + "description": "Chọn một quốc gia để định tuyến profile này qua đó. Proxy sẽ được tạo tự động.", + "country": "Quốc gia", + "selectCountry": "Chọn quốc gia", + "searchCountry": "Tìm kiếm quốc gia...", + "noCountriesFound": "Không tìm thấy quốc gia nào.", + "apply": "Áp dụng", + "creating": "Đang tạo proxy...", + "success": "Đã áp dụng proxy vị trí", + "failed": "Áp dụng proxy vị trí thất bại", + "titleCreate": "Tạo proxy vị trí", + "descriptionCreate": "Tạo proxy nhắm mục tiêu địa lý với phiên bản cố định 24 giờ", + "countryLabel": "Quốc gia (bắt buộc)", + "regionLabel": "Khu vực (tùy chọn)", + "cityLabel": "Thành phố (tùy chọn)", + "ispLabel": "Nhà mạng (tùy chọn)", + "nameLabel": "Tên", + "namePlaceholder": "Tên proxy", + "loadingCountries": "Đang tải quốc gia...", + "selectCountryPh": "Chọn quốc gia", + "searchCountries": "Tìm kiếm quốc gia...", + "loadFailed": "Tải quốc gia thất bại", + "selectCountryFirst": "Hãy chọn quốc gia trước", + "loadingRegions": "Đang tải khu vực...", + "noRegions": "Không có khu vực nào", + "selectRegion": "Chọn khu vực", + "searchRegions": "Tìm kiếm khu vực...", + "loadingCities": "Đang tải thành phố...", + "noCities": "Không có thành phố nào", + "selectCity": "Chọn thành phố", + "searchCities": "Tìm kiếm thành phố...", + "loadingIsps": "Đang tải nhà mạng...", + "noIsps": "Không có nhà mạng nào", + "selectIsp": "Chọn nhà mạng", + "searchIsps": "Tìm kiếm nhà mạng...", + "createSuccess": "Tạo proxy vị trí thành công", + "createFailed": "Tạo proxy vị trí thất bại", + "creatingButton": "Đang tạo...", + "createButton": "Tạo" + }, + "launchOnLogin": { + "title": "Bật khởi chạy khi đăng nhập?", + "description": "Chạy trong nền giúp giữ proxy và trình duyệt của bạn hoạt động.", + "declineButton": "Không hỏi lại", + "declining": "...", + "enableButton": "Bật", + "enableSuccess": "Đã bật khởi chạy khi đăng nhập", + "enableFailed": "Bật khởi chạy khi đăng nhập thất bại", + "declineFailed": "Lưu tùy chọn thất bại", + "tryAgain": "Vui lòng thử lại" + }, + "wayfernTerms": { + "title": "Điều khoản và điều kiện Wayfern", + "description": "Trước khi sử dụng Donut Browser, bạn phải đọc và đồng ý với Điều khoản và Điều kiện của Wayfern.", + "reviewLabel": "Vui lòng xem lại Điều khoản và Điều kiện tại:", + "agreeNotice": "Bằng cách nhấn \"Tôi chấp nhận\", bạn đồng ý bị ràng buộc bởi các điều khoản này.", + "acceptButton": "Tôi chấp nhận", + "acceptSuccess": "Chấp nhận điều khoản thành công", + "acceptFailed": "Chấp nhận điều khoản thất bại", + "tryAgain": "Vui lòng thử lại" + }, + "commercialTrial": { + "title": "Thời gian dùng thử thương mại đã hết", + "description": "Thời gian dùng thử thương mại 2 tuần của bạn đã kết thúc.", + "body": "Nếu bạn sử dụng Donut Browser cho mục đích thương mại, bạn cần mua giấy phép thương mại để tiếp tục. Bạn vẫn có thể sử dụng miễn phí cho mục đích cá nhân.", + "understandButton": "Tôi hiểu", + "failed": "Lưu xác nhận thất bại", + "tryAgain": "Vui lòng thử lại" + }, + "permissionDialog": { + "titleMicrophone": "Yêu cầu quyền truy cập micro", + "titleCamera": "Yêu cầu quyền truy cập camera", + "descMicrophone": "Donut Browser cần quyền truy cập micro để bật tính năng micro trong trình duyệt web. Mỗi trang web muốn sử dụng micro vẫn sẽ hỏi quyền bạn riêng lẻ.", + "descCamera": "Donut Browser cần quyền truy cập camera để bật tính năng camera trong trình duyệt web. Mỗi trang web muốn sử dụng camera vẫn sẽ hỏi quyền bạn riêng lẻ.", + "grantedMicrophone": "Đã cấp quyền! Trình duyệt khởi chạy từ Donut Browser giờ có thể truy cập micro của bạn.", + "grantedCamera": "Đã cấp quyền! Trình duyệt khởi chạy từ Donut Browser giờ có thể truy cập camera của bạn.", + "notGrantedMicrophone": "Chưa cấp quyền. Nhấn nút bên dưới để yêu cầu quyền truy cập micro.", + "notGrantedCamera": "Chưa cấp quyền. Nhấn nút bên dưới để yêu cầu quyền truy cập camera.", + "doneButton": "Xong", + "cancelButton": "Hủy", + "grantAccessButton": "Cấp quyền truy cập", + "requestSuccessMicrophone": "Đã yêu cầu quyền truy cập micro", + "requestSuccessCamera": "Đã yêu cầu quyền truy cập camera", + "requestFailed": "Yêu cầu quyền thất bại", + "stillNotGrantedMicrophone": "Quyền truy cập micro vẫn chưa được cấp. Bạn có thể cần bật thủ công trong Cài đặt hệ thống → Quyền riêng tư & Bảo mật → Micro.", + "stillNotGrantedCamera": "Quyền truy cập camera vẫn chưa được cấp. Bạn có thể cần bật thủ công trong Cài đặt hệ thống → Quyền riêng tư & Bảo mật → Camera.", + "grantedToastMicrophone": "Đã cấp quyền truy cập micro", + "grantedToastCamera": "Đã cấp quyền truy cập camera" + }, + "traffic": { + "title": "Chi tiết lưu lượng", + "bandwidthOverTime": "Băng thông theo thời gian", + "timePeriodPlaceholder": "Khoảng thời gian", + "last1m": "1 phút trước", + "last5m": "5 phút trước", + "last30m": "30 phút trước", + "last1h": "1 giờ trước", + "last2h": "2 giờ trước", + "last4h": "4 giờ trước", + "last1d": "1 ngày trước", + "last7d": "7 ngày trước", + "last30d": "30 ngày trước", + "allTime": "Tất cả thời gian", + "allTimeShort": "tất cả", + "totalSuffix": "tổng", + "sentLabel": "Đã gửi ({{period}})", + "receivedLabel": "Đã nhận ({{period}})", + "requestsLabel": "Yêu cầu ({{period}})", + "allTimeTraffic": "Lưu lượng mọi thời điểm:", + "allTimeRequests": "Yêu cầu mọi thời điểm:", + "proxyDisclaimer": "Lưu ý: Nếu bạn đang sử dụng proxy, VPN hoặc dịch vụ tương tự, nhà cung cấp có thể tính lưu lượng khác do chi phí mã hóa và khác biệt giao thức.", + "topByTraffic": "Tên miền theo lưu lượng ({{period}})", + "topByRequests": "Tên miền theo yêu cầu ({{period}})", + "columnDomain": "Tên miền", + "columnRequests": "Yêu cầu", + "columnSent": "Đã gửi", + "columnReceived": "Đã nhận", + "columnTotal": "Tổng lưu lượng", + "uniqueIps": "IP duy nhất ({{count}})", + "noData": "Không có dữ liệu lưu lượng cho profile này.", + "noDataHint": "Dữ liệu lưu lượng sẽ xuất hiện sau khi bạn khởi chạy profile.", + "sentLegend": "Đã gửi", + "receivedLegend": "Đã nhận", + "tooltipSent": "↑ Đã gửi: ", + "tooltipReceived": "↓ Đã nhận: " + }, + "camoufoxDialog": { + "titleView": "Xem cài đặt vân tay - {{name}} ({{browser}})", + "titleConfigure": "Cấu hình cài đặt vân tay - {{name}} ({{browser}})", + "invalidFingerprint": "Cấu hình vân tay không hợp lệ", + "invalidFingerprintDescription": "Cấu hình vân tay chứa JSON không hợp lệ. Vui lòng kiểm tra cài đặt nâng cao.", + "saveFailed": "Lưu cấu hình thất bại", + "unknownError": "Đã xảy ra lỗi không xác định" + }, + "proxyCheck": { + "unknownLocation": "Không xác định", + "locationToast": "Vị trí proxy của bạn là:", + "failed": "Kiểm tra proxy thất bại: {{error}}", + "tooltipChecking": "Đang kiểm tra proxy...", + "tooltipIp": "IP: {{ip}}", + "tooltipChecked": "Đã kiểm tra {{time}}", + "tooltipFailed": "Thất bại {{time}}", + "tooltipFailedTitle": "Kiểm tra proxy thất bại", + "tooltipDefault": "Kiểm tra tính hợp lệ của proxy" + }, + "vpnCheck": { + "valid": "Cấu hình VPN \"{{name}}\" hợp lệ", + "invalid": "Cấu hình VPN \"{{name}}\" không hợp lệ", + "failed": "Kiểm tra VPN thất bại: {{error}}", + "tooltipChecking": "Đang kiểm tra cấu hình VPN...", + "tooltipValid": "Cấu hình hợp lệ", + "tooltipInvalid": "Cấu hình không hợp lệ", + "tooltipChecked": "Đã kiểm tra {{time}}", + "tooltipDefault": "Kiểm tra tính hợp lệ cấu hình VPN" + }, + "profileTable": { + "syncTooltipDisabled": "Đã tắt đồng bộ", + "syncTooltipSyncing": "Đang đồng bộ...", + "syncTooltipSyncedAt": "Đã đồng bộ {{time}}", + "syncTooltipSynced": "Đã đồng bộ", + "syncTooltipWaiting": "Đang chờ đồng bộ", + "syncTooltipErrorWith": "Lỗi đồng bộ: {{error}}", + "syncTooltipError": "Lỗi đồng bộ", + "syncTooltipNotSynced": "Chưa đồng bộ", + "noTags": "Không có thẻ", + "syncTooltipCloseToSync": "Đóng profile để đồng bộ", + "syncTooltipDisabledWithLast": "Đã tắt đồng bộ, lần đồng bộ cuối {{time}}", + "addTagsPlaceholder": "Thêm thẻ", + "tagsHeader": "Thẻ", + "noteHeader": "Ghi chú", + "vpnsHeading": "VPN", + "createByCountryHeading": "Tạo theo quốc gia" + }, + "releaseTypeSelector": { + "noReleaseTypes": "Không có loại phát hành nào.", + "placeholder": "Chọn loại phát hành...", + "stable": "Ổn định", + "nightly": "Nightly", + "downloaded": "Đã tải xuống", + "downloadBrowser": "Tải trình duyệt", + "downloading": "Đang tải xuống..." + }, + "dataTableActionBar": { + "selected": "Đã chọn {{count}}", + "clearSelection": "Xóa lựa chọn" + }, + "appUpdate": { + "toast": { + "updateFailed": "Cập nhật Donut Browser thất bại", + "restartFailed": "Khởi động lại thất bại", + "updateReady": "Bản cập nhật sẵn sàng, khởi động lại để áp dụng", + "manualDownloadRequired": "Cần tải xuống thủ công", + "restartNow": "Khởi động lại ngay", + "viewRelease": "Xem phiên bản", + "later": "Để sau", + "uploading": "Đang tải lên", + "downloading": "Đang tải xuống" + } + }, + "browserDownload": { + "toast": { + "fetchVersionsFailed": "Tải phiên bản {{browser}} thất bại", + "foundNewVersions": "Tìm thấy {{count}} phiên bản {{browser}} mới!", + "totalAvailableVersions": "Tổng số phiên bản: {{count}}", + "downloadFailed": "Tải xuống {{browser}} {{version}} thất bại", + "calculating": "đang tính...", + "extractionFailed": "{{browser}} {{version}}: giải nén thất bại", + "extractionFailedDescription": "Tệp hỏng đã bị xóa. Sẽ được tải lại trong lần thử tiếp theo.", + "extracting": "Đang giải nén tệp trình duyệt... Vui lòng không đóng ứng dụng.", + "verifying": "Đang xác minh tệp trình duyệt...", + "downloadingRolling": "Đang tải bản phát hành rolling..." + } + }, + "versionUpdater": { + "toast": { + "alreadyAvailable": "{{browser}} {{version}} đã có sẵn", + "updatingProfiles": "Đang cập nhật cấu hình profile...", + "updateCompleted": "Cập nhật {{browser}} hoàn tất", + "singleProfileUpdated": "Profile \"{{name}}\" đã được cập nhật lên phiên bản {{version}}. Bạn có thể khởi chạy trình duyệt với phiên bản mới nhất.", + "multipleProfilesUpdated": "{{count}} profile đã được cập nhật lên phiên bản {{version}}. Bạn có thể khởi chạy trình duyệt với phiên bản mới nhất.", + "versionAvailable": "Phiên bản {{version}} hiện đã có sẵn. Các profile đang chạy sẽ sử dụng phiên bản mới khi khởi động lại.", + "autoUpdateFailed": "Tự động cập nhật {{browser}} thất bại", + "updateWithErrors": "Cập nhật hoàn tất với một số lỗi", + "updateWithErrorsDescription": "Tìm thấy {{newVersions}} phiên bản mới, {{failedUpdates}} trình duyệt cập nhật thất bại", + "updateSuccess": "Cập nhật phiên bản trình duyệt thành công", + "updateSuccessDescription": "Tìm thấy {{newVersions}} phiên bản mới trên {{successfulUpdates}} trình duyệt. Tự động tải xuống sẽ bắt đầu sớm.", + "upToDate": "Không tìm thấy phiên bản trình duyệt mới", + "upToDateDescription": "Tất cả phiên bản trình duyệt đều đã cập nhật", + "updateAllFailed": "Cập nhật phiên bản trình duyệt thất bại" + } + }, + "profilePassword": { + "set": { + "title": "Đặt mật khẩu profile", + "description": "Mã hóa dữ liệu trên đĩa cho {{name}}. Bạn sẽ cần mật khẩu này mỗi khi khởi chạy profile.", + "button": "Mã hóa profile" + }, + "unlock": { + "title": "Mở khóa profile", + "description": "Nhập mật khẩu để mở khóa {{name}}.", + "button": "Mở khóa" + }, + "change": { + "title": "Thay đổi mật khẩu profile", + "description": "Mã hóa lại {{name}} bằng mật khẩu mới.", + "button": "Thay đổi mật khẩu" + }, + "remove": { + "title": "Xóa mật khẩu profile", + "description": "Giải mã dữ liệu trên đĩa cho {{name}}. Profile sẽ không còn được bảo vệ bằng mật khẩu.", + "button": "Xóa mật khẩu" + }, + "fields": { + "password": "Mật khẩu", + "currentPassword": "Mật khẩu hiện tại", + "newPassword": "Mật khẩu mới", + "confirm": "Xác nhận mật khẩu", + "confirmPassword": "Xác nhận mật khẩu mới" + }, + "errors": { + "oldPasswordRequired": "Mật khẩu hiện tại là bắt buộc", + "passwordRequired": "Mật khẩu là bắt buộc", + "tooShort": "Mật khẩu phải có ít nhất 8 ký tự", + "mismatch": "Mật khẩu không khớp" + }, + "toasts": { + "set": "Profile đã được bảo vệ bằng mật khẩu", + "changed": "Đã thay đổi mật khẩu profile", + "removed": "Đã xóa mật khẩu profile" + }, + "warnings": { + "forgetWarningTitle": "Quan trọng: mật khẩu này không thể khôi phục", + "forgetWarningBody": "Donut Browser không thể đặt lại, khôi phục hoặc bỏ qua mật khẩu này. Nếu bạn quên, bạn sẽ mất quyền truy cập vĩnh viễn vào dữ liệu profile này." + }, + "modes": { + "set": "Đặt", + "change": "Thay đổi", + "remove": "Xóa", + "validate": "Xác thực" + }, + "verifyDialog": { + "title": "Xác thực mật khẩu profile", + "description": "Nhập mật khẩu profile để xác nhận khớp với mật khẩu đã lưu trên đĩa.", + "submit": "Xác thực", + "matchToast": "Mật khẩu chính xác" + } + }, + "backendErrors": { + "incorrectPassword": "Mật khẩu không đúng", + "lockedOut": "Quá nhiều lần nhập sai. Thử lại sau {{duration}}.", + "lockedOutDuration": { + "seconds": "{{seconds}} giây", + "minutes": "{{minutes}} phút", + "hours": "{{hours}} giờ" + }, + "profileNotFound": "Không tìm thấy profile", + "profileNotProtected": "Profile không được bảo vệ bằng mật khẩu", + "profileAlreadyProtected": "Profile đã được bảo vệ bằng mật khẩu", + "profileRunning": "Không thể thực hiện hành động này khi profile đang chạy", + "profileEphemeral": "Profile tạm thời không thể đặt mật khẩu — dữ liệu sẽ bị xóa khi thoát.", + "profileMissingSalt": "Profile thiếu salt mã hóa", + "profileLocked": "Profile đã bị khóa. Hãy nhập mật khẩu trước.", + "invalidProfileId": "ID profile không hợp lệ", + "passwordTooShort": "Mật khẩu phải có ít nhất {{min}} ký tự", + "proxyNotFound": "Không tìm thấy proxy", + "groupNotFound": "Không tìm thấy nhóm", + "vpnNotFound": "Không tìm thấy VPN", + "extensionNotFound": "Không tìm thấy tiện ích", + "extensionGroupNotFound": "Không tìm thấy nhóm tiện ích", + "cannotModifyCloudManagedProxy": "Không thể chỉnh sửa đồng bộ cho proxy được quản lý bởi đám mây", + "syncLockedByProfile": "Không thể tắt đồng bộ khi đang được sử dụng bởi profile đã đồng bộ", + "syncNotConfigured": "Chưa cấu hình đồng bộ. Đăng nhập hoặc cấu hình máy chủ tự lưu trữ trước.", + "internal": "Đã xảy ra lỗi: {{detail}}", + "invalidLaunchHookUrl": "URL hook khởi chạy không hợp lệ. Sử dụng URL http:// hoặc https:// đầy đủ.", + "cookieDbLocked": "Không thể đọc cookie — cơ sở dữ liệu bị khóa. Đóng trình duyệt và thử lại.", + "cookieDbUnavailable": "Không thể đọc cookie — kho cookie không khả dụng.", + "selfHostedRequiresLogout": "Đăng xuất khỏi tài khoản Donut trước khi cấu hình máy chủ tự lưu trữ." + }, + "rail": { + "profiles": "Profile", + "extensions": "Tiện ích", + "groups": "Nhóm", + "settings": "Cài đặt", + "more": { + "label": "Thêm", + "closeAriaLabel": "Đóng menu", + "importProfile": "Nhập profile", + "importProfileHint": "Đưa profile từ công cụ khác", + "keyboardShortcuts": "Phím tắt", + "keyboardShortcutsHint": "Xem tất cả phím tắt" + }, + "network": "Mạng", + "integrations": "Tích hợp", + "account": "Tài khoản" + }, + "pageTitle": { + "proxies": "Mạng", + "extensions": "Tiện ích", + "groups": "Nhóm", + "vpns": "Mạng", + "settings": "Cài đặt", + "integrations": "Tích hợp", + "account": "Tài khoản", + "import": "Nhập profile", + "shortcuts": "Phím tắt" + }, + "encryption": { + "required": { + "title": "Đồng bộ tạm dừng — cần mật khẩu", + "description": "Dữ liệu mã hóa đã được tải xuống nhưng chưa đặt mật khẩu E2E trên thiết bị này. Mở Cài đặt → Mã hóa và nhập mật khẩu để tiếp tục đồng bộ.", + "openSettings": "Mở cài đặt" + }, + "rollover": { + "startedTitle": "Đang mã hóa lại dữ liệu", + "startedDescription": "Chúng tôi đang tải lại mọi mục đồng bộ dưới mật khẩu mới. Profile trước, sau đó là proxy, nhóm, VPN và tiện ích.", + "progressTitle": "Đang mã hóa lại {{stage}}", + "progressDescription": "{{done}}/{{total}}", + "completedTitle": "Mã hóa lại hoàn tất", + "completedDescription": "Tất cả dữ liệu đồng bộ đã được đóng gói bằng mật khẩu mới.", + "stage": { + "profiles": "profile", + "proxies": "proxy", + "groups": "nhóm", + "vpns": "VPN", + "extensions": "tiện ích", + "extension_groups": "nhóm tiện ích" + } + } + }, + "account": { + "refreshed": "Đã làm mới tài khoản", + "loggedOut": "Đã đăng xuất", + "signedOut": "Đã đăng xuất", + "signedOutDescription": "Đăng nhập để bật đồng bộ đám mây, profile mã hóa và tính năng nhóm.", + "plan": "Gói: {{plan}} · {{period}}", + "refresh": "Làm mới", + "logout": "Đăng xuất", + "signIn": "Đăng nhập", + "fields": { + "plan": "Gói", + "status": "Trạng thái", + "teamRole": "Vai trò nhóm", + "period": "Chu kỳ thanh toán" + }, + "tabs": { + "account": "Tài khoản", + "selfHosted": "Tự lưu trữ" + }, + "selfHosted": { + "title": "Máy chủ đồng bộ tự lưu trữ", + "description": "Trỏ Donut đến máy chủ donut-sync của riêng bạn để đồng bộ profile, proxy, nhóm và tiện ích mà không cần sử dụng đám mây.", + "disabledWhileLoggedIn": "Đồng bộ tự lưu trữ không khả dụng khi bạn đã đăng nhập vào tài khoản Donut. Đăng xuất để sử dụng máy chủ tùy chỉnh.", + "connectionStatus": "Kết nối:", + "statusUnknown": "Chưa kiểm tra", + "testConnection": "Kiểm tra kết nối", + "disconnect": "Ngắt kết nối" + } + }, + "shortcutsPage": { + "title": "Phím tắt", + "description": "Tăng tốc quy trình làm việc với các phím tắt này." + }, + "commandPalette": { + "placeholder": "Nhập lệnh hoặc tìm kiếm...", + "empty": "Không tìm thấy kết quả.", + "groups": { + "navigation": "Điều hướng", + "profiles": "Profile", + "actions": "Hành động", + "profileGroups": "Nhóm profile" + }, + "actions": { + "launchProfile": "Khởi chạy {{name}}", + "stopProfile": "Dừng {{name}}", + "profileInfo": "Thông tin — {{name}}" + } + }, + "shortcuts": { + "openPalette": "Mở bảng lệnh", + "openShortcuts": "Xem phím tắt", + "importProfile": "Nhập profile", + "goProfiles": "Đi đến Profile", + "goProxies": "Đi đến Mạng", + "goExtensions": "Đi đến Tiện ích", + "goGroups": "Đi đến Nhóm", + "goIntegrations": "Đi đến Tích hợp", + "goAccount": "Đi đến Tài khoản", + "goSettings": "Đi đến Cài đặt" + }, + "closeConfirm": { + "title": "Đóng Donut Browser?", + "description": "Bạn muốn thu nhỏ ứng dụng vào khay hệ thống hay thoát?", + "minimize": "Thu nhỏ vào khay", + "quit": "Thoát" + } +}