From c8aa72186e88ae17c63f32a72e0ff9e080240da4 Mon Sep 17 00:00:00 2001 From: Sline Date: Sat, 8 Nov 2025 19:40:38 +0800 Subject: [PATCH] chore: i18n (#5276) * chore: notice i18n * feat: add script to clean up unused i18n keys * chore: cleanup i18n keys * refactor(i18n/proxies): migrate proxies UI to structured locale keys * chore: i18n for rule module * chore: i18n for profile module * chore: i18n for connections module * chore: i18n for settings module * chore: i18n for verge settings * chore: i18n for theme settings * chore: i18n for theme * chore(i18n): components.home.* * chore(i18n): remove unused i18n keys * chore(i18n): components.profile.* * chore(i18n): components.connection * chore(i18n): pages.logs.* * chore(i18n): pages.*.provider * chore(i18n): components.settings.externalCors.* * chore(i18n): components.settings.clash.* * chore(i18n): components.settings.liteMode.* * chore(i18n): components.settings.backup.* * chore(i18n): components.settings.clash.port.* * chore(i18n): components.settings.misc.* * chore(i18n): components.settings.update.* * chore(i18n): components.settings.sysproxy.* * chore(i18n): components.settings.sysproxy.* * chore(i18n): pages.profiles.notices/components.providers.notices * refactor(notice): unify showNotice usage * refactor(notice): add typed showNotice shortcuts, centralize defaults, and simplify subscriptions * refactor: unify showNotice usage * refactor(notice): unify showNotice API * refactor(notice): unify showNotice usage * chore(i18n): components.test.* * chore(i18n): components.settings.dns.* * chore(i18n): components.home.clashInfo.* * chore(i18n): components.home.systemInfo.* * chore(i18n): components.home.ipInfo/traffic.* * chore(i18n): navigation.* * refactor(i18n): remove pages.* namespace and migrate route texts under module-level page keys * chore(i18n): common.* * chore(i18n): common.* * fix: change error handling in patch_profiles_config to return false when a switch is in progress * fix: improve error handling in patch_profiles_config to prevent requests during profile switching * fix: change error handling in patch_profiles_config to return false when a switch is in progress fix: ensure CURRENT_SWITCHING_PROFILE is reset after config updates in perform_config_update and patch_profiles_config * chore(i18n): restructure root-level locale keys into namespaces * chore(i18n): add missing i18n keys * docs: i18n guide * chore: adjust i18n * refactor(i18n): align UI actions and status labels with common keys * refactor(i18n): unify two-name locale namespaces * refactor(i18n/components): unify locale keys and update component references * chore(i18n): add shared and entities namespaces to all locale files * refactor(i18n): consolidate shared and entity namespaces across features * chore(deps): update npm dependencies to ^7.3.5 (#5310) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * refactor(i18n): migrate shared editor modes and consolidate entities namespaces * tmp * refactor(i18n): flatten locales and move theme/validation strings * docs: CONTRIBUTING_i18n.md * refactor(i18n): restructure feedback and profile namespaces for better organization * refactor(i18n): unify settings locale structure and update references * refactor(i18n): reorganize locale keys for home, proxies, rules, connections, logs, unlock, and tests * refactor(i18n/feedback/layout): unify shared toasts & normalize layout namespace * refactor(i18n): centralize common UI strings in shared * refactor(i18n): flatten headers and unify locale schema * refactor(i18n): consolidate duplicate per-feature translations into shared namespace * refactor(i18n): split locales into per-namespace files * style: lint * refactor(i18n): unify unlock UI translations under tests namespace * feat(i18n): add type-checked translation keys * style: eslint import order * feat(i18n): replace ad-hoc loader with rust-i18n backend bundles * chore(prebuild): remove locale-copy step * fix(i18n, notice): propagate runtime params and update cleanup script path * fix(i18n,notice): make locale formatting idempotent and guard early notice translations * fix(i18n): resolve locale aliases and match OS codes correctly * fix(unlock): use i18next-compatible double-brace interpolation in failure notice * fix(i18n): route unlock error notices through translation keys * fix(i18n): i18n types * feat(i18n): localize upgrade notice for Clash core viewer * fix(notice): ensure runtime overrides apply to prefix translations * chore(i18n): replace literal notices with translation keys * chore(i18n): types * chore(i18n): regen typings before formatting to keep keys in sync * chore(i18n): simply labels * chore(i18n): adjust translation * chore: remove eslint-plugin-i18next * chore(i18n): add/refine Korean translations across frontend scopes and Rust backend (#5341) * chore(i18n): translate settings.json (missed in previous pass) (#5343) * chore(i18n): add/refine Korean translations across frontend scopes and Rust backend * chore(i18n): add/refine Korean translations across frontend scopes and Rust backend * fix(i18n-tauri): quote placeholder-leading value in ko.yml to prevent rust_i18n parse panic * chore(i18n): translate settings.json (forgot to include previously) --------- Co-authored-by: rozan <34974262+thelojan@users.noreply.github.com> --- .husky/pre-commit | 13 + crowdin.yml | 4 - docs/CONTRIBUTING_i18n.md | 116 +- eslint.config.ts | 11 + package.json | 2 + scripts/check-unused-i18n.js | 102 -- scripts/cleanup-unused-i18n.mjs | 1321 +++++++++++++++++ scripts/fix-alpha_version.mjs | 2 +- scripts/generate-i18n-keys.mjs | 98 ++ scripts/portable-fixed-webview2.mjs | 9 +- scripts/portable.mjs | 7 +- scripts/prebuild.mjs | 52 +- scripts/release-version.mjs | 3 +- scripts/telegram.mjs | 4 +- scripts/updatelog.mjs | 2 +- scripts/updater-fixed-webview2.mjs | 5 +- scripts/updater.mjs | 5 +- src-tauri/Cargo.lock | 198 ++- src-tauri/Cargo.toml | 1 + src-tauri/locales/ar.yml | 52 + src-tauri/locales/de.yml | 52 + src-tauri/locales/en.yml | 52 + src-tauri/locales/es.yml | 52 + src-tauri/locales/fa.yml | 52 + src-tauri/locales/id.yml | 52 + src-tauri/locales/jp.yml | 52 + src-tauri/locales/ko.yml | 52 + src-tauri/locales/ru.yml | 52 + src-tauri/locales/tr.yml | 52 + src-tauri/locales/tt.yml | 52 + src-tauri/locales/zh.yml | 52 + src-tauri/locales/zhtw.yml | 52 + src-tauri/src/cmd/service.rs | 7 +- src-tauri/src/core/service.rs | 12 +- src-tauri/src/core/tray/menu_def.rs | 62 +- src-tauri/src/core/tray/mod.rs | 16 +- src-tauri/src/lib.rs | 3 + src-tauri/src/utils/i18n.rs | 171 +-- src-tauri/src/utils/notification.rs | 53 +- src-tauri/tauri.conf.json | 2 +- src/components/base/NoticeManager.tsx | 59 +- src/components/base/base-empty.tsx | 19 +- src/components/base/base-search-box.tsx | 12 +- .../base/base-styled-text-field.tsx | 2 +- .../common/traffic-error-boundary.tsx | 19 +- .../connection/connection-detail.tsx | 51 +- src/components/connection/connection-item.tsx | 10 +- .../connection/connection-table.tsx | 25 +- src/components/home/clash-info-card.tsx | 12 +- src/components/home/clash-mode-card.tsx | 59 +- src/components/home/current-proxy-card.tsx | 32 +- .../home/enhanced-canvas-traffic-graph.tsx | 8 +- .../home/enhanced-traffic-stats.tsx | 12 +- src/components/home/home-profile-card.tsx | 20 +- src/components/home/ip-info-card.tsx | 41 +- src/components/home/proxy-tun-card.tsx | 28 +- src/components/home/system-info-card.tsx | 54 +- src/components/home/test-card.tsx | 6 +- src/components/layout/layout-traffic.tsx | 6 +- src/components/profile/confirm-viewer.tsx | 4 +- src/components/profile/editor-viewer.tsx | 28 +- src/components/profile/file-input.tsx | 2 +- .../profile/groups-editor-viewer.tsx | 199 ++- src/components/profile/log-viewer.tsx | 4 +- src/components/profile/profile-item.tsx | 179 ++- src/components/profile/profile-more.tsx | 30 +- src/components/profile/profile-viewer.tsx | 70 +- .../profile/proxies-editor-viewer.tsx | 28 +- .../profile/rules-editor-viewer.tsx | 99 +- src/components/proxy/provider-button.tsx | 51 +- src/components/proxy/proxy-chain.tsx | 37 +- src/components/proxy/proxy-groups.tsx | 8 +- src/components/proxy/proxy-head.tsx | 26 +- src/components/proxy/proxy-item-mini.tsx | 4 +- src/components/proxy/proxy-render.tsx | 2 +- src/components/rule/provider-button.tsx | 40 +- .../setting/mods/backup-config-viewer.tsx | 44 +- .../setting/mods/backup-table-viewer.tsx | 56 +- src/components/setting/mods/backup-viewer.tsx | 14 +- .../setting/mods/clash-core-viewer.tsx | 46 +- .../setting/mods/clash-port-viewer.tsx | 38 +- src/components/setting/mods/config-viewer.tsx | 4 +- .../setting/mods/controller-viewer.tsx | 64 +- src/components/setting/mods/dns-viewer.tsx | 144 +- .../setting/mods/external-controller-cors.tsx | 24 +- src/components/setting/mods/hotkey-input.tsx | 2 +- src/components/setting/mods/hotkey-viewer.tsx | 30 +- src/components/setting/mods/layout-viewer.tsx | 114 +- .../setting/mods/lite-mode-viewer.tsx | 33 +- .../setting/mods/local-backup-actions.tsx | 12 +- src/components/setting/mods/misc-viewer.tsx | 97 +- .../setting/mods/network-interface-viewer.tsx | 26 +- .../setting/mods/password-input.tsx | 8 +- .../setting/mods/sysproxy-viewer.tsx | 87 +- .../setting/mods/theme-mode-switch.tsx | 2 +- src/components/setting/mods/theme-viewer.tsx | 83 +- src/components/setting/mods/tun-viewer.tsx | 32 +- src/components/setting/mods/update-viewer.tsx | 16 +- src/components/setting/mods/web-ui-item.tsx | 14 +- src/components/setting/mods/web-ui-viewer.tsx | 10 +- src/components/setting/setting-clash.tsx | 71 +- src/components/setting/setting-system.tsx | 28 +- .../setting/setting-verge-advanced.tsx | 70 +- .../setting/setting-verge-basic.tsx | 63 +- .../shared/ProxyControlSwitches.tsx | 39 +- src/components/test/test-item.tsx | 4 +- src/components/test/test-viewer.tsx | 18 +- src/hooks/use-system-state.ts | 13 +- src/hooks/useServiceInstaller.ts | 22 +- src/hooks/useServiceUninstaller.ts | 27 +- src/locales/ar.json | 463 ------ src/locales/ar/connections.json | 28 + src/locales/ar/home.json | 138 ++ src/locales/ar/index.ts | 25 + src/locales/ar/layout.json | 21 + src/locales/ar/logs.json | 5 + src/locales/ar/profiles.json | 182 +++ src/locales/ar/proxies.json | 90 ++ src/locales/ar/rules.json | 82 + src/locales/ar/settings.json | 573 +++++++ src/locales/ar/shared.json | 129 ++ src/locales/ar/tests.json | 53 + src/locales/de.json | 563 ------- src/locales/de/connections.json | 28 + src/locales/de/home.json | 138 ++ src/locales/de/index.ts | 25 + src/locales/de/layout.json | 21 + src/locales/de/logs.json | 5 + src/locales/de/profiles.json | 182 +++ src/locales/de/proxies.json | 90 ++ src/locales/de/rules.json | 82 + src/locales/de/settings.json | 573 +++++++ src/locales/de/shared.json | 129 ++ src/locales/de/tests.json | 53 + src/locales/en.json | 718 --------- src/locales/en/connections.json | 28 + src/locales/en/home.json | 138 ++ src/locales/en/index.ts | 25 + src/locales/en/layout.json | 21 + src/locales/en/logs.json | 5 + src/locales/en/profiles.json | 182 +++ src/locales/en/proxies.json | 90 ++ src/locales/en/rules.json | 82 + src/locales/en/settings.json | 573 +++++++ src/locales/en/shared.json | 129 ++ src/locales/en/tests.json | 53 + src/locales/es.json | 563 ------- src/locales/es/connections.json | 28 + src/locales/es/home.json | 138 ++ src/locales/es/index.ts | 25 + src/locales/es/layout.json | 21 + src/locales/es/logs.json | 5 + src/locales/es/profiles.json | 182 +++ src/locales/es/proxies.json | 90 ++ src/locales/es/rules.json | 82 + src/locales/es/settings.json | 573 +++++++ src/locales/es/shared.json | 129 ++ src/locales/es/tests.json | 53 + src/locales/fa.json | 460 ------ src/locales/fa/connections.json | 28 + src/locales/fa/home.json | 138 ++ src/locales/fa/index.ts | 25 + src/locales/fa/layout.json | 21 + src/locales/fa/logs.json | 5 + src/locales/fa/profiles.json | 182 +++ src/locales/fa/proxies.json | 90 ++ src/locales/fa/rules.json | 82 + src/locales/fa/settings.json | 573 +++++++ src/locales/fa/shared.json | 129 ++ src/locales/fa/tests.json | 53 + src/locales/id.json | 459 ------ src/locales/id/connections.json | 28 + src/locales/id/home.json | 138 ++ src/locales/id/index.ts | 25 + src/locales/id/layout.json | 21 + src/locales/id/logs.json | 5 + src/locales/id/profiles.json | 182 +++ src/locales/id/proxies.json | 90 ++ src/locales/id/rules.json | 82 + src/locales/id/settings.json | 573 +++++++ src/locales/id/shared.json | 129 ++ src/locales/id/tests.json | 53 + src/locales/jp.json | 574 ------- src/locales/jp/connections.json | 28 + src/locales/jp/home.json | 138 ++ src/locales/jp/index.ts | 25 + src/locales/jp/layout.json | 21 + src/locales/jp/logs.json | 5 + src/locales/jp/profiles.json | 182 +++ src/locales/jp/proxies.json | 90 ++ src/locales/jp/rules.json | 82 + src/locales/jp/settings.json | 573 +++++++ src/locales/jp/shared.json | 129 ++ src/locales/jp/tests.json | 53 + src/locales/ko.json | 403 ----- src/locales/ko/connections.json | 28 + src/locales/ko/home.json | 138 ++ src/locales/ko/index.ts | 25 + src/locales/ko/layout.json | 21 + src/locales/ko/logs.json | 5 + src/locales/ko/profiles.json | 182 +++ src/locales/ko/proxies.json | 90 ++ src/locales/ko/rules.json | 82 + src/locales/ko/settings.json | 573 +++++++ src/locales/ko/shared.json | 129 ++ src/locales/ko/tests.json | 53 + src/locales/ru.json | 603 -------- src/locales/ru/connections.json | 28 + src/locales/ru/home.json | 138 ++ src/locales/ru/index.ts | 25 + src/locales/ru/layout.json | 21 + src/locales/ru/logs.json | 5 + src/locales/ru/profiles.json | 182 +++ src/locales/ru/proxies.json | 90 ++ src/locales/ru/rules.json | 82 + src/locales/ru/settings.json | 573 +++++++ src/locales/ru/shared.json | 129 ++ src/locales/ru/tests.json | 53 + src/locales/tr.json | 619 -------- src/locales/tr/connections.json | 28 + src/locales/tr/home.json | 138 ++ src/locales/tr/index.ts | 25 + src/locales/tr/layout.json | 21 + src/locales/tr/logs.json | 5 + src/locales/tr/profiles.json | 182 +++ src/locales/tr/proxies.json | 90 ++ src/locales/tr/rules.json | 82 + src/locales/tr/settings.json | 573 +++++++ src/locales/tr/shared.json | 129 ++ src/locales/tr/tests.json | 53 + src/locales/tt.json | 459 ------ src/locales/tt/connections.json | 28 + src/locales/tt/home.json | 138 ++ src/locales/tt/index.ts | 25 + src/locales/tt/layout.json | 21 + src/locales/tt/logs.json | 5 + src/locales/tt/profiles.json | 182 +++ src/locales/tt/proxies.json | 90 ++ src/locales/tt/rules.json | 82 + src/locales/tt/settings.json | 573 +++++++ src/locales/tt/shared.json | 129 ++ src/locales/tt/tests.json | 53 + src/locales/zh.json | 719 --------- src/locales/zh/connections.json | 28 + src/locales/zh/home.json | 138 ++ src/locales/zh/index.ts | 25 + src/locales/zh/layout.json | 21 + src/locales/zh/logs.json | 5 + src/locales/zh/profiles.json | 182 +++ src/locales/zh/proxies.json | 90 ++ src/locales/zh/rules.json | 82 + src/locales/zh/settings.json | 573 +++++++ src/locales/zh/shared.json | 129 ++ src/locales/zh/tests.json | 53 + src/locales/zhtw.json | 715 --------- src/locales/zhtw/connections.json | 28 + src/locales/zhtw/home.json | 138 ++ src/locales/zhtw/index.ts | 25 + src/locales/zhtw/layout.json | 21 + src/locales/zhtw/logs.json | 5 + src/locales/zhtw/profiles.json | 182 +++ src/locales/zhtw/proxies.json | 90 ++ src/locales/zhtw/rules.json | 82 + src/locales/zhtw/settings.json | 573 +++++++ src/locales/zhtw/shared.json | 129 ++ src/locales/zhtw/tests.json | 53 + src/pages/_layout.tsx | 6 +- src/pages/_layout/notificationHandlers.ts | 74 +- src/pages/_routers.tsx | 16 +- src/pages/connections.tsx | 89 +- src/pages/home.tsx | 38 +- src/pages/logs.tsx | 23 +- src/pages/profiles.tsx | 114 +- src/pages/proxies.tsx | 29 +- src/pages/rules.tsx | 2 +- src/pages/settings.tsx | 10 +- src/pages/test.tsx | 6 +- src/pages/unlock.tsx | 42 +- src/services/cmds.ts | 16 +- src/services/i18n.ts | 43 +- src/services/noticeService.ts | 362 ++++- src/types/generated/i18n-keys.ts | 728 +++++++++ src/types/generated/i18n-resources.ts | 1308 ++++++++++++++++ src/types/i18next.d.ts | 11 + src/types/react-i18next.d.ts | 39 + src/{services => types}/types.d.ts | 0 286 files changed, 24243 insertions(+), 8867 deletions(-) delete mode 100644 crowdin.yml delete mode 100644 scripts/check-unused-i18n.js create mode 100644 scripts/cleanup-unused-i18n.mjs create mode 100644 scripts/generate-i18n-keys.mjs create mode 100644 src-tauri/locales/ar.yml create mode 100644 src-tauri/locales/de.yml create mode 100644 src-tauri/locales/en.yml create mode 100644 src-tauri/locales/es.yml create mode 100644 src-tauri/locales/fa.yml create mode 100644 src-tauri/locales/id.yml create mode 100644 src-tauri/locales/jp.yml create mode 100644 src-tauri/locales/ko.yml create mode 100644 src-tauri/locales/ru.yml create mode 100644 src-tauri/locales/tr.yml create mode 100644 src-tauri/locales/tt.yml create mode 100644 src-tauri/locales/zh.yml create mode 100644 src-tauri/locales/zhtw.yml delete mode 100644 src/locales/ar.json create mode 100644 src/locales/ar/connections.json create mode 100644 src/locales/ar/home.json create mode 100644 src/locales/ar/index.ts create mode 100644 src/locales/ar/layout.json create mode 100644 src/locales/ar/logs.json create mode 100644 src/locales/ar/profiles.json create mode 100644 src/locales/ar/proxies.json create mode 100644 src/locales/ar/rules.json create mode 100644 src/locales/ar/settings.json create mode 100644 src/locales/ar/shared.json create mode 100644 src/locales/ar/tests.json delete mode 100644 src/locales/de.json create mode 100644 src/locales/de/connections.json create mode 100644 src/locales/de/home.json create mode 100644 src/locales/de/index.ts create mode 100644 src/locales/de/layout.json create mode 100644 src/locales/de/logs.json create mode 100644 src/locales/de/profiles.json create mode 100644 src/locales/de/proxies.json create mode 100644 src/locales/de/rules.json create mode 100644 src/locales/de/settings.json create mode 100644 src/locales/de/shared.json create mode 100644 src/locales/de/tests.json delete mode 100644 src/locales/en.json create mode 100644 src/locales/en/connections.json create mode 100644 src/locales/en/home.json create mode 100644 src/locales/en/index.ts create mode 100644 src/locales/en/layout.json create mode 100644 src/locales/en/logs.json create mode 100644 src/locales/en/profiles.json create mode 100644 src/locales/en/proxies.json create mode 100644 src/locales/en/rules.json create mode 100644 src/locales/en/settings.json create mode 100644 src/locales/en/shared.json create mode 100644 src/locales/en/tests.json delete mode 100644 src/locales/es.json create mode 100644 src/locales/es/connections.json create mode 100644 src/locales/es/home.json create mode 100644 src/locales/es/index.ts create mode 100644 src/locales/es/layout.json create mode 100644 src/locales/es/logs.json create mode 100644 src/locales/es/profiles.json create mode 100644 src/locales/es/proxies.json create mode 100644 src/locales/es/rules.json create mode 100644 src/locales/es/settings.json create mode 100644 src/locales/es/shared.json create mode 100644 src/locales/es/tests.json delete mode 100644 src/locales/fa.json create mode 100644 src/locales/fa/connections.json create mode 100644 src/locales/fa/home.json create mode 100644 src/locales/fa/index.ts create mode 100644 src/locales/fa/layout.json create mode 100644 src/locales/fa/logs.json create mode 100644 src/locales/fa/profiles.json create mode 100644 src/locales/fa/proxies.json create mode 100644 src/locales/fa/rules.json create mode 100644 src/locales/fa/settings.json create mode 100644 src/locales/fa/shared.json create mode 100644 src/locales/fa/tests.json delete mode 100644 src/locales/id.json create mode 100644 src/locales/id/connections.json create mode 100644 src/locales/id/home.json create mode 100644 src/locales/id/index.ts create mode 100644 src/locales/id/layout.json create mode 100644 src/locales/id/logs.json create mode 100644 src/locales/id/profiles.json create mode 100644 src/locales/id/proxies.json create mode 100644 src/locales/id/rules.json create mode 100644 src/locales/id/settings.json create mode 100644 src/locales/id/shared.json create mode 100644 src/locales/id/tests.json delete mode 100644 src/locales/jp.json create mode 100644 src/locales/jp/connections.json create mode 100644 src/locales/jp/home.json create mode 100644 src/locales/jp/index.ts create mode 100644 src/locales/jp/layout.json create mode 100644 src/locales/jp/logs.json create mode 100644 src/locales/jp/profiles.json create mode 100644 src/locales/jp/proxies.json create mode 100644 src/locales/jp/rules.json create mode 100644 src/locales/jp/settings.json create mode 100644 src/locales/jp/shared.json create mode 100644 src/locales/jp/tests.json delete mode 100644 src/locales/ko.json create mode 100644 src/locales/ko/connections.json create mode 100644 src/locales/ko/home.json create mode 100644 src/locales/ko/index.ts create mode 100644 src/locales/ko/layout.json create mode 100644 src/locales/ko/logs.json create mode 100644 src/locales/ko/profiles.json create mode 100644 src/locales/ko/proxies.json create mode 100644 src/locales/ko/rules.json create mode 100644 src/locales/ko/settings.json create mode 100644 src/locales/ko/shared.json create mode 100644 src/locales/ko/tests.json delete mode 100644 src/locales/ru.json create mode 100644 src/locales/ru/connections.json create mode 100644 src/locales/ru/home.json create mode 100644 src/locales/ru/index.ts create mode 100644 src/locales/ru/layout.json create mode 100644 src/locales/ru/logs.json create mode 100644 src/locales/ru/profiles.json create mode 100644 src/locales/ru/proxies.json create mode 100644 src/locales/ru/rules.json create mode 100644 src/locales/ru/settings.json create mode 100644 src/locales/ru/shared.json create mode 100644 src/locales/ru/tests.json delete mode 100644 src/locales/tr.json create mode 100644 src/locales/tr/connections.json create mode 100644 src/locales/tr/home.json create mode 100644 src/locales/tr/index.ts create mode 100644 src/locales/tr/layout.json create mode 100644 src/locales/tr/logs.json create mode 100644 src/locales/tr/profiles.json create mode 100644 src/locales/tr/proxies.json create mode 100644 src/locales/tr/rules.json create mode 100644 src/locales/tr/settings.json create mode 100644 src/locales/tr/shared.json create mode 100644 src/locales/tr/tests.json delete mode 100644 src/locales/tt.json create mode 100644 src/locales/tt/connections.json create mode 100644 src/locales/tt/home.json create mode 100644 src/locales/tt/index.ts create mode 100644 src/locales/tt/layout.json create mode 100644 src/locales/tt/logs.json create mode 100644 src/locales/tt/profiles.json create mode 100644 src/locales/tt/proxies.json create mode 100644 src/locales/tt/rules.json create mode 100644 src/locales/tt/settings.json create mode 100644 src/locales/tt/shared.json create mode 100644 src/locales/tt/tests.json delete mode 100644 src/locales/zh.json create mode 100644 src/locales/zh/connections.json create mode 100644 src/locales/zh/home.json create mode 100644 src/locales/zh/index.ts create mode 100644 src/locales/zh/layout.json create mode 100644 src/locales/zh/logs.json create mode 100644 src/locales/zh/profiles.json create mode 100644 src/locales/zh/proxies.json create mode 100644 src/locales/zh/rules.json create mode 100644 src/locales/zh/settings.json create mode 100644 src/locales/zh/shared.json create mode 100644 src/locales/zh/tests.json delete mode 100644 src/locales/zhtw.json create mode 100644 src/locales/zhtw/connections.json create mode 100644 src/locales/zhtw/home.json create mode 100644 src/locales/zhtw/index.ts create mode 100644 src/locales/zhtw/layout.json create mode 100644 src/locales/zhtw/logs.json create mode 100644 src/locales/zhtw/profiles.json create mode 100644 src/locales/zhtw/proxies.json create mode 100644 src/locales/zhtw/rules.json create mode 100644 src/locales/zhtw/settings.json create mode 100644 src/locales/zhtw/shared.json create mode 100644 src/locales/zhtw/tests.json create mode 100644 src/types/generated/i18n-keys.ts create mode 100644 src/types/generated/i18n-resources.ts create mode 100644 src/types/i18next.d.ts create mode 100644 src/types/react-i18next.d.ts rename src/{services => types}/types.d.ts (100%) diff --git a/.husky/pre-commit b/.husky/pre-commit index ee8dc1cec..4c21a0453 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -9,6 +9,19 @@ if ! command -v pnpm >/dev/null 2>&1; then exit 1 fi +LOCALE_DIFF="$(git diff --cached --name-only --diff-filter=ACMR | grep -E '^src/locales/' || true)" +if [ -n "$LOCALE_DIFF" ]; then + echo "[pre-commit] Locale changes detected. Regenerating i18n types..." + pnpm i18n:types + if [ -d src/types/generated ]; then + echo "[pre-commit] Staging regenerated i18n type artifacts..." + git add src/types/generated + fi +fi + +echo "[pre-commit] Running pnpm format before lint..." +pnpm format + echo "[pre-commit] Running lint-staged for JS/TS files..." pnpm exec lint-staged diff --git a/crowdin.yml b/crowdin.yml deleted file mode 100644 index 6063f529c..000000000 --- a/crowdin.yml +++ /dev/null @@ -1,4 +0,0 @@ -files: - - source: /src/locales/en.json - translation: /src/locales - multilingual: 1 diff --git a/docs/CONTRIBUTING_i18n.md b/docs/CONTRIBUTING_i18n.md index 6e97e4630..2d9e6674f 100644 --- a/docs/CONTRIBUTING_i18n.md +++ b/docs/CONTRIBUTING_i18n.md @@ -1,81 +1,79 @@ # CONTRIBUTING — i18n -Thank you for considering contributing to our localization work — your help is appreciated. +Thanks for helping localize Clash Verge Rev. This guide reflects the current architecture, where the React frontend and the Tauri backend keep their translation bundles separate. Follow the steps below to keep both sides in sync without stepping on each other. -Quick overview +## Quick workflow -- cvr-i18 is a CLI that helps manage simple top-level JSON locale files: - - Detect duplicated top-level keys - - Find keys missing versus a base file (default: en.json) - - Export missing entries for translators - - Reorder keys to match the base file for predictable diffs - - Operate on a directory or a single file +- Update the language folder under `src/locales//`; use `src/locales/en/` as the canonical reference for keys and intent. +- Run `pnpm format:i18n` to align structure and `pnpm i18n:types` to refresh generated typings. +- If you touch backend copy, edit the matching YAML file in `src-tauri/locales/.yml`. +- Preview UI changes with `pnpm dev` (desktop shell) or `pnpm web:dev` (web only). +- Keep PRs focused and add screenshots whenever layout could be affected by text length. -Get the CLI (No binary provided yet) +## Frontend locale structure -```bash -git clone https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli -cd clash-verge-rev-i18n-cli -cargo install --path . -# or -cargo install --git https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli +Each locale folder mirrors the namespaces under `src/locales/en/`: + +``` +src/locales/ + en/ + connections.json + home.json + shared.json + ... + index.ts + zh/ + ... ``` -Common commands +- JSON files map to namespaces (for example `home.json` → `home.*`). Keep keys scoped to the file they belong to. +- `shared.json` stores reusable vocabulary (buttons, validations, etc.); feature-specific wording should live in the relevant namespace. +- `index.ts` re-exports a `resources` object that aggregates the namespace JSON files. When adding or removing namespaces, mirror the pattern from `src/locales/en/index.ts`. +- Frontend bundles are lazy-loaded by `src/services/i18n.ts`. Only languages listed in `supportedLanguages` are fetched at runtime, so append new codes there when you add a locale. -- Show help: `cvr-i18` -- Directory (auto-detects `./locales` or `./src/locales`): `cvr-i18 -d /path/to/locales` -- Check duplicates: `cvr-i18 -k` -- Check missing keys: `cvr-i18 -m` -- Export missing keys: `cvr-i18 -m -e ./exports` -- Sort keys to base file: `cvr-i18 -s` -- Use a base file: `cvr-i18 -b base.json` -- Single file: `cvr-i18 -f locales/zh.json` +Because backend translations now live in their own directory, you no longer need to run `pnpm prebuild` just to sync locales—the frontend folder is the sole source of truth for web bundles. -Options (short) +## Tooling for frontend contributors -- `-d, --directory ` -- `-f, --file ` -- `-k, --duplicated-key` -- `-m, --missing-key` -- `-e, --export ` -- `-s, --sort` -- `-b, --base ` +- `pnpm format:i18n` → `node scripts/cleanup-unused-i18n.mjs --align --apply`. It aligns key ordering, removes unused entries, and keeps all locales in lock-step with English. +- `pnpm node scripts/cleanup-unused-i18n.mjs` (without flags) performs a dry-run audit. Use it to inspect missing or extra keys before committing. +- `pnpm i18n:types` regenerates `src/types/generated/i18n-keys.ts` and `src/types/generated/i18n-resources.ts`, ensuring TypeScript catches invalid key usage. +- For dynamic keys that the analyzer cannot statically detect, add explicit references in code or update the script whitelist to avoid false positives. -Exit codes +## Backend (Tauri) locale bundles -- `0` — success (no issues) -- `1` — issues found (duplicates/missing) -- `2` — error (IO/parse/runtime) +Native UI strings (tray menu, notifications, dialogs) use `rust-i18n` with YAML bundles stored in `src-tauri/locales/.yml`. These files are completely independent from the frontend JSON modules. -How to contribute (recommended steps) +- Keep `en.yml` semantically aligned with the Simplified Chinese baseline (`zh.yml`). Other locales may temporarily copy English if no translation is available yet. +- When a backend feature introduces new strings, update every YAML file to keep the key set consistent. Missing keys fall back to the default language (`zh`), so catching gaps early avoids mixed-language output. +- Rust code resolves the active language through `src-tauri/src/utils/i18n.rs`. No additional build step is required after editing YAML files; `tauri dev` and `tauri build` pick them up automatically. -- Start small: fix typos, improve phrasing, or refine tone and consistency. -- Run the CLI against your locale files to detect duplicates or missing keys. -- Export starter JSONs for translators with `-m -e `. -- Prefer incremental PRs or draft PRs; leave a comment on the issue if you want guidance. -- Open an issue to report missing strings, UI context, or localization bugs. -- Add or improve docs and tests to make future contributions easier. +## Adding a new language -PR checklist +1. Duplicate `src/locales/en/` into `src/locales//` and translate the JSON files while preserving key structure. +2. Update the locale’s `index.ts` to import every namespace. Matching the English file is the easiest way to avoid missing exports. +3. Append the language code to `supportedLanguages` in `src/services/i18n.ts`. +4. If the backend should expose the language, create `src-tauri/locales/.yml` and translate the keys used in existing YAML files. +5. Adjust `crowdin.yml` if the locale requires a special mapping for Crowdin. +6. Run `pnpm format:i18n`, `pnpm i18n:types`, and (optionally) `pnpm node scripts/cleanup-unused-i18n.mjs` in dry-run mode to confirm structure. -- Keep JSON files UTF-8 encoded. -- Follow the repo’s locale file structure and naming conventions. -- Reorder keys to match the base file (`-s`) for minimal diffs. -- Test translations in a local dev build before opening a PR. -- Reference related issues and explain any context for translations or changes. +## Authoring guidelines -Notes +- **Reuse shared vocabulary** before introducing new phrases—check `shared.json` for common actions, statuses, and labels. +- **Prefer semantic keys** (`systemProxy`, `updateInterval`, `autoRefresh`) over positional ones (`item1`, `dialogTitle2`). +- **Document placeholders** using `{{placeholder}}` and ensure components supply the required values. +- **Group keys by UI responsibility** inside each namespace (`page`, `sections`, `forms`, `actions`, `tooltips`, `notifications`, `errors`, `tables`, `statuses`, etc.). +- **Keep strings concise** to avoid layout issues. If a translation needs more context, leave a PR note so reviewers can verify the UI. -- The tool expects simple top-level JSON key/value maps. -- Exported JSONs are starter files for translators (fill in values, keep keys). -- Sorting keeps diffs consistent and reviewable. +## Testing & QA -Repository -https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli +- Launch the desktop shell with `pnpm dev` (or `pnpm web:dev`) and navigate through the affected views to confirm translations load and layouts behave. +- Run `pnpm test` if you touched code that consumes translations or adjusts formatting logic. +- For backend changes, trigger the relevant tray actions or notifications to verify the updated copy. +- Note any remaining untranslated sections or layout concerns in your PR description so maintainers can follow up. -## Feedback & Contributions +## Feedback & support -- For tool usage issues or feedback: please open an Issue in the [repository](https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli) so it can be tracked and addressed. -- For localization contributions (translations, fixes, context notes, etc.): submit a PR or Issue in this repository and include examples, context, and testing instructions when possible. -- If you need help or a review, leave a comment on your submission requesting assistance. +- File an issue for missing context, tooling bugs, or localization gaps so we can track them. +- PRs that touch UI should include screenshots or GIFs whenever text length may affect layout. +- Mention the commands you ran (formatting, type generation, tests) in the PR checklist. If you need extra context or review help, request it via a PR comment. diff --git a/eslint.config.ts b/eslint.config.ts index 8342ff0f0..f8f51a631 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -17,6 +17,7 @@ export default defineConfig([ plugins: { js: eslintJS, + // @ts-expect-error -- https://github.com/typescript-eslint/typescript-eslint/issues/11543 "react-hooks": pluginReactHooks, // @ts-expect-error -- https://github.com/un-ts/eslint-plugin-import-x/issues/421 "import-x": pluginImportX, @@ -132,4 +133,14 @@ export default defineConfig([ "prettier/prettier": "warn", }, }, + { + files: ["scripts/**/*.{js,mjs,cjs}", "scripts-workflow/**/*.{js,mjs,cjs}"], + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, ]); diff --git a/package.json b/package.json index bdbe35bc0..fadc52056 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "lint:fix": "eslint -c eslint.config.ts --max-warnings=0 --cache --cache-location .eslintcache --fix src", "format": "prettier --write .", "format:check": "prettier --check .", + "format:i18n": "node scripts/cleanup-unused-i18n.mjs --align --apply", + "i18n:types": "node scripts/generate-i18n-keys.mjs", "typecheck": "tsc --noEmit", "test": "vitest run" }, diff --git a/scripts/check-unused-i18n.js b/scripts/check-unused-i18n.js deleted file mode 100644 index 95958df4a..000000000 --- a/scripts/check-unused-i18n.js +++ /dev/null @@ -1,102 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const LOCALES_DIR = path.resolve(__dirname, "../src/locales"); -const SRC_DIRS = [ - path.resolve(__dirname, "../src"), - path.resolve(__dirname, "../src-tauri"), -]; -const exts = [".js", ".ts", ".tsx", ".jsx", ".vue", ".rs"]; - -// 递归获取所有文件 -function getAllFiles(dir, exts) { - let files = []; - fs.readdirSync(dir).forEach((file) => { - const full = path.join(dir, file); - if (fs.statSync(full).isDirectory()) { - files = files.concat(getAllFiles(full, exts)); - } else if (exts.includes(path.extname(full))) { - files.push(full); - } - }); - return files; -} - -// 读取所有源码内容为一个大字符串 -function getAllSourceContent() { - const files = SRC_DIRS.flatMap((dir) => getAllFiles(dir, exts)); - return files.map((f) => fs.readFileSync(f, "utf8")).join("\n"); -} - -// 白名单 key,不检查这些 key 是否被使用 -const WHITELIST_KEYS = [ - "theme.light", - "theme.dark", - "theme.system", - "Already Using Latest Core Version", -]; - -// 主流程 -function processI18nFile(i18nPath, lang, allSource) { - const i18n = JSON.parse(fs.readFileSync(i18nPath, "utf8")); - const keys = Object.keys(i18n); - - const used = {}; - const unused = []; - - let checked = 0; - const total = keys.length; - keys.forEach((key) => { - if (WHITELIST_KEYS.includes(key)) { - used[key] = i18n[key]; - } else { - // 只查找一次 - const regex = new RegExp(`["'\`]${key}["'\`]`); - if (regex.test(allSource)) { - used[key] = i18n[key]; - } else { - unused.push(key); - } - } - checked++; - if (checked % 20 === 0 || checked === total) { - const percent = ((checked / total) * 100).toFixed(1); - process.stdout.write( - `\r[${lang}] Progress: ${checked}/${total} (${percent}%)`, - ); - if (checked === total) process.stdout.write("\n"); - } - }); - - // 输出未使用的 key - console.log(`\n[${lang}] Unused keys:`, unused); - - // 备份原文件 - const oldPath = i18nPath + ".old"; - fs.renameSync(i18nPath, oldPath); - - // 写入精简后的 i18n 文件(保留原文件名) - fs.writeFileSync(i18nPath, JSON.stringify(used, null, 2), "utf8"); - console.log( - `[${lang}] Cleaned i18n file written to src/locales/${path.basename(i18nPath)}`, - ); - console.log(`[${lang}] Original file backed up as ${path.basename(oldPath)}`); -} - -function main() { - // 支持 zhtw.json、zh-tw.json、zh_CN.json 等 - const files = fs - .readdirSync(LOCALES_DIR) - .filter((f) => /^[a-z0-9\-_]+\.json$/i.test(f) && !f.endsWith(".old")); - const allSource = getAllSourceContent(); - files.forEach((file) => { - const lang = path.basename(file, ".json"); - processI18nFile(path.join(LOCALES_DIR, file), lang, allSource); - }); -} - -main(); diff --git a/scripts/cleanup-unused-i18n.mjs b/scripts/cleanup-unused-i18n.mjs new file mode 100644 index 000000000..ce8af9c3d --- /dev/null +++ b/scripts/cleanup-unused-i18n.mjs @@ -0,0 +1,1321 @@ +#!/usr/bin/env node + +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +import ts from "typescript"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const LOCALES_DIR = path.resolve(__dirname, "../src/locales"); +const TAURI_LOCALES_DIR = path.resolve(__dirname, "../src-tauri/locales"); +const DEFAULT_SOURCE_DIRS = [ + path.resolve(__dirname, "../src"), + path.resolve(__dirname, "../src-tauri"), +]; +const EXCLUDE_USAGE_DIRS = [LOCALES_DIR, TAURI_LOCALES_DIR]; +const DEFAULT_BASELINE_LANG = "en"; +const IGNORE_DIR_NAMES = new Set([ + ".git", + ".idea", + ".turbo", + ".next", + ".cache", + ".pnpm", + "node_modules", + "dist", + "build", + "coverage", + "out", + "target", + "gen", + "packages", + "release", + "logs", + "__pycache__", +]); +const SUPPORTED_EXTENSIONS = new Set([ + ".ts", + ".tsx", + ".js", + ".jsx", + ".mjs", + ".cjs", + ".vue", + ".json", +]); + +const TS_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]); + +const KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+$/; +const TEMPLATE_PREFIX_PATTERN = + /^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)*\.$/; + +const IGNORED_KEY_PREFIXES = new Set([ + "text", + "primary", + "secondary", + "error", + "warning", + "success", + "info", + "background", + "grey", + "option", + "action", + "example", + "chrome", + "localhost", + "www", + "pac", + "V2", + "v2", + "v1", +]); + +const NOTICE_METHOD_NAMES = new Set(["success", "error", "info", "warning"]); +const NOTICE_SERVICE_IDENTIFIERS = new Set([ + "@/services/noticeService", + "./noticeService", + "../services/noticeService", +]); + +const WHITELIST_KEYS = new Set([ + "theme.light", + "theme.dark", + "theme.system", + "Already Using Latest Core Version", +]); + +const MAX_PREVIEW_ENTRIES = 40; +const dynamicKeyCache = new Map(); +const fileUsageCache = new Map(); + +function printUsage() { + console.log(`Usage: pnpm node scripts/cleanup-unused-i18n.mjs [options] + +Options: + --apply Write locale files with unused keys removed (default: report only) + --align Align locale structure/order using the baseline locale + --baseline Baseline locale file name (default: ${DEFAULT_BASELINE_LANG}) + --keep-extra Preserve keys that exist only in non-baseline locales when aligning + --no-backup Skip creating \`.bak\` backups when applying changes + --report Write a JSON report to the given path + --src Include an additional source directory (repeatable) + --help Show this message +`); +} + +function parseArgs(argv) { + const options = { + apply: false, + backup: true, + reportPath: null, + extraSources: [], + align: false, + baseline: DEFAULT_BASELINE_LANG, + keepExtra: false, + }; + + for (let i = 0; i < argv.length; i += 1) { + const arg = argv[i]; + switch (arg) { + case "--apply": + options.apply = true; + break; + case "--align": + options.align = true; + break; + case "--keep-extra": + options.keepExtra = true; + break; + case "--no-backup": + options.backup = false; + break; + case "--report": { + const next = argv[i + 1]; + if (!next) { + throw new Error("--report requires a file path"); + } + options.reportPath = path.resolve(process.cwd(), next); + i += 1; + break; + } + case "--baseline": { + const next = argv[i + 1]; + if (!next) { + throw new Error("--baseline requires a locale name (e.g. en)"); + } + options.baseline = next.replace(/\.json$/, ""); + i += 1; + break; + } + case "--src": + case "--source": { + const next = argv[i + 1]; + if (!next) { + throw new Error(`${arg} requires a directory path`); + } + options.extraSources.push(path.resolve(process.cwd(), next)); + i += 1; + break; + } + case "--help": + printUsage(); + process.exit(0); + break; + default: + if (arg.startsWith("--")) { + throw new Error(`Unknown option: ${arg}`); + } + throw new Error(`Unexpected positional argument: ${arg}`); + } + } + + return options; +} + +function getAllFiles(start, predicate) { + if (!fs.existsSync(start)) return []; + + const stack = [start]; + const files = []; + + while (stack.length) { + const current = stack.pop(); + if (!current) continue; + const stat = fs.statSync(current); + if (stat.isDirectory()) { + const entries = fs.readdirSync(current, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isSymbolicLink()) { + continue; + } + if (IGNORE_DIR_NAMES.has(entry.name)) { + continue; + } + const entryPath = path.join(current, entry.name); + if (entry.isDirectory()) { + stack.push(entryPath); + } else if (!predicate || predicate(entryPath)) { + files.push(entryPath); + } + } + } else if (!predicate || predicate(current)) { + files.push(current); + } + } + + return files; +} + +function collectSourceFiles(sourceDirs) { + const seen = new Set(); + const files = []; + + for (const dir of sourceDirs) { + const resolved = getAllFiles(dir, (filePath) => { + if (seen.has(filePath)) return false; + if (!SUPPORTED_EXTENSIONS.has(path.extname(filePath))) return false; + if ( + EXCLUDE_USAGE_DIRS.some((excluded) => + filePath.startsWith(`${excluded}${path.sep}`), + ) || + EXCLUDE_USAGE_DIRS.includes(filePath) + ) { + return false; + } + return true; + }); + + for (const filePath of resolved) { + seen.add(filePath); + files.push({ + path: filePath, + extension: path.extname(filePath).toLowerCase(), + content: fs.readFileSync(filePath, "utf8"), + }); + } + } + + files.sort((a, b) => a.path.localeCompare(b.path)); + return files; +} + +function flattenLocale(obj, parent = "") { + const entries = new Map(); + + if (!obj || typeof obj !== "object" || Array.isArray(obj)) { + return entries; + } + + for (const [key, value] of Object.entries(obj)) { + const currentPath = parent ? `${parent}.${key}` : key; + if (value && typeof value === "object" && !Array.isArray(value)) { + const childEntries = flattenLocale(value, currentPath); + for (const [childKey, childValue] of childEntries) { + entries.set(childKey, childValue); + } + } else { + entries.set(currentPath, value); + } + } + + return entries; +} + +function diffLocaleKeys(baselineEntries, localeEntries) { + const missing = []; + const extra = []; + + for (const key of baselineEntries.keys()) { + if (!localeEntries.has(key)) { + missing.push(key); + } + } + + for (const key of localeEntries.keys()) { + if (!baselineEntries.has(key)) { + extra.push(key); + } + } + + missing.sort(); + extra.sort(); + + return { missing, extra }; +} + +function determineScriptKind(extension) { + switch (extension) { + case ".ts": + return ts.ScriptKind.TS; + case ".tsx": + return ts.ScriptKind.TSX; + case ".jsx": + return ts.ScriptKind.JSX; + case ".js": + case ".mjs": + case ".cjs": + return ts.ScriptKind.JS; + default: + return ts.ScriptKind.TS; + } +} + +function getNamespaceFromKey(key) { + if (!key || typeof key !== "string") return null; + const [namespace] = key.split("."); + return namespace ?? null; +} + +function addTemplatePrefixCandidate( + prefix, + dynamicPrefixes, + baselineNamespaces, +) { + if (!prefix || typeof prefix !== "string") return; + const normalized = prefix.trim(); + if (!normalized) return; + let candidate = normalized; + if (!candidate.endsWith(".")) { + const lastDotIndex = candidate.lastIndexOf("."); + if (lastDotIndex === -1) { + return; + } + candidate = candidate.slice(0, lastDotIndex + 1); + } + if (!TEMPLATE_PREFIX_PATTERN.test(candidate)) return; + const namespace = getNamespaceFromKey(candidate); + if (!namespace || IGNORED_KEY_PREFIXES.has(namespace)) return; + if (!baselineNamespaces.has(namespace)) return; + dynamicPrefixes.add(candidate); +} + +function addKeyIfValid(key, usedKeys, baselineNamespaces, options = {}) { + if (!key || typeof key !== "string") return false; + if (!KEY_PATTERN.test(key)) return false; + const namespace = getNamespaceFromKey(key); + if (!namespace || IGNORED_KEY_PREFIXES.has(namespace)) return false; + if (!options.forceNamespace && !baselineNamespaces.has(namespace)) { + return false; + } + usedKeys.add(key); + return true; +} + +function collectImportSpecifiers(sourceFile) { + const specifiers = new Map(); + + sourceFile.forEachChild((node) => { + if (!ts.isImportDeclaration(node)) return; + const moduleText = + ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text; + if (!moduleText || !node.importClause) return; + + if (node.importClause.name) { + specifiers.set(node.importClause.name.text, moduleText); + } + + const { namedBindings } = node.importClause; + if (!namedBindings) return; + + if (ts.isNamespaceImport(namedBindings)) { + specifiers.set(namedBindings.name.text, `${moduleText}.*`); + return; + } + + if (ts.isNamedImports(namedBindings)) { + for (const element of namedBindings.elements) { + specifiers.set(element.name.text, moduleText); + } + } + }); + + return specifiers; +} + +function getCallExpressionChain(expression) { + const chain = []; + let current = expression; + while (current) { + if (ts.isIdentifier(current)) { + chain.unshift(current.text); + break; + } + if (ts.isPropertyAccessExpression(current)) { + chain.unshift(current.name.text); + current = current.expression; + continue; + } + if (ts.isElementAccessExpression(current)) { + const argument = current.argumentExpression; + if (ts.isStringLiteralLike(argument)) { + chain.unshift(argument.text); + current = current.expression; + continue; + } + return []; + } + break; + } + return chain; +} + +function classifyCallExpression(expression, importSpecifiers) { + if (!expression) return null; + const chain = getCallExpressionChain(expression); + if (chain.length === 0) return null; + + const last = chain[chain.length - 1]; + const root = chain[0]; + + if (last === "t") { + return { type: "translation", forceNamespace: true }; + } + + if ( + NOTICE_METHOD_NAMES.has(last) && + root === "showNotice" && + (!importSpecifiers || + NOTICE_SERVICE_IDENTIFIERS.has(importSpecifiers.get("showNotice") ?? "")) + ) { + return { type: "notice", forceNamespace: true }; + } + + return null; +} + +function resolveBindingValue(name, scopeStack) { + if (!name) return null; + for (let index = scopeStack.length - 1; index >= 0; index -= 1) { + const scope = scopeStack[index]; + if (scope && scope.has(name)) { + return scope.get(name); + } + } + return null; +} + +function resolveKeyFromExpression( + node, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, +) { + if (!node) return null; + + if ( + ts.isStringLiteralLike(node) || + ts.isNoSubstitutionTemplateLiteral(node) + ) { + return node.text; + } + + if (ts.isTemplateExpression(node)) { + addTemplatePrefixCandidate( + node.head?.text ?? "", + dynamicPrefixes, + baselineNamespaces, + ); + for (const span of node.templateSpans) { + const literalText = span.literal?.text ?? ""; + const combined = (node.head?.text ?? "") + literalText; + addTemplatePrefixCandidate(combined, dynamicPrefixes, baselineNamespaces); + } + return null; + } + + if (ts.isBinaryExpression(node)) { + if (node.operatorToken.kind === ts.SyntaxKind.PlusToken) { + const left = resolveKeyFromExpression( + node.left, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + const right = resolveKeyFromExpression( + node.right, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + if (left && right) { + return `${left}${right}`; + } + if (left) { + addTemplatePrefixCandidate(left, dynamicPrefixes, baselineNamespaces); + } + return null; + } + return null; + } + + if (ts.isParenthesizedExpression(node)) { + return resolveKeyFromExpression( + node.expression, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + } + + if (ts.isAsExpression(node) || ts.isTypeAssertionExpression(node)) { + return resolveKeyFromExpression( + node.expression, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + } + + if (ts.isIdentifier(node)) { + return resolveBindingValue(node.text, scopeStack); + } + + if (ts.isCallExpression(node)) { + const classification = classifyCallExpression( + node.expression, + importSpecifiers, + ); + if (!classification) return null; + const firstArg = node.arguments[0]; + if (!firstArg) return null; + return resolveKeyFromExpression( + firstArg, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + } + + return null; +} + +function collectUsedKeysFromTsFile( + file, + baselineNamespaces, + usedKeys, + dynamicPrefixes, +) { + let sourceFile; + + try { + sourceFile = ts.createSourceFile( + file.path, + file.content, + ts.ScriptTarget.Latest, + true, + determineScriptKind(file.extension), + ); + } catch (error) { + console.warn(`Warning: failed to parse ${file.path}: ${error.message}`); + return; + } + + const importSpecifiers = collectImportSpecifiers(sourceFile); + const scopeStack = [new Map()]; + + const visit = (node) => { + let scopePushed = false; + if ( + ts.isBlock(node) || + ts.isModuleBlock(node) || + node.kind === ts.SyntaxKind.CaseBlock || + ts.isCatchClause(node) + ) { + scopeStack.push(new Map()); + scopePushed = true; + } + + if (ts.isTemplateExpression(node)) { + resolveKeyFromExpression( + node, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + } + + if (ts.isVariableDeclaration(node) && node.initializer) { + const key = resolveKeyFromExpression( + node.initializer, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + if (key && KEY_PATTERN.test(key)) { + if (ts.isIdentifier(node.name)) { + scopeStack[scopeStack.length - 1].set(node.name.text, key); + } + } + } + + if (ts.isCallExpression(node)) { + const classification = classifyCallExpression( + node.expression, + importSpecifiers, + ); + if (classification) { + const [firstArg] = node.arguments; + if (firstArg) { + const key = resolveKeyFromExpression( + firstArg, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + if ( + !addKeyIfValid(key, usedKeys, baselineNamespaces, classification) + ) { + addTemplatePrefixCandidate( + key ?? "", + dynamicPrefixes, + baselineNamespaces, + ); + } + } + } + } + + if (ts.isJsxAttribute(node) && node.name?.text === "i18nKey") { + const initializer = node.initializer; + if (initializer && ts.isStringLiteralLike(initializer)) { + addKeyIfValid(initializer.text, usedKeys, baselineNamespaces, { + forceNamespace: false, + }); + } else if ( + initializer && + ts.isJsxExpression(initializer) && + initializer.expression + ) { + const key = resolveKeyFromExpression( + initializer.expression, + scopeStack, + dynamicPrefixes, + baselineNamespaces, + importSpecifiers, + ); + addKeyIfValid(key, usedKeys, baselineNamespaces, { + forceNamespace: true, + }); + } + } + + node.forEachChild(visit); + + if (scopePushed) { + scopeStack.pop(); + } + }; + + visit(sourceFile); +} + +function collectUsedKeysFromTextFile(file, baselineNamespaces, usedKeys) { + const regex = /['"`]([A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+)['"`]/g; + let match; + while ((match = regex.exec(file.content))) { + addKeyIfValid(match[1], usedKeys, baselineNamespaces, { + forceNamespace: false, + }); + } +} + +function collectUsedI18nKeys(sourceFiles, baselineNamespaces) { + const usedKeys = new Set(); + const dynamicPrefixes = new Set(); + + for (const file of sourceFiles) { + if (TS_EXTENSIONS.has(file.extension)) { + collectUsedKeysFromTsFile( + file, + baselineNamespaces, + usedKeys, + dynamicPrefixes, + ); + } else { + collectUsedKeysFromTextFile(file, baselineNamespaces, usedKeys); + } + } + + return { usedKeys, dynamicPrefixes }; +} + +function alignToBaseline(baselineNode, localeNode, options) { + const shouldCopyLocale = + localeNode && typeof localeNode === "object" && !Array.isArray(localeNode); + + if ( + baselineNode && + typeof baselineNode === "object" && + !Array.isArray(baselineNode) + ) { + const result = {}; + const baselineKeys = Object.keys(baselineNode); + for (const key of baselineKeys) { + const baselineValue = baselineNode[key]; + const localeValue = shouldCopyLocale ? localeNode[key] : undefined; + + if ( + baselineValue && + typeof baselineValue === "object" && + !Array.isArray(baselineValue) + ) { + result[key] = alignToBaseline( + baselineValue, + localeValue && typeof localeValue === "object" ? localeValue : {}, + options, + ); + } else if (localeValue === undefined) { + result[key] = baselineValue; + } else { + result[key] = localeValue; + } + } + + if (options.keepExtra && shouldCopyLocale) { + const extraKeys = Object.keys(localeNode) + .filter((key) => !baselineKeys.includes(key)) + .sort(); + for (const key of extraKeys) { + result[key] = localeNode[key]; + } + } + + return result; + } + + return shouldCopyLocale ? localeNode : baselineNode; +} + +function logPreviewEntries(label, items) { + if (!items || items.length === 0) return; + + const preview = items.slice(0, MAX_PREVIEW_ENTRIES); + for (const item of preview) { + console.log(` · ${label}: ${item}`); + } + if (items.length > preview.length) { + console.log( + ` · ${label}: ... and ${items.length - preview.length} more`, + ); + } +} + +function removeKey(target, dottedKey) { + if ( + !target || + typeof target !== "object" || + Array.isArray(target) || + dottedKey === "" + ) { + return; + } + + if (dottedKey in target) { + delete target[dottedKey]; + return; + } + + const parts = dottedKey.split(".").filter((part) => part !== ""); + if (parts.length === 0) return; + + let current = target; + for (let index = 0; index < parts.length; index += 1) { + const part = parts[index]; + if ( + !current || + typeof current !== "object" || + Array.isArray(current) || + !(part in current) + ) { + return; + } + if (index === parts.length - 1) { + delete current[part]; + return; + } + current = current[part]; + } +} + +function cleanupEmptyBranches(target) { + if (!target || typeof target !== "object" || Array.isArray(target)) { + return false; + } + + for (const key of Object.keys(target)) { + if (cleanupEmptyBranches(target[key])) { + delete target[key]; + } + } + + return Object.keys(target).length === 0; +} + +function escapeRegExp(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function findKeyInSources(key, sourceFiles) { + if (fileUsageCache.has(key)) { + return fileUsageCache.get(key); + } + + const pattern = new RegExp(`(['"\`])${escapeRegExp(key)}\\1`); + let found = false; + + for (const file of sourceFiles) { + if (pattern.test(file.content)) { + found = true; + break; + } + } + + fileUsageCache.set(key, found); + return found; +} + +function isKeyUsed(key, usage, sourceFiles) { + if (WHITELIST_KEYS.has(key)) return true; + if (!key) return false; + if (usage.usedKeys.has(key)) return true; + + if (dynamicKeyCache.has(key)) { + return dynamicKeyCache.get(key); + } + + const prefixes = getCandidatePrefixes(key); + let used = prefixes.some((prefix) => usage.dynamicPrefixes.has(prefix)); + + if (!used) { + used = findKeyInSources(key, sourceFiles); + } + + dynamicKeyCache.set(key, used); + return used; +} + +function getCandidatePrefixes(key) { + if (!key.includes(".")) return []; + const parts = key.split("."); + const prefixes = []; + for (let index = 0; index < parts.length - 1; index += 1) { + const prefix = `${parts.slice(0, index + 1).join(".")}.`; + prefixes.push(prefix); + } + return prefixes; +} + +function writeReport(reportPath, data) { + const payload = JSON.stringify(data, null, 2); + fs.writeFileSync(reportPath, `${payload}\n`, "utf8"); +} + +function loadLocales() { + if (!fs.existsSync(LOCALES_DIR)) { + throw new Error(`Locales directory not found: ${LOCALES_DIR}`); + } + + const entries = fs.readdirSync(LOCALES_DIR, { withFileTypes: true }); + const locales = []; + + for (const entry of entries) { + if (entry.isFile()) { + if ( + /^[a-z0-9\-_]+\.json$/i.test(entry.name) && + !entry.name.endsWith(".bak") && + !entry.name.endsWith(".old") + ) { + const localePath = path.join(LOCALES_DIR, entry.name); + const name = path.basename(entry.name, ".json"); + const raw = fs.readFileSync(localePath, "utf8"); + locales.push({ + name, + dir: LOCALES_DIR, + format: "single-file", + files: [ + { + namespace: "translation", + path: localePath, + }, + ], + data: JSON.parse(raw), + }); + } + continue; + } + + if (!entry.isDirectory()) continue; + if (entry.name.startsWith(".")) continue; + + const localeDir = path.join(LOCALES_DIR, entry.name); + const namespaceEntries = fs + .readdirSync(localeDir, { withFileTypes: true }) + .filter( + (item) => + item.isFile() && + item.name.endsWith(".json") && + !item.name.endsWith(".bak") && + !item.name.endsWith(".old"), + ) + .map((item) => ({ + namespace: path.basename(item.name, ".json"), + path: path.join(localeDir, item.name), + })); + + namespaceEntries.sort((a, b) => a.path.localeCompare(b.path)); + + const data = {}; + for (const file of namespaceEntries) { + const raw = fs.readFileSync(file.path, "utf8"); + try { + data[file.namespace] = JSON.parse(raw); + } catch (error) { + console.warn(`Warning: failed to parse ${file.path}: ${error.message}`); + data[file.namespace] = {}; + } + } + + locales.push({ + name: entry.name, + dir: localeDir, + format: "multi-file", + files: namespaceEntries, + data, + }); + } + + locales.sort((a, b) => a.name.localeCompare(b.name)); + return locales; +} + +function ensureBackup(localePath) { + const backupPath = `${localePath}.bak`; + if (fs.existsSync(backupPath)) { + try { + fs.rmSync(backupPath); + } catch (error) { + throw new Error( + `Failed to recycle existing backup for ${path.basename( + localePath, + )}: ${error.message}`, + ); + } + } + fs.copyFileSync(localePath, backupPath); + return backupPath; +} + +function backupIfNeeded(filePath, backups, options) { + if (!options.backup) return; + if (!fs.existsSync(filePath)) return; + if (backups.has(filePath)) return; + const backupPath = ensureBackup(filePath); + backups.set(filePath, backupPath); + return backupPath; +} + +function cleanupBackups(backups) { + for (const backupPath of backups.values()) { + try { + if (fs.existsSync(backupPath)) { + fs.rmSync(backupPath); + } + } catch (error) { + console.warn( + `Warning: failed to remove backup ${path.basename( + backupPath, + )}: ${error.message}`, + ); + } + } + backups.clear(); +} + +function toModuleIdentifier(namespace, seen) { + const RESERVED = new Set([ + "default", + "function", + "var", + "let", + "const", + "import", + "export", + "class", + "enum", + ]); + + const base = + namespace.replace(/[^a-zA-Z0-9_$]/g, "_").replace(/^[^a-zA-Z_$]+/, "") || + "ns"; + + let candidate = base; + let counter = 1; + while (RESERVED.has(candidate) || seen.has(candidate)) { + candidate = `${base}_${counter}`; + counter += 1; + } + seen.add(candidate); + return candidate; +} + +function regenerateLocaleIndex(localeDir, namespaces) { + const seen = new Set(); + const imports = []; + const mappings = []; + + for (const namespace of namespaces) { + const filePath = path.join(localeDir, `${namespace}.json`); + if (!fs.existsSync(filePath)) continue; + const identifier = toModuleIdentifier(namespace, seen); + imports.push(`import ${identifier} from "./${namespace}.json";`); + mappings.push(` "${namespace}": ${identifier},`); + } + + const content = `${imports.join("\n")} + +const resources = { +${mappings.join("\n")} +}; + +export default resources; +`; + + fs.writeFileSync(path.join(localeDir, "index.ts"), content, "utf8"); +} + +function writeLocale(locale, data, options) { + const backups = new Map(); + let success = false; + + try { + if (locale.format === "single-file") { + const target = locale.files[0].path; + backupIfNeeded(target, backups, options); + const serialized = JSON.stringify(data, null, 2); + fs.writeFileSync(target, `${serialized}\n`, "utf8"); + success = true; + return; + } + + const entries = Object.entries(data); + const orderedNamespaces = entries.map(([namespace]) => namespace); + const existingFiles = new Map( + locale.files.map((file) => [file.namespace, file.path]), + ); + const visited = new Set(); + + for (const [namespace, value] of entries) { + const target = + existingFiles.get(namespace) ?? + path.join(locale.dir, `${namespace}.json`); + backupIfNeeded(target, backups, options); + const serialized = JSON.stringify(value ?? {}, null, 2); + fs.mkdirSync(path.dirname(target), { recursive: true }); + fs.writeFileSync(target, `${serialized}\n`, "utf8"); + visited.add(namespace); + } + + for (const [namespace, filePath] of existingFiles.entries()) { + if (!visited.has(namespace) && fs.existsSync(filePath)) { + backupIfNeeded(filePath, backups, options); + fs.rmSync(filePath); + } + } + + regenerateLocaleIndex(locale.dir, orderedNamespaces); + locale.files = orderedNamespaces.map((namespace) => ({ + namespace, + path: path.join(locale.dir, `${namespace}.json`), + })); + success = true; + } finally { + if (success) { + cleanupBackups(backups); + } + } +} + +function processLocale( + locale, + baselineData, + baselineEntries, + usage, + sourceFiles, + missingFromSource, + options, +) { + const data = JSON.parse(JSON.stringify(locale.data)); + const flattened = flattenLocale(data); + const expectedTotal = baselineEntries.size; + + const { missing, extra } = diffLocaleKeys(baselineEntries, flattened); + + const unused = []; + for (const key of flattened.keys()) { + if (!isKeyUsed(key, usage, sourceFiles)) { + unused.push(key); + } + } + + const sourceMissing = + locale.name === options.baseline + ? missingFromSource.filter((key) => !flattened.has(key)) + : []; + + if ( + unused.length === 0 && + missing.length === 0 && + extra.length === 0 && + sourceMissing.length === 0 && + !options.align + ) { + console.log(`[${locale.name}] No issues detected 🎉`); + } else { + console.log(`[${locale.name}] Check results:`); + console.log( + ` unused: ${unused.length}, missing vs baseline: ${missing.length}, extra: ${extra.length}`, + ); + if (sourceMissing.length > 0) { + console.log(` missing in source: ${sourceMissing.length}`); + logPreviewEntries("missing-source", sourceMissing); + } + logPreviewEntries("unused", unused); + logPreviewEntries("missing", missing); + logPreviewEntries("extra", extra); + } + + const removed = []; + let aligned = false; + if (options.apply) { + let updated; + if (options.align) { + aligned = true; + updated = alignToBaseline(baselineData, data, options); + } else { + updated = JSON.parse(JSON.stringify(data)); + } + + for (const key of unused) { + removeKey(updated, key); + removed.push(key); + } + cleanupEmptyBranches(updated); + + writeLocale(locale, updated, options); + locale.data = JSON.parse(JSON.stringify(updated)); + console.log( + `[${locale.name}] Locale resources updated (${removed.length} unused removed${ + aligned ? ", structure aligned" : "" + })`, + ); + } + + return { + locale: locale.name, + file: locale.format === "single-file" ? locale.files[0].path : locale.dir, + totalKeys: flattened.size, + expectedKeys: expectedTotal, + unusedKeys: unused, + removed, + missingKeys: missing, + extraKeys: extra, + missingSourceKeys: sourceMissing, + aligned: aligned && options.apply, + }; +} + +function main() { + const argv = process.argv.slice(2); + + let options; + try { + options = parseArgs(argv); + } catch (error) { + console.error(`Error: ${error.message}`); + console.log(); + printUsage(); + process.exit(1); + } + + const sourceDirs = [ + ...new Set([...DEFAULT_SOURCE_DIRS, ...options.extraSources]), + ]; + + console.log("Scanning source directories:"); + for (const dir of sourceDirs) { + console.log(` - ${dir}`); + } + + const sourceFiles = collectSourceFiles(sourceDirs); + const locales = loadLocales(); + + if (locales.length === 0) { + console.log("No locale files found."); + return; + } + + const baselineLocale = locales.find( + (item) => item.name.toLowerCase() === options.baseline.toLowerCase(), + ); + + if (!baselineLocale) { + const available = locales.map((item) => item.name).join(", "); + throw new Error( + `Baseline locale "${options.baseline}" not found. Available locales: ${available}`, + ); + } + + const baselineData = JSON.parse(JSON.stringify(baselineLocale.data)); + const baselineEntries = flattenLocale(baselineData); + const baselineNamespaces = new Set(Object.keys(baselineData)); + const usage = collectUsedI18nKeys(sourceFiles, baselineNamespaces); + const baselineKeys = new Set(baselineEntries.keys()); + const missingFromSource = Array.from(usage.usedKeys).filter( + (key) => !baselineKeys.has(key), + ); + missingFromSource.sort(); + + locales.sort((a, b) => { + if (a.name === baselineLocale.name) return -1; + if (b.name === baselineLocale.name) return 1; + return a.name.localeCompare(b.name); + }); + + console.log(`\nChecking ${locales.length} locale files...\n`); + + const results = locales.map((locale) => + processLocale( + locale, + baselineData, + baselineEntries, + usage, + sourceFiles, + missingFromSource, + options, + ), + ); + + const totalUnused = results.reduce( + (count, result) => count + result.unusedKeys.length, + 0, + ); + const totalMissing = results.reduce( + (count, result) => count + result.missingKeys.length, + 0, + ); + const totalExtra = results.reduce( + (count, result) => count + result.extraKeys.length, + 0, + ); + const totalSourceMissing = results.reduce( + (count, result) => count + result.missingSourceKeys.length, + 0, + ); + + console.log("\nSummary:"); + for (const result of results) { + console.log( + ` • ${result.locale}: unused=${result.unusedKeys.length}, missing=${result.missingKeys.length}, extra=${result.extraKeys.length}, missingSource=${result.missingSourceKeys.length}, total=${result.totalKeys}, expected=${result.expectedKeys}`, + ); + } + console.log( + `\nTotals → unused: ${totalUnused}, missing: ${totalMissing}, extra: ${totalExtra}, missingSource: ${totalSourceMissing}`, + ); + if (options.apply) { + console.log( + "Files were updated in-place; review diffs before committing changes.", + ); + } else { + console.log( + "Run with --apply to write cleaned locale files. Backups will be created unless --no-backup is passed.", + ); + if (options.align) { + console.log( + "Alignment was evaluated in dry-run mode; rerun with --apply to rewrite locale files.", + ); + } else { + console.log( + "Pass --align to normalize locale structure/order based on the baseline locale.", + ); + } + } + + if (options.reportPath) { + const payload = { + generatedAt: new Date().toISOString(), + options: { + apply: options.apply, + backup: options.backup, + align: options.align, + baseline: baselineLocale.name, + keepExtra: options.keepExtra, + sourceDirs, + }, + results, + }; + writeReport(options.reportPath, payload); + console.log(`Report written to ${options.reportPath}`); + } +} + +try { + main(); +} catch (error) { + console.error("Failed to complete i18n cleanup draft."); + console.error(error); + process.exit(1); +} diff --git a/scripts/fix-alpha_version.mjs b/scripts/fix-alpha_version.mjs index 22863ba6e..7817eb4a1 100644 --- a/scripts/fix-alpha_version.mjs +++ b/scripts/fix-alpha_version.mjs @@ -1,7 +1,7 @@ import { exec } from "child_process"; -import { promisify } from "util"; import fs from "fs/promises"; import path from "path"; +import { promisify } from "util"; /** * 为Alpha版本重命名版本号 diff --git a/scripts/generate-i18n-keys.mjs b/scripts/generate-i18n-keys.mjs new file mode 100644 index 000000000..133ab5ef3 --- /dev/null +++ b/scripts/generate-i18n-keys.mjs @@ -0,0 +1,98 @@ +#!/usr/bin/env node +import { promises as fs } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const ROOT_DIR = path.resolve(__dirname, ".."); +const LOCALE_DIR = path.resolve(ROOT_DIR, "src/locales/en"); +const KEY_OUTPUT = path.resolve(ROOT_DIR, "src/types/generated/i18n-keys.ts"); +const RESOURCE_OUTPUT = path.resolve( + ROOT_DIR, + "src/types/generated/i18n-resources.ts", +); + +const isPlainObject = (value) => + typeof value === "object" && value !== null && !Array.isArray(value); + +const flattenKeys = (data, prefix = "") => { + const keys = []; + for (const [key, value] of Object.entries(data)) { + const nextPrefix = prefix ? `${prefix}.${key}` : key; + if (isPlainObject(value)) { + keys.push(...flattenKeys(value, nextPrefix)); + } else { + keys.push(nextPrefix); + } + } + return keys; +}; + +const buildType = (data, indent = 0) => { + if (!isPlainObject(data)) { + return "string"; + } + + const entries = Object.entries(data).sort(([a], [b]) => a.localeCompare(b)); + const pad = " ".repeat(indent); + const inner = entries + .map(([key, value]) => { + const typeStr = buildType(value, indent + 2); + return `${" ".repeat(indent + 2)}${JSON.stringify(key)}: ${typeStr};`; + }) + .join("\n"); + + return entries.length + ? `{ +${inner} +${pad}}` + : "{}"; +}; + +const loadNamespaceJson = async () => { + const dirents = await fs.readdir(LOCALE_DIR, { withFileTypes: true }); + const namespaces = []; + for (const dirent of dirents) { + if (!dirent.isFile() || !dirent.name.endsWith(".json")) continue; + const name = dirent.name.replace(/\.json$/, ""); + const filePath = path.join(LOCALE_DIR, dirent.name); + const raw = await fs.readFile(filePath, "utf8"); + const json = JSON.parse(raw); + namespaces.push({ name, json }); + } + namespaces.sort((a, b) => a.name.localeCompare(b.name)); + return namespaces; +}; + +const buildKeysFile = (keys) => { + const arrayLiteral = keys.map((key) => ` "${key}"`).join(",\n"); + return `// This file is auto-generated by scripts/generate-i18n-keys.mjs\n// Do not edit this file manually.\n\nexport const translationKeys = [\n${arrayLiteral}\n] as const;\n\nexport type TranslationKey = typeof translationKeys[number];\n`; +}; + +const buildResourcesFile = (namespaces) => { + const namespaceEntries = namespaces + .map(({ name, json }) => { + const typeStr = buildType(json, 4); + return ` ${JSON.stringify(name)}: ${typeStr};`; + }) + .join("\n"); + + return `// This file is auto-generated by scripts/generate-i18n-keys.mjs\n// Do not edit this file manually.\n\nexport interface TranslationResources {\n translation: {\n${namespaceEntries}\n };\n}\n`; +}; + +const main = async () => { + const namespaces = await loadNamespaceJson(); + const keys = namespaces.flatMap(({ name, json }) => flattenKeys(json, name)); + const keysContent = buildKeysFile(keys); + const resourcesContent = buildResourcesFile(namespaces); + await fs.mkdir(path.dirname(KEY_OUTPUT), { recursive: true }); + await fs.writeFile(KEY_OUTPUT, keysContent, "utf8"); + await fs.writeFile(RESOURCE_OUTPUT, resourcesContent, "utf8"); + console.log(`Generated ${keys.length} translation keys.`); +}; + +main().catch((error) => { + console.error("Failed to generate i18n metadata:", error); + process.exitCode = 1; +}); diff --git a/scripts/portable-fixed-webview2.mjs b/scripts/portable-fixed-webview2.mjs index b3424fb51..99bbbc62d 100644 --- a/scripts/portable-fixed-webview2.mjs +++ b/scripts/portable-fixed-webview2.mjs @@ -1,9 +1,10 @@ import fs from "fs"; import fsp from "fs/promises"; -import path from "path"; -import AdmZip from "adm-zip"; import { createRequire } from "module"; +import path from "path"; + import { getOctokit, context } from "@actions/github"; +import AdmZip from "adm-zip"; const target = process.argv.slice(2)[0]; const alpha = process.argv.slice(2)[1]; @@ -79,11 +80,11 @@ async function resolvePortable() { tag, }); - let assets = release.assets.filter((x) => { + const assets = release.assets.filter((x) => { return x.name === zipFile; }); if (assets.length > 0) { - let id = assets[0].id; + const id = assets[0].id; await github.rest.repos.deleteReleaseAsset({ ...options, asset_id: id, diff --git a/scripts/portable.mjs b/scripts/portable.mjs index 49aafdb9c..e1918971b 100644 --- a/scripts/portable.mjs +++ b/scripts/portable.mjs @@ -1,8 +1,9 @@ import fs from "fs"; -import path from "path"; -import AdmZip from "adm-zip"; -import { createRequire } from "module"; import fsp from "fs/promises"; +import { createRequire } from "module"; +import path from "path"; + +import AdmZip from "adm-zip"; const target = process.argv.slice(2)[0]; const ARCH_MAP = { diff --git a/scripts/prebuild.mjs b/scripts/prebuild.mjs index d127a0caa..21f0da7cc 100644 --- a/scripts/prebuild.mjs +++ b/scripts/prebuild.mjs @@ -1,14 +1,16 @@ -import AdmZip from "adm-zip"; import { execSync } from "child_process"; import { createHash } from "crypto"; import fs from "fs"; import fsp from "fs/promises"; +import path from "path"; +import zlib from "zlib"; + +import AdmZip from "adm-zip"; import { glob } from "glob"; import { HttpsProxyAgent } from "https-proxy-agent"; import fetch from "node-fetch"; -import path from "path"; import { extract } from "tar"; -import zlib from "zlib"; + import { log_debug, log_error, log_info, log_success } from "./utils.mjs"; /** @@ -55,7 +57,7 @@ const ARCH_MAP = { const arg1 = process.argv.slice(2)[0]; const arg2 = process.argv.slice(2)[1]; -let target = arg1 === "--force" || arg1 === "-f" ? arg2 : arg1; +const target = arg1 === "--force" || arg1 === "-f" ? arg2 : arg1; const { platform, arch } = target ? { platform: PLATFORM_MAP[target], arch: ARCH_MAP[target] } : process; @@ -113,7 +115,7 @@ async function calculateFileHash(filePath) { const hashSum = createHash("sha256"); hashSum.update(fileBuffer); return hashSum.digest("hex"); - } catch (err) { + } catch (ignoreErr) { return null; } } @@ -547,9 +549,9 @@ const resolveServicePermission = async () => { const hashCache = await loadHashCache(); let hasChanges = false; - for (let f of serviceExecutables) { + for (const f of serviceExecutables) { const files = glob.sync(path.join(resDir, f)); - for (let filePath of files) { + for (const filePath of files) { if (fs.existsSync(filePath)) { const currentHash = await calculateFileHash(filePath); const cacheKey = `${filePath}_chmod`; @@ -573,52 +575,29 @@ const resolveServicePermission = async () => { } }; -// resolve locales (从 src/locales 复制到 resources/locales,并使用 hash 检查) -async function resolveLocales() { - const srcLocalesDir = path.join(cwd, "src/locales"); - const targetLocalesDir = path.join(cwd, "src-tauri/resources/locales"); - - try { - await fsp.mkdir(targetLocalesDir, { recursive: true }); - const files = await fsp.readdir(srcLocalesDir); - for (const file of files) { - const srcPath = path.join(srcLocalesDir, file); - const targetPath = path.join(targetLocalesDir, file); - if (!(await hasFileChanged(srcPath, targetPath))) continue; - await fsp.copyFile(srcPath, targetPath); - await updateHashCache(targetPath); - log_success(`Copied locale file: ${file}`); - } - log_success("All locale files processed successfully"); - } catch (err) { - log_error("Error copying locale files:", err.message); - throw err; - } -} - // ======================= // Other resource resolvers (service, mmdb, geosite, geoip, enableLoopback, sysproxy) // ======================= const SERVICE_URL = `https://github.com/clash-verge-rev/clash-verge-service-ipc/releases/download/${SIDECAR_HOST}`; const resolveService = () => { - let ext = platform === "win32" ? ".exe" : ""; - let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; + const ext = platform === "win32" ? ".exe" : ""; + const suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; return resolveResource({ file: "clash-verge-service" + suffix + ext, downloadURL: `${SERVICE_URL}/clash-verge-service${ext}`, }); }; const resolveInstall = () => { - let ext = platform === "win32" ? ".exe" : ""; - let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; + const ext = platform === "win32" ? ".exe" : ""; + const suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; return resolveResource({ file: "clash-verge-service-install" + suffix + ext, downloadURL: `${SERVICE_URL}/clash-verge-service-install${ext}`, }); }; const resolveUninstall = () => { - let ext = platform === "win32" ? ".exe" : ""; - let suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; + const ext = platform === "win32" ? ".exe" : ""; + const suffix = platform === "linux" ? "-" + SIDECAR_HOST : ""; return resolveResource({ file: "clash-verge-service-uninstall" + suffix + ext, downloadURL: `${SERVICE_URL}/clash-verge-service-uninstall${ext}`, @@ -715,7 +694,6 @@ const tasks = [ retry: 5, macosOnly: true, }, - { name: "locales", func: resolveLocales, retry: 2 }, ]; async function runTask() { diff --git a/scripts/release-version.mjs b/scripts/release-version.mjs index bc177a29c..0a6fdbed8 100644 --- a/scripts/release-version.mjs +++ b/scripts/release-version.mjs @@ -30,10 +30,11 @@ */ import { execSync } from "child_process"; -import { program } from "commander"; import fs from "fs/promises"; import path from "path"; +import { program } from "commander"; + /** * 获取当前 git 短 commit hash * @returns {string} diff --git a/scripts/telegram.mjs b/scripts/telegram.mjs index f12404940..914fdf928 100644 --- a/scripts/telegram.mjs +++ b/scripts/telegram.mjs @@ -1,5 +1,7 @@ -import axios from "axios"; import { readFileSync } from "fs"; + +import axios from "axios"; + import { log_error, log_info, log_success } from "./utils.mjs"; const CHAT_ID_RELEASE = "@clash_verge_re"; // 正式发布频道 diff --git a/scripts/updatelog.mjs b/scripts/updatelog.mjs index d3c90b581..b00d35087 100644 --- a/scripts/updatelog.mjs +++ b/scripts/updatelog.mjs @@ -58,7 +58,7 @@ export async function resolveUpdateLogDefault() { const reEnd = /^---/; let isCapturing = false; - let content = []; + const content = []; let firstTag = ""; for (const line of data.split("\n")) { diff --git a/scripts/updater-fixed-webview2.mjs b/scripts/updater-fixed-webview2.mjs index 64426d94a..083c9b21f 100644 --- a/scripts/updater-fixed-webview2.mjs +++ b/scripts/updater-fixed-webview2.mjs @@ -1,5 +1,6 @@ -import fetch from "node-fetch"; import { getOctokit, context } from "@actions/github"; +import fetch from "node-fetch"; + import { resolveUpdateLog } from "./updatelog.mjs"; const UPDATE_TAG_NAME = "updater"; @@ -113,7 +114,7 @@ async function resolveUpdater() { }); // delete the old assets - for (let asset of updateRelease.assets) { + for (const asset of updateRelease.assets) { if (asset.name === UPDATE_JSON_FILE) { await github.rest.repos.deleteReleaseAsset({ ...options, diff --git a/scripts/updater.mjs b/scripts/updater.mjs index 9291d6ab9..51f6af3eb 100644 --- a/scripts/updater.mjs +++ b/scripts/updater.mjs @@ -1,5 +1,6 @@ -import fetch from "node-fetch"; import { getOctokit, context } from "@actions/github"; +import fetch from "node-fetch"; + import { resolveUpdateLog, resolveUpdateLogDefault } from "./updatelog.mjs"; // Add stable update JSON filenames @@ -259,7 +260,7 @@ async function processRelease(github, options, tag, isAlpha) { const proxyFile = isAlpha ? ALPHA_UPDATE_JSON_PROXY : UPDATE_JSON_PROXY; // Delete existing assets with these names - for (let asset of updateRelease.assets) { + for (const asset of updateRelease.assets) { if (asset.name === jsonFile) { await github.rest.repos.deleteReleaseAsset({ ...options, diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 934caa5a1..b7bf8c381 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -572,6 +572,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "base62" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adf9755786e27479693dedd3271691a92b5e242ab139cacb9fb8e7fb5381111" + [[package]] name = "base64" version = "0.13.1" @@ -822,6 +828,16 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -1131,6 +1147,7 @@ dependencies = [ "reqwest", "reqwest_dav", "runas", + "rust-i18n", "scopeguard", "serde", "serde_json", @@ -2847,7 +2864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ "heck 0.4.1", - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", @@ -2888,6 +2905,30 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + [[package]] name = "gobject-sys" version = "0.18.0" @@ -3512,6 +3553,22 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "image" version = "0.25.8" @@ -3701,6 +3758,15 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -4432,6 +4498,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normpath" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "notify-rust" version = "4.11.7" @@ -5554,11 +5629,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime 0.6.3", "toml_edit 0.20.2", ] @@ -6230,6 +6304,60 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rust-i18n" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332" +dependencies = [ + "globwalk", + "once_cell", + "regex", + "rust-i18n-macro", + "rust-i18n-support", + "smallvec", +] + +[[package]] +name = "rust-i18n-macro" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965" +dependencies = [ + "glob", + "once_cell", + "proc-macro2", + "quote", + "rust-i18n-support", + "serde", + "serde_json", + "serde_yaml", + "syn 2.0.108", +] + +[[package]] +name = "rust-i18n-support" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19" +dependencies = [ + "arc-swap", + "base62", + "globwalk", + "itertools 0.11.0", + "lazy_static", + "normpath", + "once_cell", + "proc-macro2", + "regex", + "serde", + "serde_json", + "serde_yaml", + "siphasher 1.0.1", + "toml 0.8.23", + "triomphe", +] + [[package]] name = "rust-ini" version = "0.21.3" @@ -6672,6 +6800,19 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.12.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serde_yaml_ng" version = "0.10.0" @@ -7185,7 +7326,7 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.2", + "toml 0.8.23", "version-compare", ] @@ -8126,14 +8267,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned 0.6.9", - "toml_datetime 0.6.3", - "toml_edit 0.20.2", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] @@ -8153,9 +8294,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -8176,7 +8317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.12.0", - "toml_datetime 0.6.3", + "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -8185,12 +8326,24 @@ name = "toml_edit" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.12.0", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.12.0", "serde", "serde_spanned 0.6.9", - "toml_datetime 0.6.3", - "winnow 0.5.40", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.13", ] [[package]] @@ -8214,6 +8367,12 @@ dependencies = [ "winnow 0.7.13", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "toml_writer" version = "1.0.4" @@ -8513,6 +8672,17 @@ dependencies = [ "petgraph", ] +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +dependencies = [ + "arc-swap", + "serde", + "stable_deref_trait", +] + [[package]] name = "try-lock" version = "0.2.5" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 889a3136c..1c252fdf3 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -87,6 +87,7 @@ clash_verge_service_ipc = { version = "2.0.21", features = [ "client", ], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc" } arc-swap = "1.7.1" +rust-i18n = "3.1.5" [target.'cfg(windows)'.dependencies] runas = "=1.2.0" diff --git a/src-tauri/locales/ar.yml b/src-tauri/locales/ar.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/ar.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/de.yml b/src-tauri/locales/de.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/de.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/en.yml b/src-tauri/locales/en.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/en.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/es.yml b/src-tauri/locales/es.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/es.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/fa.yml b/src-tauri/locales/fa.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/fa.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/id.yml b/src-tauri/locales/id.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/id.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/jp.yml b/src-tauri/locales/jp.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/jp.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/ko.yml b/src-tauri/locales/ko.yml new file mode 100644 index 000000000..b671b8aec --- /dev/null +++ b/src-tauri/locales/ko.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: 대시보드 + body: 대시보드 표시 상태가 업데이트되었습니다. + clashModeChanged: + title: 모드 전환 + body: "{mode}(으)로 전환되었습니다." + systemProxyToggled: + title: 시스템 프록시 + body: 시스템 프록시 상태가 업데이트되었습니다. + tunModeToggled: + title: TUN 모드 + body: TUN 모드 상태가 업데이트되었습니다. + lightweightModeEntered: + title: 경량 모드 + body: 경량 모드에 진입했습니다. + appQuit: + title: 곧 종료 + body: Clash Verge가 곧 종료됩니다. + appHidden: + title: 앱이 숨겨짐 + body: Clash Verge가 백그라운드에서 실행 중입니다. +service: + adminPrompt: 서비스를 설치하려면 관리자 권한이 필요합니다. +tray: + dashboard: 대시보드 + ruleMode: 규칙 모드 + globalMode: 전역 모드 + directMode: 직접 모드 + profiles: 프로필 + proxies: 프록시 + systemProxy: 시스템 프록시 + tunMode: TUN 모드 + closeAllConnections: 모든 연결 닫기 + lightweightMode: 경량 모드 + copyEnv: 환경 변수 복사 + confDir: 구성 디렉터리 + coreDir: 코어 디렉터리 + logsDir: 로그 디렉터리 + openDir: 디렉터리 열기 + appLog: 애플리케이션 로그 + coreLog: 코어 로그 + restartClash: Clash 코어 재시작 + restartApp: 애플리케이션 재시작 + vergeVersion: Verge 버전 + more: 더 보기 + exit: 종료 + tooltip: + systemProxy: 시스템 프록시 + tun: TUN + profile: 프로필 diff --git a/src-tauri/locales/ru.yml b/src-tauri/locales/ru.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/ru.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/tr.yml b/src-tauri/locales/tr.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/tr.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/tt.yml b/src-tauri/locales/tt.yml new file mode 100644 index 000000000..330cf3b50 --- /dev/null +++ b/src-tauri/locales/tt.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: Dashboard + body: Dashboard visibility has been updated. + clashModeChanged: + title: Mode Switch + body: Switched to {mode}. + systemProxyToggled: + title: System Proxy + body: System proxy status has been updated. + tunModeToggled: + title: TUN Mode + body: TUN mode status has been updated. + lightweightModeEntered: + title: Lightweight Mode + body: Entered lightweight mode. + appQuit: + title: About to Exit + body: Clash Verge is about to exit. + appHidden: + title: Application Hidden + body: Clash Verge is running in the background. +service: + adminPrompt: Installing the service requires administrator privileges. +tray: + dashboard: Dashboard + ruleMode: Rule Mode + globalMode: Global Mode + directMode: Direct Mode + profiles: Profiles + proxies: Proxies + systemProxy: System Proxy + tunMode: TUN Mode + closeAllConnections: Close All Connections + lightweightMode: Lightweight Mode + copyEnv: Copy Environment Variables + confDir: Configuration Directory + coreDir: Core Directory + logsDir: Log Directory + openDir: Open Directory + appLog: Application Log + coreLog: Core Log + restartClash: Restart Clash Core + restartApp: Restart Application + vergeVersion: Verge Version + more: More + exit: Exit + tooltip: + systemProxy: System Proxy + tun: TUN + profile: Profile diff --git a/src-tauri/locales/zh.yml b/src-tauri/locales/zh.yml new file mode 100644 index 000000000..10c2e6362 --- /dev/null +++ b/src-tauri/locales/zh.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: 仪表板 + body: 仪表板显示状态已更新。 + clashModeChanged: + title: 模式切换 + body: 已切换至 {mode}。 + systemProxyToggled: + title: 系统代理 + body: 系统代理状态已更新。 + tunModeToggled: + title: TUN 模式 + body: TUN 模式状态已更新。 + lightweightModeEntered: + title: 轻量模式 + body: 已进入轻量模式。 + appQuit: + title: 即将退出 + body: Clash Verge 即将退出。 + appHidden: + title: 应用已隐藏 + body: Clash Verge 正在后台运行。 +service: + adminPrompt: 安装服务需要管理员权限 +tray: + dashboard: 仪表板 + ruleMode: 规则模式 + globalMode: 全局模式 + directMode: 直连模式 + profiles: 订阅 + proxies: 代理 + systemProxy: 系统代理 + tunMode: TUN 模式 + closeAllConnections: 关闭所有连接 + lightweightMode: 轻量模式 + copyEnv: 复制环境变量 + confDir: 配置目录 + coreDir: 内核目录 + logsDir: 日志目录 + openDir: 打开目录 + appLog: 应用日志 + coreLog: 内核日志 + restartClash: 重启 Clash 内核 + restartApp: 重启应用 + vergeVersion: Verge 版本 + more: 更多 + exit: 退出 + tooltip: + systemProxy: 系统代理 + tun: TUN + profile: 订阅 diff --git a/src-tauri/locales/zhtw.yml b/src-tauri/locales/zhtw.yml new file mode 100644 index 000000000..040226b2e --- /dev/null +++ b/src-tauri/locales/zhtw.yml @@ -0,0 +1,52 @@ +_version: 1 +notifications: + dashboardToggled: + title: 儀表板 + body: 儀表板顯示狀態已更新。 + clashModeChanged: + title: 模式切換 + body: 已切換至 {mode}。 + systemProxyToggled: + title: 系統代理 + body: 系統代理狀態已更新。 + tunModeToggled: + title: TUN 模式 + body: TUN 模式狀態已更新。 + lightweightModeEntered: + title: 輕量模式 + body: 已進入輕量模式。 + appQuit: + title: 即將退出 + body: Clash Verge 即將退出。 + appHidden: + title: 應用已隱藏 + body: Clash Verge 正在背景執行。 +service: + adminPrompt: 安裝服務需要管理員權限 +tray: + dashboard: 儀表板 + ruleMode: 規則模式 + globalMode: 全域模式 + directMode: 直連模式 + profiles: 訂閱 + proxies: 代理 + systemProxy: 系統代理 + tunMode: TUN 模式 + closeAllConnections: 關閉所有連線 + lightweightMode: 輕量模式 + copyEnv: 複製環境變數 + confDir: 設定目錄 + coreDir: 核心目錄 + logsDir: 日誌目錄 + openDir: 開啟目錄 + appLog: 應用程式日誌 + coreLog: 核心日誌 + restartClash: 重新啟動 Clash 核心 + restartApp: 重新啟動應用程式 + vergeVersion: Verge 版本 + more: 更多 + exit: 離開 + tooltip: + systemProxy: 系統代理 + tun: TUN + profile: 訂閱 diff --git a/src-tauri/src/cmd/service.rs b/src-tauri/src/cmd/service.rs index 75d1a5444..7e5b7d2c0 100644 --- a/src-tauri/src/cmd/service.rs +++ b/src-tauri/src/cmd/service.rs @@ -1,8 +1,5 @@ use super::{CmdResult, StringifyErr}; -use crate::{ - core::service::{self, SERVICE_MANAGER, ServiceStatus}, - utils::i18n::t, -}; +use crate::core::service::{self, SERVICE_MANAGER, ServiceStatus}; use smartstring::SmartString; async fn execute_service_operation_sync(status: ServiceStatus, op_type: &str) -> CmdResult { @@ -13,7 +10,7 @@ async fn execute_service_operation_sync(status: ServiceStatus, op_type: &str) -> .await { let emsg = format!("{} Service failed: {}", op_type, e); - return Err(SmartString::from(&*t(emsg.as_str()).await)); + return Err(SmartString::from(emsg)); } Ok(()) } diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 284033900..1737b9666 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -227,8 +227,6 @@ fn linux_running_as_root() -> bool { #[cfg(target_os = "macos")] async fn uninstall_service() -> Result<()> { - use crate::utils::i18n::t; - logging!(info, Type::Service, "uninstall service"); let binary_path = dirs::service_path()?; @@ -240,7 +238,9 @@ async fn uninstall_service() -> Result<()> { let uninstall_shell: String = uninstall_path.to_string_lossy().into_owned(); - let prompt = t("Service Administrator Prompt").await; + crate::utils::i18n::sync_locale().await; + + let prompt = rust_i18n::t!("service.adminPrompt").to_string(); let command = format!( r#"do shell script "sudo '{uninstall_shell}'" with administrator privileges with prompt "{prompt}""# ); @@ -263,8 +263,6 @@ async fn uninstall_service() -> Result<()> { #[cfg(target_os = "macos")] async fn install_service() -> Result<()> { - use crate::utils::i18n::t; - logging!(info, Type::Service, "install service"); let binary_path = dirs::service_path()?; @@ -276,7 +274,9 @@ async fn install_service() -> Result<()> { let install_shell: String = install_path.to_string_lossy().into_owned(); - let prompt = t("Service Administrator Prompt").await; + crate::utils::i18n::sync_locale().await; + + let prompt = rust_i18n::t!("service.adminPrompt").to_string(); let command = format!( r#"do shell script "sudo '{install_shell}'" with administrator privileges with prompt "{prompt}""# ); diff --git a/src-tauri/src/core/tray/menu_def.rs b/src-tauri/src/core/tray/menu_def.rs index 10fe3835c..78c76e6cb 100644 --- a/src-tauri/src/core/tray/menu_def.rs +++ b/src-tauri/src/core/tray/menu_def.rs @@ -1,5 +1,12 @@ -use crate::utils::i18n::t; -use std::sync::Arc; +use rust_i18n::t; +use std::{borrow::Cow, sync::Arc}; + +fn to_arc_str(value: Cow<'static, str>) -> Arc { + match value { + Cow::Borrowed(s) => Arc::from(s), + Cow::Owned(s) => Arc::from(s.into_boxed_str()), + } +} macro_rules! define_menu { ($($field:ident => $const_name:ident, $id:expr, $text:expr),+ $(,)?) => { @@ -11,9 +18,10 @@ macro_rules! define_menu { pub struct MenuIds; impl MenuTexts { - pub async fn new() -> Self { - let ($($field,)+) = futures::join!($(t($text),)+); - Self { $($field,)+ } + pub fn new() -> Self { + Self { + $($field: to_arc_str(t!($text)),)+ + } } } @@ -24,26 +32,26 @@ macro_rules! define_menu { } define_menu! { - dashboard => DASHBOARD, "tray_dashboard", "Dashboard", - rule_mode => RULE_MODE, "tray_rule_mode", "Rule Mode", - global_mode => GLOBAL_MODE, "tray_global_mode", "Global Mode", - direct_mode => DIRECT_MODE, "tray_direct_mode", "Direct Mode", - profiles => PROFILES, "tray_profiles", "Profiles", - proxies => PROXIES, "tray_proxies", "Proxies", - system_proxy => SYSTEM_PROXY, "tray_system_proxy", "System Proxy", - tun_mode => TUN_MODE, "tray_tun_mode", "TUN Mode", - close_all_connections => CLOSE_ALL_CONNECTIONS, "tray_close_all_connections", "Close All Connections", - lightweight_mode => LIGHTWEIGHT_MODE, "tray_lightweight_mode", "LightWeight Mode", - copy_env => COPY_ENV, "tray_copy_env", "Copy Env", - conf_dir => CONF_DIR, "tray_conf_dir", "Conf Dir", - core_dir => CORE_DIR, "tray_core_dir", "Core Dir", - logs_dir => LOGS_DIR, "tray_logs_dir", "Logs Dir", - open_dir => OPEN_DIR, "tray_open_dir", "Open Dir", - app_log => APP_LOG, "tray_app_log", "Open App Log", - core_log => CORE_LOG, "tray_core_log", "Open Core Log", - restart_clash => RESTART_CLASH, "tray_restart_clash", "Restart Clash Core", - restart_app => RESTART_APP, "tray_restart_app", "Restart App", - verge_version => VERGE_VERSION, "tray_verge_version", "Verge Version", - more => MORE, "tray_more", "More", - exit => EXIT, "tray_exit", "Exit", + dashboard => DASHBOARD, "tray_dashboard", "tray.dashboard", + rule_mode => RULE_MODE, "tray_rule_mode", "tray.ruleMode", + global_mode => GLOBAL_MODE, "tray_global_mode", "tray.globalMode", + direct_mode => DIRECT_MODE, "tray_direct_mode", "tray.directMode", + profiles => PROFILES, "tray_profiles", "tray.profiles", + proxies => PROXIES, "tray_proxies", "tray.proxies", + system_proxy => SYSTEM_PROXY, "tray_system_proxy", "tray.systemProxy", + tun_mode => TUN_MODE, "tray_tun_mode", "tray.tunMode", + close_all_connections => CLOSE_ALL_CONNECTIONS, "tray_close_all_connections", "tray.closeAllConnections", + lightweight_mode => LIGHTWEIGHT_MODE, "tray_lightweight_mode", "tray.lightweightMode", + copy_env => COPY_ENV, "tray_copy_env", "tray.copyEnv", + conf_dir => CONF_DIR, "tray_conf_dir", "tray.confDir", + core_dir => CORE_DIR, "tray_core_dir", "tray.coreDir", + logs_dir => LOGS_DIR, "tray_logs_dir", "tray.logsDir", + open_dir => OPEN_DIR, "tray_open_dir", "tray.openDir", + app_log => APP_LOG, "tray_app_log", "tray.appLog", + core_log => CORE_LOG, "tray_core_log", "tray.coreLog", + restart_clash => RESTART_CLASH, "tray_restart_clash", "tray.restartClash", + restart_app => RESTART_APP, "tray_restart_app", "tray.restartApp", + verge_version => VERGE_VERSION, "tray_verge_version", "tray.vergeVersion", + more => MORE, "tray_more", "tray.more", + exit => EXIT, "tray_exit", "tray.exit", } diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 246e39353..574e9294f 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -15,7 +15,7 @@ use crate::{ feat, logging, module::lightweight::is_in_lightweight_mode, singleton_lazy, - utils::{dirs::find_target_icons, i18n::t}, + utils::{dirs::find_target_icons, i18n}, }; use super::handle; @@ -438,6 +438,8 @@ impl Tray { let app_handle = handle::Handle::app_handle(); + i18n::sync_locale().await; + let verge = Config::verge().await.latest_arc(); let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); @@ -464,9 +466,9 @@ impl Tray { } // Get localized strings before using them - let sys_proxy_text = t("SysProxy").await; - let tun_text = t("TUN").await; - let profile_text = t("Profile").await; + let sys_proxy_text = rust_i18n::t!("tray.tooltip.systemProxy"); + let tun_text = rust_i18n::t!("tray.tooltip.tun"); + let profile_text = rust_i18n::t!("tray.tooltip.profile"); let v = env!("CARGO_PKG_VERSION"); let reassembled_version = v.split_once('+').map_or_else( @@ -622,7 +624,7 @@ async fn create_profile_menu_item( CheckMenuItem::with_id( &app_handle, format!("profiles_{profile_uid}"), - t(profile_name).await, + profile_name.as_str(), true, is_current_profile, None::<&str>, @@ -817,6 +819,8 @@ async fn create_tray_menu( ) -> Result> { let current_proxy_mode = mode.unwrap_or(""); + i18n::sync_locale().await; + // 获取当前配置文件的选中代理组信息 let current_profile_selected = { let profiles_config = Config::profiles().await; @@ -877,7 +881,7 @@ async fn create_tray_menu( create_profile_menu_item(app_handle, profile_uid_and_name).await?; // Pre-fetch all localized strings - let texts = &MenuTexts::new().await; + let texts = MenuTexts::new(); // Convert to references only when needed let profile_menu_items_refs: Vec<&dyn IsMenuItem> = profile_menu_items .iter() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 746df76c6..01573ef46 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -25,12 +25,15 @@ use crate::{ use anyhow::Result; use config::Config; use once_cell::sync::OnceCell; +use rust_i18n::i18n; use tauri::{AppHandle, Manager}; #[cfg(target_os = "macos")] use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_deep_link::DeepLinkExt; use utils::logging::Type; +i18n!("locales", fallback = "zh"); + pub static APP_HANDLE: OnceCell = OnceCell::new(); /// Application initialization helper functions mod app_init { diff --git a/src-tauri/src/utils/i18n.rs b/src-tauri/src/utils/i18n.rs index b1c552324..057908283 100644 --- a/src-tauri/src/utils/i18n.rs +++ b/src-tauri/src/utils/i18n.rs @@ -1,43 +1,80 @@ -use crate::{config::Config, utils::dirs}; -use once_cell::sync::Lazy; -use smartstring::alias::String; -use std::{ - collections::HashMap, - fs, - path::PathBuf, - sync::{Arc, RwLock}, -}; +use crate::config::Config; use sys_locale; const DEFAULT_LANGUAGE: &str = "zh"; -type TranslationMap = (String, HashMap>); +fn supported_languages_internal() -> Vec<&'static str> { + rust_i18n::available_locales!() +} -fn get_locales_dir() -> Option { - dirs::app_resources_dir() - .map(|resource_path| resource_path.join("locales")) - .ok() +const fn fallback_language() -> &'static str { + DEFAULT_LANGUAGE +} + +fn locale_alias(locale: &str) -> Option<&'static str> { + match locale { + "ja" | "ja-jp" | "jp" => Some("jp"), + "zh" | "zh-cn" | "zh-hans" | "zh-sg" | "zh-my" | "zh-chs" => Some("zh"), + "zh-tw" | "zh-hk" | "zh-hant" | "zh-mo" | "zh-cht" => Some("zhtw"), + _ => None, + } +} + +fn resolve_supported_language(language: &str) -> Option { + if language.is_empty() { + return None; + } + + let normalized = language.to_lowercase().replace('_', "-"); + + let mut candidates: Vec = Vec::new(); + let mut push_candidate = |candidate: String| { + if !candidate.is_empty() + && !candidates + .iter() + .any(|existing| existing.eq_ignore_ascii_case(&candidate)) + { + candidates.push(candidate); + } + }; + + let segments: Vec<&str> = normalized.split('-').collect(); + + for i in (1..=segments.len()).rev() { + let prefix = segments[..i].join("-"); + if let Some(alias) = locale_alias(&prefix) { + push_candidate(alias.to_string()); + } + push_candidate(prefix); + } + + let supported = supported_languages_internal(); + + candidates.into_iter().find(|candidate| { + supported + .iter() + .any(|&lang| lang.eq_ignore_ascii_case(candidate)) + }) +} + +fn system_language() -> String { + sys_locale::get_locale() + .as_deref() + .and_then(resolve_supported_language) + .unwrap_or_else(|| fallback_language().to_string()) } pub fn get_supported_languages() -> Vec { - let mut languages = Vec::new(); + supported_languages_internal() + .into_iter() + .map(|lang| lang.to_string()) + .collect() +} - if let Some(locales_dir) = get_locales_dir() - && let Ok(entries) = fs::read_dir(locales_dir) - { - for entry in entries.flatten() { - if let Some(file_name) = entry.file_name().to_str() - && let Some(lang) = file_name.strip_suffix(".json") - { - languages.push(lang.into()); - } - } - } - - if languages.is_empty() { - languages.push(DEFAULT_LANGUAGE.into()); - } - languages +pub fn set_locale(language: &str) { + let lang = + resolve_supported_language(language).unwrap_or_else(|| fallback_language().to_string()); + rust_i18n::set_locale(&lang); } pub async fn current_language() -> String { @@ -45,70 +82,18 @@ pub async fn current_language() -> String { .await .latest_arc() .language - .as_deref() - .map(String::from) - .unwrap_or_else(get_system_language) + .clone() + .filter(|lang| !lang.is_empty()) + .and_then(|lang| resolve_supported_language(&lang)) + .unwrap_or_else(system_language) } -static TRANSLATIONS: Lazy> = Lazy::new(|| { - let lang = get_system_language(); - let map = load_lang_file(&lang).unwrap_or_default(); - RwLock::new((lang, map)) -}); - -fn load_lang_file(lang: &str) -> Option>> { - let locales_dir = get_locales_dir()?; - let file_path = locales_dir.join(format!("{lang}.json")); - fs::read_to_string(file_path) - .ok() - .and_then(|content| serde_json::from_str::>(&content).ok()) - .map(|map| { - map.into_iter() - .map(|(k, v)| (k, Arc::from(v.as_str()))) - .collect() - }) +pub async fn sync_locale() -> String { + let language = current_language().await; + set_locale(&language); + language } -fn get_system_language() -> String { - sys_locale::get_locale() - .map(|locale| locale.to_lowercase()) - .and_then(|locale| locale.split(['_', '-']).next().map(String::from)) - .filter(|lang| get_supported_languages().contains(lang)) - .unwrap_or_else(|| DEFAULT_LANGUAGE.into()) -} - -pub async fn t(key: &str) -> Arc { - let current_lang = current_language().await; - - { - if let Ok(cache) = TRANSLATIONS.read() - && cache.0 == current_lang - && let Some(text) = cache.1.get(key) - { - return Arc::clone(text); - } - } - - if let Some(new_map) = load_lang_file(¤t_lang) - && let Ok(mut cache) = TRANSLATIONS.write() - { - *cache = (current_lang.clone(), new_map); - - if let Some(text) = cache.1.get(key) { - return Arc::clone(text); - } - } - - if current_lang != DEFAULT_LANGUAGE - && let Some(default_map) = load_lang_file(DEFAULT_LANGUAGE) - && let Ok(mut cache) = TRANSLATIONS.write() - { - *cache = (DEFAULT_LANGUAGE.into(), default_map); - - if let Some(text) = cache.1.get(key) { - return Arc::clone(text); - } - } - - Arc::from(key) +pub const fn default_language() -> &'static str { + fallback_language() } diff --git a/src-tauri/src/utils/notification.rs b/src-tauri/src/utils/notification.rs index f737560e8..5370132d3 100644 --- a/src-tauri/src/utils/notification.rs +++ b/src-tauri/src/utils/notification.rs @@ -1,5 +1,4 @@ -use crate::{core::handle, utils::i18n::t}; - +use crate::{core::handle, utils::i18n}; use tauri_plugin_notification::NotificationExt; pub enum NotificationEvent<'a> { @@ -27,48 +26,44 @@ fn notify(title: &str, body: &str) { } pub async fn notify_event<'a>(event: NotificationEvent<'a>) { + i18n::sync_locale().await; + match event { NotificationEvent::DashboardToggled => { - notify( - &t("DashboardToggledTitle").await, - &t("DashboardToggledBody").await, - ); + let title = rust_i18n::t!("notifications.dashboardToggled.title").to_string(); + let body = rust_i18n::t!("notifications.dashboardToggled.body").to_string(); + notify(&title, &body); } NotificationEvent::ClashModeChanged { mode } => { - notify( - &t("ClashModeChangedTitle").await, - &t_with_args("ClashModeChangedBody", mode).await, - ); + let title = rust_i18n::t!("notifications.clashModeChanged.title").to_string(); + let body = rust_i18n::t!("notifications.clashModeChanged.body").replace("{mode}", mode); + notify(&title, &body); } NotificationEvent::SystemProxyToggled => { - notify( - &t("SystemProxyToggledTitle").await, - &t("SystemProxyToggledBody").await, - ); + let title = rust_i18n::t!("notifications.systemProxyToggled.title").to_string(); + let body = rust_i18n::t!("notifications.systemProxyToggled.body").to_string(); + notify(&title, &body); } NotificationEvent::TunModeToggled => { - notify( - &t("TunModeToggledTitle").await, - &t("TunModeToggledBody").await, - ); + let title = rust_i18n::t!("notifications.tunModeToggled.title").to_string(); + let body = rust_i18n::t!("notifications.tunModeToggled.body").to_string(); + notify(&title, &body); } NotificationEvent::LightweightModeEntered => { - notify( - &t("LightweightModeEnteredTitle").await, - &t("LightweightModeEnteredBody").await, - ); + let title = rust_i18n::t!("notifications.lightweightModeEntered.title").to_string(); + let body = rust_i18n::t!("notifications.lightweightModeEntered.body").to_string(); + notify(&title, &body); } NotificationEvent::AppQuit => { - notify(&t("AppQuitTitle").await, &t("AppQuitBody").await); + let title = rust_i18n::t!("notifications.appQuit.title").to_string(); + let body = rust_i18n::t!("notifications.appQuit.body").to_string(); + notify(&title, &body); } #[cfg(target_os = "macos")] NotificationEvent::AppHidden => { - notify(&t("AppHiddenTitle").await, &t("AppHiddenBody").await); + let title = rust_i18n::t!("notifications.appHidden.title").to_string(); + let body = rust_i18n::t!("notifications.appHidden.body").to_string(); + notify(&title, &body); } } } - -// 辅助函数,带参数的i18n -async fn t_with_args(key: &str, mode: &str) -> String { - t(key).await.replace("{mode}", mode) -} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 774429c12..daf6d3801 100755 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -11,7 +11,7 @@ "icons/icon.icns", "icons/icon.ico" ], - "resources": ["resources", "resources/locales/*"], + "resources": ["resources"], "publisher": "Clash Verge Rev", "externalBin": ["sidecar/verge-mihomo", "sidecar/verge-mihomo-alpha"], "copyright": "GNU General Public License v3.0", diff --git a/src/components/base/NoticeManager.tsx b/src/components/base/NoticeManager.tsx index f2ae5ef21..dc00eac88 100644 --- a/src/components/base/NoticeManager.tsx +++ b/src/components/base/NoticeManager.tsx @@ -1,14 +1,17 @@ import { CloseRounded } from "@mui/icons-material"; import { Snackbar, Alert, IconButton, Box } from "@mui/material"; import React, { useSyncExternalStore } from "react"; +import { useTranslation } from "react-i18next"; import { subscribeNotices, hideNotice, getSnapshotNotices, } from "@/services/noticeService"; +import type { TranslationKey } from "@/types/generated/i18n-keys"; export const NoticeManager: React.FC = () => { + const { t } = useTranslation(); const currentNotices = useSyncExternalStore( subscribeNotices, getSnapshotNotices, @@ -60,7 +63,61 @@ export const NoticeManager: React.FC = () => { } > - {notice.message} + {notice.i18n + ? (() => { + const params = (notice.i18n.params ?? {}) as Record< + string, + unknown + >; + const { + prefixKey, + prefixParams, + prefix, + message, + ...restParams + } = params; + + const prefixKeyParams = + prefixParams && + typeof prefixParams === "object" && + prefixParams !== null + ? (prefixParams as Record) + : undefined; + + const resolvedPrefix = + typeof prefixKey === "string" + ? t(prefixKey as TranslationKey, { + defaultValue: prefixKey, + ...(prefixKeyParams ?? {}), + ...restParams, + }) + : typeof prefix === "string" + ? prefix + : undefined; + + const finalParams: Record = { + ...restParams, + }; + if (resolvedPrefix !== undefined) { + finalParams.prefix = resolvedPrefix; + } + if (typeof message === "string") { + finalParams.message = message; + } + + const defaultValue = + resolvedPrefix && typeof message === "string" + ? `${resolvedPrefix} ${message}` + : typeof message === "string" + ? message + : undefined; + + return t(notice.i18n.key as TranslationKey, { + defaultValue, + ...finalParams, + }); + })() + : notice.message} ))} diff --git a/src/components/base/base-empty.tsx b/src/components/base/base-empty.tsx index dcf04bbb9..acbe36c46 100644 --- a/src/components/base/base-empty.tsx +++ b/src/components/base/base-empty.tsx @@ -1,16 +1,25 @@ import { InboxRounded } from "@mui/icons-material"; import { alpha, Box, Typography } from "@mui/material"; +import type { ReactNode } from "react"; import { useTranslation } from "react-i18next"; +import type { TranslationKey } from "@/types/generated/i18n-keys"; + interface Props { - text?: React.ReactNode; - extra?: React.ReactNode; + text?: ReactNode; + textKey?: TranslationKey; + extra?: ReactNode; } -export const BaseEmpty = (props: Props) => { - const { text = "Empty", extra } = props; +export const BaseEmpty = ({ + text, + textKey = "shared.statuses.empty", + extra, +}: Props) => { const { t } = useTranslation(); + const resolvedText: ReactNode = text !== undefined ? text : t(textKey); + return ( ({ @@ -24,7 +33,7 @@ export const BaseEmpty = (props: Props) => { })} > - {t(`${text}`)} + {resolvedText} {extra} ); diff --git a/src/components/base/base-search-box.tsx b/src/components/base/base-search-box.tsx index 4ce93a306..beb961e0c 100644 --- a/src/components/base/base-search-box.tsx +++ b/src/components/base/base-search-box.tsx @@ -135,7 +135,7 @@ export const BaseSearchBox = ({ if (useRegularExpression && value) { const isValid = validateRegex(value); if (!isValid) { - setErrorMessage(t("Invalid regular expression")); + setErrorMessage(t("shared.validation.invalidRegex")); } } @@ -156,7 +156,7 @@ export const BaseSearchBox = ({ } else { const value = inputRef.current?.value ?? ""; if (value && !validateRegex(value)) { - setErrorMessage(t("Invalid regular expression")); + setErrorMessage(t("shared.validation.invalidRegex")); } } return next; @@ -173,7 +173,7 @@ export const BaseSearchBox = ({ size="small" variant="outlined" spellCheck="false" - placeholder={placeholder ?? t("Filter conditions")} + placeholder={placeholder ?? t("shared.placeholders.filter")} sx={{ input: { py: 0.65, px: 1.25 } }} onChange={onChange} error={!!errorMessage} @@ -182,7 +182,7 @@ export const BaseSearchBox = ({ sx: { pr: 1 }, endAdornment: ( - +
- +
- +
{ size="small" variant="outlined" spellCheck="false" - placeholder={t("Filter conditions")} + placeholder={t("shared.placeholders.filter")} sx={{ input: { py: 0.65, px: 1.25 } }} {...props} /> diff --git a/src/components/common/traffic-error-boundary.tsx b/src/components/common/traffic-error-boundary.tsx index c665e2a94..763dcbbea 100644 --- a/src/components/common/traffic-error-boundary.tsx +++ b/src/components/common/traffic-error-boundary.tsx @@ -177,7 +177,7 @@ const TrafficErrorFallback: React.FC = ({ - {t("Traffic Statistics Error")} + {t("shared.feedback.errors.trafficStats")} = ({ textAlign="center" sx={{ mb: 2 }} > - {t( - "The traffic statistics component encountered an error and has been disabled to prevent crashes.", - )} + {t("shared.feedback.errors.trafficStatsDescription")} - Error: {error?.message || "Unknown error"} + Error:{" "} + {error instanceof Error ? error.message : "Unknown error"} {retryCount > 0 && ( - {t("Retry attempts")}: {retryCount}/{maxRetries} + {t("shared.labels.retryAttempts")}: {retryCount}/{maxRetries} )} @@ -211,12 +210,12 @@ const TrafficErrorFallback: React.FC = ({ onClick={onRetry} size="small" > - {t("Retry")} + {t("shared.actions.retry")} )} diff --git a/src/components/connection/connection-detail.tsx b/src/components/connection/connection-detail.tsx index f580ae006..7e5bc8737 100644 --- a/src/components/connection/connection-detail.tsx +++ b/src/components/connection/connection-detail.tsx @@ -1,8 +1,8 @@ import { Box, Button, Snackbar, useTheme } from "@mui/material"; import { useLockFn } from "ahooks"; import dayjs from "dayjs"; -import { t } from "i18next"; import { useImperativeHandle, useState, type Ref } from "react"; +import { useTranslation } from "react-i18next"; import { closeConnections } from "tauri-plugin-mihomo-api"; import parseTraffic from "@/utils/parse-traffic"; @@ -55,6 +55,7 @@ interface InnerProps { } const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { + const { t } = useTranslation(); const { metadata, rulePayload } = data; const theme = useTheme(); const chains = [...data.chains].reverse().join(" / "); @@ -67,34 +68,52 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { : metadata.remoteDestination; const information = [ - { label: t("Host"), value: host }, - { label: t("Downloaded"), value: parseTraffic(data.download).join(" ") }, - { label: t("Uploaded"), value: parseTraffic(data.upload).join(" ") }, + { label: t("connections.components.fields.host"), value: host }, { - label: t("DL Speed"), + label: t("shared.labels.downloaded"), + value: parseTraffic(data.download).join(" "), + }, + { + label: t("shared.labels.uploaded"), + value: parseTraffic(data.upload).join(" "), + }, + { + label: t("connections.components.fields.dlSpeed"), value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s", }, { - label: t("UL Speed"), + label: t("connections.components.fields.ulSpeed"), value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s", }, { - label: t("Chains"), + label: t("connections.components.fields.chains"), value: chains, }, - { label: t("Rule"), value: rule }, + { label: t("connections.components.fields.rule"), value: rule }, { - label: t("Process"), + label: t("connections.components.fields.process"), value: `${metadata.process}${metadata.processPath ? `(${metadata.processPath})` : ""}`, }, - { label: t("Time"), value: dayjs(data.start).fromNow() }, { - label: t("Source"), + label: t("connections.components.fields.time"), + value: dayjs(data.start).fromNow(), + }, + { + label: t("connections.components.fields.source"), value: `${metadata.sourceIP}:${metadata.sourcePort}`, }, - { label: t("Destination"), value: Destination }, - { label: t("DestinationPort"), value: `${metadata.destinationPort}` }, - { label: t("Type"), value: `${metadata.type}(${metadata.network})` }, + { + label: t("connections.components.fields.destination"), + value: Destination, + }, + { + label: t("connections.components.fields.destinationPort"), + value: `${metadata.destinationPort}`, + }, + { + label: t("connections.components.fields.type"), + value: `${metadata.type}(${metadata.network})`, + }, ]; const onDelete = useLockFn(async () => closeConnections(data.id)); @@ -118,13 +137,13 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { diff --git a/src/components/connection/connection-item.tsx b/src/components/connection/connection-item.tsx index a596ec72b..d978733da 100644 --- a/src/components/connection/connection-item.tsx +++ b/src/components/connection/connection-item.tsx @@ -9,6 +9,7 @@ import { } from "@mui/material"; import { useLockFn } from "ahooks"; import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; import { closeConnections } from "tauri-plugin-mihomo-api"; import parseTraffic from "@/utils/parse-traffic"; @@ -33,6 +34,7 @@ export const ConnectionItem = (props: Props) => { const { value, onShowDetail } = props; const { id, metadata, chains, start, curUpload, curDownload } = value; + const { t } = useTranslation(); const onDelete = useLockFn(async () => closeConnections(id)); const showTraffic = curUpload! >= 100 || curDownload! >= 100; @@ -42,7 +44,13 @@ export const ConnectionItem = (props: Props) => { dense sx={{ borderBottom: "1px solid var(--divider-color)" }} secondaryAction={ - + } diff --git a/src/components/connection/connection-table.tsx b/src/components/connection/connection-table.tsx index 3eea11b12..8761a522a 100644 --- a/src/components/connection/connection-table.tsx +++ b/src/components/connection/connection-table.tsx @@ -162,13 +162,13 @@ export const ConnectionTable = (props: Props) => { return [ { field: "host", - headerName: t("Host"), + headerName: t("connections.components.fields.host"), width: columnWidths["host"] || 220, minWidth: 180, }, { field: "download", - headerName: t("Downloaded"), + headerName: t("shared.labels.downloaded"), width: columnWidths["download"] || 88, align: "right", headerAlign: "right", @@ -176,7 +176,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "upload", - headerName: t("Uploaded"), + headerName: t("shared.labels.uploaded"), width: columnWidths["upload"] || 88, align: "right", headerAlign: "right", @@ -184,7 +184,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "dlSpeed", - headerName: t("DL Speed"), + headerName: t("connections.components.fields.dlSpeed"), width: columnWidths["dlSpeed"] || 88, align: "right", headerAlign: "right", @@ -192,7 +192,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "ulSpeed", - headerName: t("UL Speed"), + headerName: t("connections.components.fields.ulSpeed"), width: columnWidths["ulSpeed"] || 88, align: "right", headerAlign: "right", @@ -200,25 +200,25 @@ export const ConnectionTable = (props: Props) => { }, { field: "chains", - headerName: t("Chains"), + headerName: t("connections.components.fields.chains"), width: columnWidths["chains"] || 340, minWidth: 180, }, { field: "rule", - headerName: t("Rule"), + headerName: t("connections.components.fields.rule"), width: columnWidths["rule"] || 280, minWidth: 180, }, { field: "process", - headerName: t("Process"), + headerName: t("connections.components.fields.process"), width: columnWidths["process"] || 220, minWidth: 180, }, { field: "time", - headerName: t("Time"), + headerName: t("connections.components.fields.time"), width: columnWidths["time"] || 120, minWidth: 100, align: "right", @@ -229,19 +229,19 @@ export const ConnectionTable = (props: Props) => { }, { field: "source", - headerName: t("Source"), + headerName: t("connections.components.fields.source"), width: columnWidths["source"] || 200, minWidth: 130, }, { field: "remoteDestination", - headerName: t("Destination"), + headerName: t("connections.components.fields.destination"), width: columnWidths["remoteDestination"] || 200, minWidth: 130, }, { field: "type", - headerName: t("Type"), + headerName: t("connections.components.fields.type"), width: columnWidths["type"] || 160, minWidth: 100, }, @@ -250,7 +250,6 @@ export const ConnectionTable = (props: Props) => { const handleColumnResize = (params: GridColumnResizeParams) => { const { colDef, width } = params; - console.log("Column resize:", colDef.field, width); setColumnWidths((prev) => ({ ...prev, [colDef.field]: width, diff --git a/src/components/home/clash-info-card.tsx b/src/components/home/clash-info-card.tsx index 9b6ff4b71..ed62732f5 100644 --- a/src/components/home/clash-info-card.tsx +++ b/src/components/home/clash-info-card.tsx @@ -32,7 +32,7 @@ export const ClashInfoCard = () => { - {t("Core Version")} + {t("home.components.clashInfo.fields.coreVersion")} {clashVersion || "-"} @@ -41,7 +41,7 @@ export const ClashInfoCard = () => { - {t("System Proxy Address")} + {t("home.components.clashInfo.fields.systemProxyAddress")} {systemProxyAddress} @@ -50,7 +50,7 @@ export const ClashInfoCard = () => { - {t("Mixed Port")} + {t("home.components.clashInfo.fields.mixedPort")} {clashConfig.mixedPort || "-"} @@ -59,7 +59,7 @@ export const ClashInfoCard = () => { - {t("Uptime")} + {t("home.components.clashInfo.fields.uptime")} {formattedUptime} @@ -68,7 +68,7 @@ export const ClashInfoCard = () => { - {t("Rules Count")} + {t("home.components.clashInfo.fields.rulesCount")} {rules.length} @@ -87,7 +87,7 @@ export const ClashInfoCard = () => { return ( } iconColor="warning" action={null} diff --git a/src/components/home/clash-mode-card.tsx b/src/components/home/clash-mode-card.tsx index 10c56fb7d..ea48128ca 100644 --- a/src/components/home/clash-mode-card.tsx +++ b/src/components/home/clash-mode-card.tsx @@ -12,6 +12,31 @@ import { closeAllConnections } from "tauri-plugin-mihomo-api"; import { useVerge } from "@/hooks/use-verge"; import { useAppData } from "@/providers/app-data-context"; import { patchClashMode } from "@/services/cmds"; +import type { TranslationKey } from "@/types/generated/i18n-keys"; + +const CLASH_MODES = ["rule", "global", "direct"] as const; +type ClashMode = (typeof CLASH_MODES)[number]; + +const isClashMode = (mode: string): mode is ClashMode => + (CLASH_MODES as readonly string[]).includes(mode); + +const MODE_META: Record< + ClashMode, + { label: TranslationKey; description: TranslationKey } +> = { + rule: { + label: "home.components.clashMode.labels.rule", + description: "home.components.clashMode.descriptions.rule", + }, + global: { + label: "home.components.clashMode.labels.global", + description: "home.components.clashMode.descriptions.global", + }, + direct: { + label: "home.components.clashMode.labels.direct", + description: "home.components.clashMode.descriptions.direct", + }, +}; export const ClashModeCard = () => { const { t } = useTranslation(); @@ -19,19 +44,21 @@ export const ClashModeCard = () => { const { clashConfig, refreshClashConfig } = useAppData(); // 支持的模式列表 - const modeList = useMemo(() => ["rule", "global", "direct"] as const, []); + const modeList = CLASH_MODES; // 直接使用API返回的模式,不维护本地状态 const currentMode = clashConfig?.mode?.toLowerCase(); + const currentModeKey = + typeof currentMode === "string" && isClashMode(currentMode) + ? currentMode + : undefined; const modeDescription = useMemo(() => { - if (typeof currentMode === "string" && currentMode.length > 0) { - return t( - `${currentMode[0].toLocaleUpperCase()}${currentMode.slice(1)} Mode Description`, - ); + if (currentModeKey) { + return t(MODE_META[currentModeKey].description); } - return t("Core communication error"); - }, [currentMode, t]); + return t("home.components.clashMode.errors.communication"); + }, [currentModeKey, t]); // 模式图标映射 const modeIcons = useMemo( @@ -44,8 +71,8 @@ export const ClashModeCard = () => { ); // 切换模式的处理函数 - const onChangeMode = useLockFn(async (mode: string) => { - if (mode === currentMode) return; + const onChangeMode = useLockFn(async (mode: ClashMode) => { + if (mode === currentModeKey) return; if (verge?.auto_close_connection) { closeAllConnections(); } @@ -60,7 +87,7 @@ export const ClashModeCard = () => { }); // 按钮样式 - const buttonStyles = (mode: string) => ({ + const buttonStyles = (mode: ClashMode) => ({ cursor: "pointer", px: 2, py: 1.2, @@ -68,8 +95,8 @@ export const ClashModeCard = () => { alignItems: "center", justifyContent: "center", gap: 1, - bgcolor: mode === currentMode ? "primary.main" : "background.paper", - color: mode === currentMode ? "primary.contrastText" : "text.primary", + bgcolor: mode === currentModeKey ? "primary.main" : "background.paper", + color: mode === currentModeKey ? "primary.contrastText" : "text.primary", borderRadius: 1.5, transition: "all 0.2s ease-in-out", position: "relative", @@ -82,7 +109,7 @@ export const ClashModeCard = () => { transform: "translateY(1px)", }, "&::after": - mode === currentMode + mode === currentModeKey ? { content: '""', position: "absolute", @@ -128,7 +155,7 @@ export const ClashModeCard = () => { {modeList.map((mode) => ( onChangeMode(mode)} sx={buttonStyles(mode)} > @@ -137,10 +164,10 @@ export const ClashModeCard = () => { variant="body2" sx={{ textTransform: "capitalize", - fontWeight: mode === currentMode ? 600 : 400, + fontWeight: mode === currentModeKey ? 600 : 400, }} > - {t(mode)} + {t(MODE_META[mode].label)} ))} diff --git a/src/components/home/current-proxy-card.tsx b/src/components/home/current-proxy-card.tsx index c50619386..c29db668b 100644 --- a/src/components/home/current-proxy-card.tsx +++ b/src/components/home/current-proxy-card.tsx @@ -811,11 +811,11 @@ export const CurrentProxyCard = () => { const getSortTooltip = (): string => { switch (sortType) { case 0: - return t("Sort by default"); + return t("proxies.page.tooltips.sortDefault"); case 1: - return t("Sort by delay"); + return t("proxies.page.tooltips.sortDelay"); case 2: - return t("Sort by name"); + return t("proxies.page.tooltips.sortName"); default: return ""; } @@ -823,7 +823,7 @@ export const CurrentProxyCard = () => { return ( { iconColor={currentProxy ? "primary" : undefined} action={ - + { sx={{ borderRadius: 1.5 }} endIcon={} > - {t("Label-Proxies")} + {t("layout.components.navigation.tabs.proxies")} } @@ -906,7 +908,7 @@ export const CurrentProxyCard = () => { {isGlobalMode && ( @@ -914,7 +916,7 @@ export const CurrentProxyCard = () => { {isDirectMode && ( @@ -954,12 +956,14 @@ export const CurrentProxyCard = () => { size="small" sx={{ mb: 1.5 }} > - {t("Group")} + + {t("home.components.currentProxy.labels.group")} + { ) : ( - {t("No active proxy node")} + {t("home.components.currentProxy.labels.noActiveNode")} )} diff --git a/src/components/home/enhanced-canvas-traffic-graph.tsx b/src/components/home/enhanced-canvas-traffic-graph.tsx index 8e59c4d18..a77f4db85 100644 --- a/src/components/home/enhanced-canvas-traffic-graph.tsx +++ b/src/components/home/enhanced-canvas-traffic-graph.tsx @@ -851,7 +851,9 @@ export const EnhancedCanvasTrafficGraph = memo( // 获取时间范围文本 const getTimeRangeText = useCallback(() => { - return t("{{time}} Minutes", { time: timeRange }); + return t("home.components.traffic.patterns.minutes", { + time: timeRange, + }); }, [timeRange, t]); return ( @@ -934,7 +936,7 @@ export const EnhancedCanvasTrafficGraph = memo( textAlign: "right", }} > - {t("Upload")} + {t("home.components.traffic.legends.upload")} - {t("Download")} + {t("home.components.traffic.legends.download")} diff --git a/src/components/home/enhanced-traffic-stats.tsx b/src/components/home/enhanced-traffic-stats.tsx index 199bbd6fa..589c287cc 100644 --- a/src/components/home/enhanced-traffic-stats.tsx +++ b/src/components/home/enhanced-traffic-stats.tsx @@ -219,42 +219,42 @@ export const EnhancedTrafficStats = () => { () => [ { icon: , - title: t("Upload Speed"), + title: t("home.components.traffic.metrics.uploadSpeed"), value: parsedData.up, unit: `${parsedData.upUnit}/s`, color: "secondary" as const, }, { icon: , - title: t("Download Speed"), + title: t("home.components.traffic.metrics.downloadSpeed"), value: parsedData.down, unit: `${parsedData.downUnit}/s`, color: "primary" as const, }, { icon: , - title: t("Active Connections"), + title: t("home.components.traffic.metrics.activeConnections"), value: parsedData.connectionsCount, unit: "", color: "success" as const, }, { icon: , - title: t("Uploaded"), + title: t("shared.labels.uploaded"), value: parsedData.uploadTotal, unit: parsedData.uploadTotalUnit, color: "secondary" as const, }, { icon: , - title: t("Downloaded"), + title: t("shared.labels.downloaded"), value: parsedData.downloadTotal, unit: parsedData.downloadTotalUnit, color: "primary" as const, }, { icon: , - title: t("Memory Usage"), + title: t("home.components.traffic.metrics.memoryUsage"), value: parsedData.inuse, unit: parsedData.inuseUnit, color: "error" as const, diff --git a/src/components/home/home-profile-card.tsx b/src/components/home/home-profile-card.tsx index 3638f0f0d..86d0e3ef0 100644 --- a/src/components/home/home-profile-card.tsx +++ b/src/components/home/home-profile-card.tsx @@ -111,7 +111,7 @@ const ProfileDetails = ({ noWrap sx={{ display: "flex", alignItems: "center" }} > - {t("From")}: + {t("shared.labels.from")}: {current.home ? ( - {t("Update Time")}:{" "} + {t("shared.labels.updateTime")}:{" "} {dayjs(current.updated * 1000).format("YYYY-MM-DD HH:mm")} @@ -199,7 +199,7 @@ const ProfileDetails = ({ - {t("Used / Total")}:{" "} + {t("shared.labels.usedTotal")}:{" "} {parseTraffic(usedTraffic)} /{" "} {parseTraffic(current.extra.total)} @@ -211,7 +211,7 @@ const ProfileDetails = ({ - {t("Expire Time")}:{" "} + {t("shared.labels.expireTime")}:{" "} {parseExpire(current.extra.expire)} @@ -266,10 +266,10 @@ const EmptyProfile = ({ onClick }: { onClick: () => void }) => { sx={{ fontSize: 60, color: "primary.main", mb: 2 }} /> - {t("Import")} {t("Profiles")} + {t("profiles.page.actions.import")} {t("profiles.page.title")} - {t("Click to import subscription")} + {t("profiles.components.card.labels.clickToImport")} ); @@ -296,8 +296,8 @@ export const HomeProfileCard = ({ // 刷新首页数据 refreshAll(); - } catch (err: any) { - showNotice("error", err.message || err.toString(), 3000); + } catch (err) { + showNotice.error(err, 3000); } finally { setUpdating(false); } @@ -310,7 +310,7 @@ export const HomeProfileCard = ({ // 卡片标题 const cardTitle = useMemo(() => { - if (!current) return t("Profiles"); + if (!current) return t("profiles.page.title"); if (!current.home) return current.name; @@ -363,7 +363,7 @@ export const HomeProfileCard = ({ endIcon={} sx={{ borderRadius: 1.5 }} > - {t("Label-Profiles")} + {t("layout.components.navigation.tabs.proxies")} ); }, [current, goToProfiles, t]); diff --git a/src/components/home/ip-info-card.tsx b/src/components/home/ip-info-card.tsx index 585460dc6..a8f81d381 100644 --- a/src/components/home/ip-info-card.tsx +++ b/src/components/home/ip-info-card.tsx @@ -68,8 +68,12 @@ export const IpInfoCard = () => { const data = await getIpInfo(); setIpInfo(data); setCountdown(IP_REFRESH_SECONDS); - } catch (err: any) { - setError(err.message || t("Failed to get IP info")); + } catch (err) { + setError( + err instanceof Error + ? err.message + : t("home.components.ipInfo.errors.load"), + ); } finally { setLoading(false); } @@ -114,7 +118,7 @@ export const IpInfoCard = () => { if (loading) { return ( } iconColor="info" action={ @@ -137,7 +141,7 @@ export const IpInfoCard = () => { if (error) { return ( } iconColor="info" action={ @@ -160,7 +164,7 @@ export const IpInfoCard = () => { {error} @@ -170,7 +174,7 @@ export const IpInfoCard = () => { // 渲染正常数据 return ( } iconColor="info" action={ @@ -222,7 +226,7 @@ export const IpInfoCard = () => { maxWidth: "100%", }} > - {ipInfo?.country || t("Unknown")} + {ipInfo?.country || t("home.components.ipInfo.labels.unknown")} @@ -232,7 +236,7 @@ export const IpInfoCard = () => { color="text.secondary" sx={{ flexShrink: 0 }} > - {t("IP")}: + {t("home.components.ipInfo.labels.ip")}: { {/* 右侧:组织、ISP和位置信息 */} - - + + - + @@ -297,7 +310,7 @@ export const IpInfoCard = () => { }} > - {t("Auto refresh")}: {countdown}s + {t("home.components.ipInfo.labels.autoRefresh")}: {countdown}s { const { enable_tun_mode } = verge ?? {}; - const handleError = (err: Error) => { - showNotice("error", err.message || err.toString()); + const handleError = (err: unknown) => { + showNotice.error(err); }; const handleTabChange = (tab: string) => { @@ -160,18 +160,18 @@ export const ProxyTunCard: FC = () => { if (activeTab === "system") { return { text: systemProxyActualState - ? t("System Proxy Enabled") - : t("System Proxy Disabled"), - tooltip: t("System Proxy Info"), + ? t("home.components.proxyTun.status.systemProxyEnabled") + : t("home.components.proxyTun.status.systemProxyDisabled"), + tooltip: t("home.components.proxyTun.tooltips.systemProxy"), }; } else { return { text: !isTunModeAvailable - ? t("TUN Mode Service Required") + ? t("home.components.proxyTun.status.tunModeServiceRequired") : enable_tun_mode - ? t("TUN Mode Enabled") - : t("TUN Mode Disabled"), - tooltip: t("TUN Mode Intercept Info"), + ? t("home.components.proxyTun.status.tunModeEnabled") + : t("home.components.proxyTun.status.tunModeDisabled"), + tooltip: t("home.components.proxyTun.tooltips.tunMode"), }; } }, [ @@ -198,14 +198,14 @@ export const ProxyTunCard: FC = () => { isActive={activeTab === "system"} onClick={() => handleTabChange("system")} icon={ComputerRounded} - label={t("System Proxy")} + label={t("settings.sections.system.toggles.systemProxy")} hasIndicator={systemProxyActualState} /> handleTabChange("tun")} icon={TroubleshootRounded} - label={t("Tun Mode")} + label={t("settings.sections.system.toggles.tunMode")} hasIndicator={enable_tun_mode && isTunModeAvailable} /> @@ -236,7 +236,11 @@ export const ProxyTunCard: FC = () => { > diff --git a/src/components/home/system-info-card.tsx b/src/components/home/system-info-card.tsx index e9f483b7f..8697291f5 100644 --- a/src/components/home/system-info-card.tsx +++ b/src/components/home/system-info-card.tsx @@ -174,13 +174,15 @@ export const SystemInfoCard = () => { try { const info = await checkUpdate(); if (!info?.available) { - showNotice("success", t("Currently on the Latest Version")); + showNotice.success( + "settings.components.verge.advanced.notifications.latestVersion", + ); } else { - showNotice("info", t("Update Available"), 2000); + showNotice.info("shared.feedback.notifications.updateAvailable", 2000); goToSettings(); } - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -217,11 +219,11 @@ export const SystemInfoCard = () => { <> ); @@ -229,21 +231,21 @@ export const SystemInfoCard = () => { return ( ); } else if (isSidecarMode) { return ( ); } else { return ( ); } @@ -254,13 +256,13 @@ export const SystemInfoCard = () => { if (isAdminMode) { // 判断是否同时处于服务模式 if (!isSidecarMode) { - return t("Administrator + Service Mode"); + return t("home.components.systemInfo.badges.adminServiceMode"); } - return t("Administrator Mode"); + return t("home.components.systemInfo.badges.adminMode"); } else if (isSidecarMode) { - return t("Sidecar Mode"); + return t("home.components.systemInfo.badges.sidecarMode"); } else { - return t("Service Mode"); + return t("home.components.systemInfo.badges.serviceMode"); } }; @@ -269,11 +271,15 @@ export const SystemInfoCard = () => { return ( } iconColor="error" action={ - + } @@ -281,7 +287,7 @@ export const SystemInfoCard = () => { - {t("OS Info")} + {t("home.components.systemInfo.fields.osInfo")} {systemState.osInfo} @@ -294,19 +300,23 @@ export const SystemInfoCard = () => { alignItems="center" > - {t("Auto Launch")} + {t("home.components.systemInfo.fields.autoLaunch")} {isAdminMode && ( )} { alignItems="center" > - {t("Running Mode")} + {t("home.components.systemInfo.fields.runningMode")} { - {t("Last Check Update")} + {t("home.components.systemInfo.fields.lastCheckUpdate")} { - {t("Verge Version")} + {t("home.components.systemInfo.fields.vergeVersion")} v{appVersion} diff --git a/src/components/home/test-card.tsx b/src/components/home/test-card.tsx index 518500907..903f3c7ce 100644 --- a/src/components/home/test-card.tsx +++ b/src/components/home/test-card.tsx @@ -173,16 +173,16 @@ export const TestCard = () => { return ( } action={ - + - + diff --git a/src/components/layout/layout-traffic.tsx b/src/components/layout/layout-traffic.tsx index 9b37c5252..36c35ac2e 100644 --- a/src/components/layout/layout-traffic.tsx +++ b/src/components/layout/layout-traffic.tsx @@ -87,7 +87,7 @@ export const LayoutTraffic = () => { { { {displayMemory && ( { diff --git a/src/components/profile/editor-viewer.tsx b/src/components/profile/editor-viewer.tsx index 016344617..bc95531cc 100644 --- a/src/components/profile/editor-viewer.tsx +++ b/src/components/profile/editor-viewer.tsx @@ -97,7 +97,7 @@ export const EditorViewer = (props: Props) => { onClose, } = props; - const resolvedTitle = title ?? t("Edit File"); + const resolvedTitle = title ?? t("profiles.components.menu.editFile"); const resolvedInitialData = useMemo( () => initialData ?? Promise.resolve(""), [initialData], @@ -130,8 +130,8 @@ export const EditorViewer = (props: Props) => { try { currData.current = value; onChange?.(prevData.current, currData.current); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -141,16 +141,16 @@ export const EditorViewer = (props: Props) => { onSave?.(prevData.current, currData.current); } onClose(); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); const handleClose = useLockFn(async () => { try { onClose(); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -200,7 +200,9 @@ export const EditorViewer = (props: Props) => { }, mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例 readOnly: readOnly, // 只读模式 - readOnlyMessage: { value: t("ReadOnlyMessage") }, // 只读模式尝试编辑时的提示信息 + readOnlyMessage: { + value: t("profiles.modals.editor.messages.readOnly"), + }, // 只读模式尝试编辑时的提示信息 renderValidationDecorations: "on", // 只读模式下显示校验信息 quickSuggestions: { strings: true, // 字符串类型的建议 @@ -229,7 +231,7 @@ export const EditorViewer = (props: Props) => { size="medium" color="inherit" sx={{ display: readOnly ? "none" : "" }} - title={t("Format document")} + title={t("profiles.modals.editor.actions.format")} onClick={() => editorRef.current ?.getAction("editor.action.formatDocument") @@ -241,7 +243,9 @@ export const EditorViewer = (props: Props) => { appWindow.toggleMaximize().then(editorResize)} > {isMaximized ? : } @@ -251,11 +255,11 @@ export const EditorViewer = (props: Props) => { {!readOnly && ( )} diff --git a/src/components/profile/file-input.tsx b/src/components/profile/file-input.tsx index 5d8511b76..20b4ad20c 100644 --- a/src/components/profile/file-input.tsx +++ b/src/components/profile/file-input.tsx @@ -42,7 +42,7 @@ export const FileInput = (props: Props) => { sx={{ flex: "none" }} onClick={() => inputRef.current?.click()} > - {t("Choose File")} + {t("profiles.components.fileInput.chooseFile")} = { + select: "proxies.components.enums.strategies.select", + "url-test": "proxies.components.enums.strategies.url-test", + fallback: "proxies.components.enums.strategies.fallback", + "load-balance": "proxies.components.enums.strategies.load-balance", + relay: "proxies.components.enums.strategies.relay", +}; + +const PROXY_POLICY_LABEL_KEYS: Record = + builtinProxyPolicies.reduce( + (acc, policy) => { + acc[policy] = + `proxies.components.enums.policies.${policy}` as TranslationKey; + return acc; + }, + {} as Record, + ); + const normalizeDeleteSeq = (input?: unknown): string[] => { if (!Array.isArray(input)) { return []; @@ -121,6 +140,20 @@ export const GroupsEditorViewer = (props: Props) => { const { mergeUid, proxiesUid, profileUid, property, open, onClose, onSave } = props; const { t } = useTranslation(); + const translateStrategy = useCallback( + (value: string) => + PROXY_STRATEGY_LABEL_KEYS[value] + ? t(PROXY_STRATEGY_LABEL_KEYS[value]) + : value, + [t], + ); + const translatePolicy = useCallback( + (value: string) => + PROXY_POLICY_LABEL_KEYS[value] + ? t(PROXY_POLICY_LABEL_KEYS[value]) + : value, + [t], + ); const themeMode = useThemeMode(); const [prevData, setPrevData] = useState(""); const [currData, setCurrData] = useState(""); @@ -369,7 +402,7 @@ export const GroupsEditorViewer = (props: Props) => { const validateGroup = () => { const group = formIns.getValues(); if (group.name === "") { - throw new Error(t("Group Name Required")); + throw new Error(t("profiles.modals.groupsEditor.errors.nameRequired")); } }; @@ -384,12 +417,12 @@ export const GroupsEditorViewer = (props: Props) => { } await saveProfileFile(property, nextData); - showNotice("success", t("Saved Successfully")); + showNotice.success("shared.feedback.notifications.saved"); setPrevData(nextData); onSave?.(prevData, nextData); onClose(); - } catch (err: any) { - showNotice("error", err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -398,7 +431,7 @@ export const GroupsEditorViewer = (props: Props) => { { - {t("Edit Groups")} + {t("profiles.modals.groupsEditor.title")} @@ -436,7 +471,9 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + { "relay", ]} value={field.value} + getOptionLabel={translateStrategy} renderOption={(props, option) => ( -
  • - {option} +
  • + {translateStrategy(option)}
  • )} onChange={(_, value) => value && field.onChange(value)} @@ -464,7 +502,9 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { onChange={(_, value) => value && field.onChange(value)} renderInput={(params) => } renderOption={(props, option) => ( -
  • - {option} +
  • + {translatePolicy(option)}
  • )} + getOptionLabel={translatePolicy} />
    )} @@ -521,7 +568,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { input: { endAdornment: ( - {t("seconds")} + {t("shared.units.seconds")} ), }, @@ -601,7 +664,7 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + { input: { endAdornment: ( - {t("millis")} + {t("shared.units.milliseconds")} ), }, @@ -629,7 +692,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + { control={control} render={({ field }) => ( - + )} @@ -769,7 +860,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + )} @@ -779,7 +874,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + )} @@ -789,7 +888,9 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + )} @@ -799,7 +900,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + )} @@ -809,7 +914,11 @@ export const GroupsEditorViewer = (props: Props) => { control={control} render={({ field }) => ( - + )} @@ -825,16 +934,18 @@ export const GroupsEditorViewer = (props: Props) => { validateGroup(); for (const item of [...prependSeq, ...groupList]) { if (item.name === formIns.getValues().name) { - throw new Error(t("Group Name Already Exists")); + throw new Error( + t("profiles.modals.groupsEditor.errors.nameExists"), + ); } } setPrependSeq([formIns.getValues(), ...prependSeq]); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }} > - {t("Prepend Group")} + {t("profiles.modals.groupsEditor.actions.prepend")} @@ -847,16 +958,18 @@ export const GroupsEditorViewer = (props: Props) => { validateGroup(); for (const item of [...appendSeq, ...groupList]) { if (item.name === formIns.getValues().name) { - throw new Error(t("Group Name Already Exists")); + throw new Error( + t("profiles.modals.groupsEditor.errors.nameExists"), + ); } } setAppendSeq([...appendSeq, formIns.getValues()]); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }} > - {t("Append Group")} + {t("profiles.modals.groupsEditor.actions.append")} @@ -1007,11 +1120,11 @@ export const GroupsEditorViewer = (props: Props) => { diff --git a/src/components/profile/log-viewer.tsx b/src/components/profile/log-viewer.tsx index 9375ace3e..90349ccca 100644 --- a/src/components/profile/log-viewer.tsx +++ b/src/components/profile/log-viewer.tsx @@ -26,7 +26,7 @@ export const LogViewer = (props: Props) => { return ( - {t("Script Console")} + {t("profiles.modals.logViewer.title")} { diff --git a/src/components/profile/profile-item.tsx b/src/components/profile/profile-item.tsx index 48aa6385b..7f928336d 100644 --- a/src/components/profile/profile-item.tsx +++ b/src/components/profile/profile-item.tsx @@ -36,6 +36,7 @@ import { } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; import { useLoadingCache, useSetLoadingCache } from "@/services/states"; +import type { TranslationKey } from "@/types/generated/i18n-keys"; import parseTraffic from "@/utils/parse-traffic"; import { ProfileBox } from "./profile-box"; @@ -120,34 +121,46 @@ export const ProfileItem = (props: Props) => { // 如果已经过期,显示"更新失败" if (nextUpdateDate.isBefore(now)) { - setNextUpdateTime(t("Last Update failed")); + setNextUpdateTime( + t("profiles.components.profileItem.status.lastUpdateFailed"), + ); } else { // 否则显示剩余时间 const diffMinutes = nextUpdateDate.diff(now, "minute"); if (diffMinutes < 60) { if (diffMinutes <= 0) { - setNextUpdateTime(`${t("Next Up")} <1m`); + setNextUpdateTime( + `${t("profiles.components.profileItem.status.nextUp")} <1m`, + ); } else { - setNextUpdateTime(`${t("Next Up")} ${diffMinutes}m`); + setNextUpdateTime( + `${t("profiles.components.profileItem.status.nextUp")} ${diffMinutes}m`, + ); } } else { const hours = Math.floor(diffMinutes / 60); const mins = diffMinutes % 60; - setNextUpdateTime(`${t("Next Up")} ${hours}h ${mins}m`); + setNextUpdateTime( + `${t("profiles.components.profileItem.status.nextUp")} ${hours}h ${mins}m`, + ); } } } else { console.log(`返回的下次更新时间为空`); - setNextUpdateTime(t("No schedule")); + setNextUpdateTime( + t("profiles.components.profileItem.status.noSchedule"), + ); } } catch (err) { console.error(`获取下次更新时间出错:`, err); - setNextUpdateTime(t("Unknown")); + setNextUpdateTime(t("profiles.components.profileItem.status.unknown")); } } else { console.log(`该配置未设置更新间隔或间隔为0`); - setNextUpdateTime(t("Auto update disabled")); + setNextUpdateTime( + t("profiles.components.profileItem.status.autoUpdateDisabled"), + ); } }); @@ -312,8 +325,8 @@ export const ProfileItem = (props: Props) => { setAnchorEl(null); try { await viewProfile(itemData.uid); - } catch (err: any) { - showNotice("error", err?.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -354,42 +367,95 @@ export const ProfileItem = (props: Props) => { } }); - const urlModeMenu = ( - hasHome ? [{ label: "Home", handler: onOpenHome, disabled: false }] : [] - ).concat([ - { label: "Select", handler: onForceSelect, disabled: false }, - { label: "Edit Info", handler: onEditInfo, disabled: false }, - { label: "Edit File", handler: onEditFile, disabled: false }, + type ContextMenuItem = { + label: string; + handler: () => void; + disabled: boolean; + }; + + const menuLabels: Record = { + home: "profiles.components.menu.home", + select: "profiles.components.menu.select", + editInfo: "profiles.components.menu.editInfo", + editFile: "profiles.components.menu.editFile", + editRules: "profiles.components.menu.editRules", + editProxies: "profiles.components.menu.editProxies", + editGroups: "profiles.components.menu.editGroups", + extendConfig: "profiles.components.menu.extendConfig", + extendScript: "profiles.components.menu.extendScript", + openFile: "profiles.components.menu.openFile", + update: "profiles.components.menu.update", + updateViaProxy: "profiles.components.menu.updateViaProxy", + delete: "shared.actions.delete", + } as const; + + const urlModeMenu: ContextMenuItem[] = [ + ...(hasHome + ? [ + { + label: menuLabels.home, + handler: onOpenHome, + disabled: false, + } satisfies ContextMenuItem, + ] + : []), { - label: "Edit Rules", + label: menuLabels.select, + handler: onForceSelect, + disabled: false, + }, + { + label: menuLabels.editInfo, + handler: onEditInfo, + disabled: false, + }, + { + label: menuLabels.editFile, + handler: onEditFile, + disabled: false, + }, + { + label: menuLabels.editRules, handler: onEditRules, disabled: !option?.rules, }, { - label: "Edit Proxies", + label: menuLabels.editProxies, handler: onEditProxies, disabled: !option?.proxies, }, { - label: "Edit Groups", + label: menuLabels.editGroups, handler: onEditGroups, disabled: !option?.groups, }, { - label: "Extend Config", + label: menuLabels.extendConfig, handler: onEditMerge, disabled: !option?.merge, }, { - label: "Extend Script", + label: menuLabels.extendScript, handler: onEditScript, disabled: !option?.script, }, - { label: "Open File", handler: onOpenFile, disabled: false }, - { label: "Update", handler: () => onUpdate(0), disabled: false }, - { label: "Update via proxy", handler: () => onUpdate(2), disabled: false }, { - label: "Delete", + label: menuLabels.openFile, + handler: onOpenFile, + disabled: false, + }, + { + label: menuLabels.update, + handler: () => onUpdate(0), + disabled: false, + }, + { + label: menuLabels.updateViaProxy, + handler: () => onUpdate(2), + disabled: false, + }, + { + label: menuLabels.delete, handler: () => { setAnchorEl(null); if (batchMode) { @@ -403,39 +469,55 @@ export const ProfileItem = (props: Props) => { }, disabled: false, }, - ]); - const fileModeMenu = [ - { label: "Select", handler: onForceSelect, disabled: false }, - { label: "Edit Info", handler: onEditInfo, disabled: false }, - { label: "Edit File", handler: onEditFile, disabled: false }, + ]; + const fileModeMenu: ContextMenuItem[] = [ { - label: "Edit Rules", + label: menuLabels.select, + handler: onForceSelect, + disabled: false, + }, + { + label: menuLabels.editInfo, + handler: onEditInfo, + disabled: false, + }, + { + label: menuLabels.editFile, + handler: onEditFile, + disabled: false, + }, + { + label: menuLabels.editRules, handler: onEditRules, disabled: !option?.rules, }, { - label: "Edit Proxies", + label: menuLabels.editProxies, handler: onEditProxies, disabled: !option?.proxies, }, { - label: "Edit Groups", + label: menuLabels.editGroups, handler: onEditGroups, disabled: !option?.groups, }, { - label: "Extend Config", + label: menuLabels.extendConfig, handler: onEditMerge, disabled: !option?.merge, }, { - label: "Extend Script", + label: menuLabels.extendScript, handler: onEditScript, disabled: !option?.script, }, - { label: "Open File", handler: onOpenFile, disabled: false }, { - label: "Delete", + label: menuLabels.openFile, + handler: onOpenFile, + disabled: false, + }, + { + label: menuLabels.delete, handler: () => { setAnchorEl(null); if (batchMode) { @@ -599,7 +681,7 @@ export const ProfileItem = (props: Props) => { {/* only if has url can it be updated */} {hasUrl && ( {
    ) : ( hasUrl && ( - + {from} ) @@ -657,8 +742,8 @@ export const ProfileItem = (props: Props) => { textAlign="right" title={ showNextUpdate - ? t("Click to show last update time") - : `${t("Update Time")}: ${parseExpire(updated)}\n${t("Click to show next update")}` + ? t("profiles.components.profileItem.tooltips.showLast") + : `${t("shared.labels.updateTime")}: ${parseExpire(updated)}\n${t("profiles.components.profileItem.tooltips.showNext")}` } sx={{ cursor: "pointer", @@ -686,14 +771,16 @@ export const ProfileItem = (props: Props) => { {/* the third line show extra info or last updated time */} {hasExtra ? ( - + {parseTraffic(upload + download)} / {parseTraffic(total)} - {expire} + {expire} ) : ( - {parseExpire(updated)} + + {parseExpire(updated)} + )} { (theme) => { return { color: - item.label === "Delete" + item.label === menuLabels.delete ? theme.palette.error.main : undefined, }; @@ -813,8 +900,8 @@ export const ProfileItem = (props: Props) => { )} setConfirmOpen(false)} onConfirm={() => { diff --git a/src/components/profile/profile-more.tsx b/src/components/profile/profile-more.tsx index 2ead4b94a..bcc7acd34 100644 --- a/src/components/profile/profile-more.tsx +++ b/src/components/profile/profile-more.tsx @@ -47,16 +47,26 @@ export const ProfileMore = (props: Props) => { setAnchorEl(null); try { await viewProfile(id); - } catch (err: any) { - showNotice("error", err?.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); const hasError = entries.some(([level]) => level === "exception"); + const globalTitles: Record = { + Merge: "profiles.components.more.global.merge", + Script: "profiles.components.more.global.script", + }; + + const chipLabels: Record = { + Merge: "profiles.components.more.chips.merge", + Script: "profiles.components.more.chips.script", + }; + const itemMenu = [ - { label: "Edit File", handler: onEditFile }, - { label: "Open File", handler: onOpenFile }, + { label: "profiles.components.menu.editFile", handler: onEditFile }, + { label: "profiles.components.menu.openFile", handler: onOpenFile }, ]; const boxStyle = { @@ -89,13 +99,13 @@ export const ProfileMore = (props: Props) => { variant="h6" component="h2" noWrap - title={t(`Global ${id}`)} + title={t(globalTitles[id])} > - {t(`Global ${id}`)} + {t(globalTitles[id])} { size="small" edge="start" color="error" - title={t("Script Console")} + title={t("profiles.modals.logViewer.title")} onClick={() => setLogOpen(true)} > @@ -122,7 +132,7 @@ export const ProfileMore = (props: Props) => { size="small" edge="start" color="inherit" - title={t("Script Console")} + title={t("profiles.modals.logViewer.title")} onClick={() => setLogOpen(true)} > @@ -170,7 +180,7 @@ export const ProfileMore = (props: Props) => { {fileOpen && ( { onChange(isActivating); }, 0); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } finally { setLoading(false); } @@ -220,10 +218,14 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { return ( ( - {t("Type")} - Remote Local @@ -247,7 +255,7 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { name="name" control={control} render={({ field }) => ( - + )} /> @@ -255,7 +263,11 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { name="desc" control={control} render={({ field }) => ( - + )} /> @@ -269,7 +281,7 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { {...text} {...field} multiline - label={t("Subscription URL")} + label={t("profiles.modals.profileForm.fields.subscriptionUrl")} /> )} /> @@ -296,12 +308,12 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { {...field} type="number" placeholder="60" - label={t("HTTP Request Timeout")} + label={t("profiles.modals.profileForm.fields.httpTimeout")} slotProps={{ input: { endAdornment: ( - {t("seconds")} + {t("shared.units.seconds")} ), }, @@ -321,11 +333,13 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { {...text} {...field} type="number" - label={t("Update Interval")} + label={t("profiles.modals.profileForm.fields.updateInterval")} slotProps={{ input: { endAdornment: ( - {t("mins")} + + {t("shared.units.minutes")} + ), }, }} @@ -350,7 +364,9 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { control={control} render={({ field }) => ( - {t("Use System Proxy")} + + {t("profiles.modals.profileForm.fields.useSystemProxy")} + )} @@ -361,7 +377,9 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { control={control} render={({ field }) => ( - {t("Use Clash Proxy")} + + {t("profiles.modals.profileForm.fields.useClashProxy")} + )} @@ -372,7 +390,9 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { control={control} render={({ field }) => ( - {t("Accept Invalid Certs (Danger)")} + + {t("profiles.modals.profileForm.fields.acceptInvalidCerts")} + )} @@ -383,7 +403,9 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) { control={control} render={({ field }) => ( - {t("Allow Auto Update")} + + {t("profiles.modals.profileForm.fields.allowAutoUpdate")} + )} diff --git a/src/components/profile/proxies-editor-viewer.tsx b/src/components/profile/proxies-editor-viewer.tsx index 9143ef8de..61811e49a 100644 --- a/src/components/profile/proxies-editor-viewer.tsx +++ b/src/components/profile/proxies-editor-viewer.tsx @@ -163,11 +163,11 @@ export const ProxiesEditorViewer = (props: Props) => { proxies.push(proxy); names.push(proxy.name); } - } catch (err: any) { + } catch (err) { console.warn( "[ProxiesEditorViewer] parseUri failed for line:", uri, - err?.message || err, + err, ); // 不阻塞主流程 } @@ -263,11 +263,11 @@ export const ProxiesEditorViewer = (props: Props) => { const handleSave = useLockFn(async () => { try { await saveProfileFile(property, currData); - showNotice("success", t("Saved Successfully")); + showNotice.success("shared.feedback.notifications.saved"); onSave?.(prevData, currData); onClose(); - } catch (err: any) { - showNotice("error", err.toString()); + } catch (err) { + showNotice.error(err); } }); @@ -276,7 +276,7 @@ export const ProxiesEditorViewer = (props: Props) => { { - {t("Edit Proxies")} + {t("profiles.modals.proxiesEditor.title")} @@ -312,7 +314,9 @@ export const ProxiesEditorViewer = (props: Props) => { { }); }} > - {t("Prepend Proxy")} + {t("profiles.modals.proxiesEditor.actions.prepend")} @@ -346,7 +350,7 @@ export const ProxiesEditorViewer = (props: Props) => { }); }} > - {t("Append Proxy")} + {t("profiles.modals.proxiesEditor.actions.append")} @@ -497,11 +501,11 @@ export const ProxiesEditorViewer = (props: Props) => { diff --git a/src/components/profile/rules-editor-viewer.tsx b/src/components/profile/rules-editor-viewer.tsx index 585d08c4e..10524e977 100644 --- a/src/components/profile/rules-editor-viewer.tsx +++ b/src/components/profile/rules-editor-viewer.tsx @@ -240,8 +240,24 @@ const rules: { }, ]; +const RULE_TYPE_LABEL_KEYS: Record = Object.fromEntries( + rules.map((rule) => [ + rule.name, + `rules.modals.editor.ruleTypes.${rule.name}`, + ]), +); + const builtinProxyPolicies = ["DIRECT", "REJECT", "REJECT-DROP", "PASS"]; +const PROXY_POLICY_LABEL_KEYS: Record = + builtinProxyPolicies.reduce( + (acc, policy) => { + acc[policy] = `proxy.policies.${policy}`; + return acc; + }, + {} as Record, + ); + export const RulesEditorViewer = (props: Props) => { const { groupsUid, mergeUid, profileUid, property, open, onClose, onSave } = props; @@ -350,8 +366,8 @@ export const RulesEditorViewer = (props: Props) => { { forceQuotes: true }, ), ); - } catch (e: any) { - showNotice("error", e?.message || e?.toString() || "YAML dump error"); + } catch (error) { + showNotice.error(error ?? "YAML dump error"); } }; let idleId: number | undefined; @@ -462,10 +478,12 @@ export const RulesEditorViewer = (props: Props) => { const validateRule = () => { if ((ruleType.required ?? true) && !ruleContent) { - throw new Error(t("Rule Condition Required")); + throw new Error( + t("rules.modals.editor.form.validation.conditionRequired"), + ); } if (ruleType.validator && !ruleType.validator(ruleContent)) { - throw new Error(t("Invalid Rule")); + throw new Error(t("rules.modals.editor.form.validation.invalidRule")); } const condition = (ruleType.required ?? true) ? ruleContent : ""; @@ -477,11 +495,11 @@ export const RulesEditorViewer = (props: Props) => { const handleSave = useLockFn(async () => { try { await saveProfileFile(property, currData); - showNotice("success", t("Saved Successfully")); + showNotice.success("shared.feedback.notifications.saved"); onSave?.(prevData, currData); onClose(); } catch (err: any) { - showNotice("error", err.toString()); + showNotice.error(err); } }); @@ -490,7 +508,7 @@ export const RulesEditorViewer = (props: Props) => { { - {t("Edit Rules")} + {t("rules.modals.editor.title")} @@ -518,26 +538,37 @@ export const RulesEditorViewer = (props: Props) => { }} > - + } options={rules} value={ruleType} - getOptionLabel={(option) => option.name} - renderOption={(props, option) => ( -
  • - {option.name} -
  • - )} + getOptionLabel={(option) => + t(RULE_TYPE_LABEL_KEYS[option.name] ?? option.name) + } + renderOption={(props, option) => { + const label = t( + RULE_TYPE_LABEL_KEYS[option.name] ?? option.name, + ); + return ( +
  • + {label} +
  • + ); + }} onChange={(_, value) => value && setRuleType(value)} />
    - + {ruleType.name === "RULE-SET" && ( { )} - + } options={proxyPolicyList} value={proxyPolicy} - renderOption={(props, option) => ( -
  • - {option} -
  • - )} + getOptionLabel={(option) => + t(PROXY_POLICY_LABEL_KEYS[option] ?? option) + } + renderOption={(props, option) => { + const label = t(PROXY_POLICY_LABEL_KEYS[option] ?? option); + return ( +
  • + {label} +
  • + ); + }} onChange={(_, value) => value && setProxyPolicy(value)} />
    {ruleType.noResolve && ( - + setNoResolve(!noResolve)} @@ -609,11 +650,11 @@ export const RulesEditorViewer = (props: Props) => { if (prependSeq.includes(raw)) return; setPrependSeq([raw, ...prependSeq]); } catch (err: any) { - showNotice("error", err.message || err.toString()); + showNotice.error(err); } }} > - {t("Prepend Rule")} + {t("rules.modals.editor.form.actions.prependRule")} @@ -627,11 +668,11 @@ export const RulesEditorViewer = (props: Props) => { if (appendSeq.includes(raw)) return; setAppendSeq([...appendSeq, raw]); } catch (err: any) { - showNotice("error", err.message || err.toString()); + showNotice.error(err); } }} > - {t("Append Rule")} + {t("rules.modals.editor.form.actions.appendRule")} @@ -776,11 +817,11 @@ export const RulesEditorViewer = (props: Props) => { diff --git a/src/components/proxy/provider-button.tsx b/src/components/proxy/provider-button.tsx index e22b856e0..435516386 100644 --- a/src/components/proxy/provider-button.tsx +++ b/src/components/proxy/provider-button.tsx @@ -66,12 +66,17 @@ export const ProviderButton = () => { await refreshProxy(); await refreshProxyProviders(); - showNotice("success", `${name} 更新成功`); - } catch (err: any) { - showNotice( - "error", - `${name} 更新失败: ${err?.message || err.toString()}`, + showNotice.success( + "proxies.feedback.notifications.provider.updateSuccess", + { + name, + }, ); + } catch (err) { + showNotice.error("proxies.feedback.notifications.provider.updateFailed", { + name, + message: String(err), + }); } finally { // 清除更新状态 setUpdating((prev) => ({ ...prev, [name]: false })); @@ -84,7 +89,7 @@ export const ProviderButton = () => { // 获取所有provider的名称 const allProviders = Object.keys(proxyProviders || {}); if (allProviders.length === 0) { - showNotice("info", "没有可更新的代理提供者"); + showNotice.info("proxies.feedback.notifications.provider.none"); return; } @@ -114,9 +119,11 @@ export const ProviderButton = () => { await refreshProxy(); await refreshProxyProviders(); - showNotice("success", "全部代理提供者更新成功"); - } catch (err: any) { - showNotice("error", `更新失败: ${err?.message || err.toString()}`); + showNotice.success("proxies.feedback.notifications.provider.allUpdated"); + } catch (err) { + showNotice.error("proxies.feedback.notifications.provider.genericError", { + message: String(err), + }); } finally { // 清除所有更新状态 setUpdating({}); @@ -138,7 +145,7 @@ export const ProviderButton = () => { onClick={() => setOpen(true)} sx={{ mr: 1 }} > - {t("Proxy Provider")} + {t("proxies.page.provider.title")} @@ -148,14 +155,17 @@ export const ProviderButton = () => { justifyContent="space-between" alignItems="center" > - {t("Proxy Provider")} + + {t("proxies.page.provider.title")} + @@ -246,7 +256,7 @@ export const ProviderButton = () => { color="text.secondary" noWrap > - {t("Update At")}: + {t("shared.labels.updateAt")}: {time.fromNow()}
    @@ -264,11 +274,17 @@ export const ProviderButton = () => { justifyContent: "space-between", }} > - + {parseTraffic(upload + download)} /{" "} {parseTraffic(total)} - + {parseExpire(expire)} @@ -313,7 +329,8 @@ export const ProviderButton = () => { "100%": { transform: "rotate(360deg)" }, }, }} - title={t("Update Provider") as string} + title={t("proxies.page.provider.actions.update")} + aria-label={t("proxies.page.provider.actions.update")} >
    @@ -326,7 +343,7 @@ export const ProviderButton = () => { diff --git a/src/components/proxy/proxy-chain.tsx b/src/components/proxy/proxy-chain.tsx index ea19e9318..99bf10435 100644 --- a/src/components/proxy/proxy-chain.tsx +++ b/src/components/proxy/proxy-chain.tsx @@ -156,7 +156,11 @@ const SortableItem = ({ proxy, index, onRemove }: SortableItemProps) => { {proxy.delay !== undefined && ( 0 ? `${proxy.delay}ms` : t("timeout") || "超时"} + label={ + proxy.delay > 0 + ? `${proxy.delay}ms` + : t("shared.labels.timeout") || "超时" + } size="small" color={ proxy.delay > 0 && proxy.delay < 200 @@ -299,7 +303,7 @@ export const ProxyChain = ({ // onUpdateChain([]); } catch (error) { console.error("Failed to disconnect from proxy chain:", error); - alert(t("Failed to disconnect from proxy chain") || "断开链式代理失败"); + alert(t("proxies.page.chain.disconnectFailed") || "断开链式代理失败"); } finally { setIsConnecting(false); } @@ -307,9 +311,7 @@ export const ProxyChain = ({ } if (proxyChain.length < 2) { - alert( - t("Chain proxy requires at least 2 nodes") || "链式代理至少需要2个节点", - ); + alert(t("proxies.page.chain.minimumNodes") || "链式代理至少需要2个节点"); return; } @@ -341,7 +343,7 @@ export const ProxyChain = ({ console.log("Successfully connected to proxy chain"); } catch (error) { console.error("Failed to connect to proxy chain:", error); - alert(t("Failed to connect to proxy chain") || "连接链式代理失败"); + alert(t("proxies.page.chain.connectFailed") || "连接链式代理失败"); } finally { setIsConnecting(false); } @@ -471,7 +473,7 @@ export const ProxyChain = ({ mb: 2, }} > - {t("Chain Proxy Config")} + {t("proxies.page.chain.header")} {proxyChain.length > 0 && ( @@ -507,16 +511,16 @@ export const ProxyChain = ({ }} title={ proxyChain.length < 2 - ? t("Chain proxy requires at least 2 nodes") || + ? t("proxies.page.chain.minimumNodes") || "链式代理至少需要2个节点" : undefined } > {isConnecting - ? t("Connecting...") || "连接中..." + ? t("proxies.page.actions.connecting") || "连接中..." : isConnected - ? t("Disconnect") || "断开" - : t("Connect") || "连接"} + ? t("proxies.page.actions.disconnect") || "断开" + : t("proxies.page.actions.connect") || "连接"} @@ -526,10 +530,9 @@ export const ProxyChain = ({ sx={{ mb: 2 }} > {proxyChain.length === 1 - ? t( - "Chain proxy requires at least 2 nodes. Please add one more node.", - ) || "链式代理至少需要2个节点,请再添加一个节点。" - : t("Click nodes in order to add to proxy chain") || + ? t("proxies.page.chain.minimumNodesHint") || + "链式代理至少需要2个节点,请再添加一个节点。" + : t("proxies.page.chain.instruction") || "按顺序点击节点添加到代理链中"} @@ -544,7 +547,7 @@ export const ProxyChain = ({ color: theme.palette.text.secondary, }} > - {t("No proxy chain configured")} + {t("proxies.page.chain.empty")} ) : ( { setProxyChain((prev) => { // 检查是否已经存在相同名称的代理,防止重复添加 if (prev.some((item) => item.name === proxy.name)) { - const warningMessage = t("Proxy node already exists in chain"); + const warningMessage = t("proxies.page.chain.duplicateNode"); setDuplicateWarning({ open: true, message: warningMessage, @@ -372,7 +372,7 @@ export const ProxyGroups = (props: Props) => { }, [renderList]); if (mode === "direct") { - return ; + return ; } if (isChainMode) { @@ -403,7 +403,7 @@ export const ProxyGroups = (props: Props) => { variant="h6" sx={{ fontWeight: 600, fontSize: "16px" }} > - {t("Proxy Rules")} + {t("proxies.page.rules.title")}
    {currentGroup && ( { variant="body2" sx={{ mr: 0.5, fontSize: "12px" }} > - {t("Select Rules")} + {t("proxies.page.rules.select")}
    diff --git a/src/components/proxy/proxy-head.tsx b/src/components/proxy/proxy-head.tsx index 5ba089582..56a034bd0 100644 --- a/src/components/proxy/proxy-head.tsx +++ b/src/components/proxy/proxy-head.tsx @@ -67,7 +67,7 @@ export const ProxyHead = ({ @@ -76,7 +76,7 @@ export const ProxyHead = ({ { console.log(`[ProxyHead] 点击延迟测试按钮,组: ${groupName}`); // Remind the user that it is custom test url @@ -94,9 +94,11 @@ export const ProxyHead = ({ size="small" color="inherit" title={ - [t("Sort by default"), t("Sort by delay"), t("Sort by name")][ - sortType - ] + [ + t("proxies.page.tooltips.sortDefault"), + t("proxies.page.tooltips.sortDelay"), + t("proxies.page.tooltips.sortName"), + ][sortType] } onClick={() => onHeadState({ sortType: ((sortType + 1) % 3) as ProxySortType }) @@ -110,7 +112,7 @@ export const ProxyHead = ({ onHeadState({ textState: textState === "url" ? null : "url" }) } @@ -125,7 +127,11 @@ export const ProxyHead = ({ onHeadState({ showType: !showType })} > {showType ? : } @@ -134,7 +140,7 @@ export const ProxyHead = ({ onHeadState({ textState: textState === "filter" ? null : "filter" }) } @@ -154,7 +160,7 @@ export const ProxyHead = ({ value={filterText} size="small" variant="outlined" - placeholder={t("Filter conditions")} + placeholder={t("shared.placeholders.filter")} onChange={(e) => onHeadState({ filterText: e.target.value })} sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }} /> @@ -169,7 +175,7 @@ export const ProxyHead = ({ value={testUrl} size="small" variant="outlined" - placeholder={t("Delay check URL")} + placeholder={t("proxies.page.placeholders.delayCheckUrl")} onChange={(e) => onHeadState({ testUrl: e.target.value })} sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }} /> diff --git a/src/components/proxy/proxy-item-mini.tsx b/src/components/proxy/proxy-item-mini.tsx index a6e6e6601..1bbb30f16 100644 --- a/src/components/proxy/proxy-item-mini.tsx +++ b/src/components/proxy/proxy-item-mini.tsx @@ -271,7 +271,9 @@ export const ProxyItemMini = (props: Props) => { 📌 diff --git a/src/components/proxy/proxy-render.tsx b/src/components/proxy/proxy-render.tsx index bb9919f59..fe527a3eb 100644 --- a/src/components/proxy/proxy-render.tsx +++ b/src/components/proxy/proxy-render.tsx @@ -160,7 +160,7 @@ export const ProxyRender = (props: RenderProps) => { }} /> - + { await refreshRules(); await refreshRuleProviders(); - showNotice("success", `${name} 更新成功`); - } catch (err: any) { - showNotice( - "error", - `${name} 更新失败: ${err?.message || err.toString()}`, + showNotice.success( + "rules.feedback.notifications.provider.updateSuccess", + { + name, + }, ); + } catch (err) { + showNotice.error("rules.feedback.notifications.provider.updateFailed", { + name, + message: String(err), + }); } finally { // 清除更新状态 setUpdating((prev) => ({ ...prev, [name]: false })); @@ -76,7 +81,7 @@ export const ProviderButton = () => { // 获取所有provider的名称 const allProviders = Object.keys(ruleProviders || {}); if (allProviders.length === 0) { - showNotice("info", "没有可更新的规则提供者"); + showNotice.info("rules.feedback.notifications.provider.none"); return; } @@ -106,9 +111,11 @@ export const ProviderButton = () => { await refreshRules(); await refreshRuleProviders(); - showNotice("success", "全部规则提供者更新成功"); - } catch (err: any) { - showNotice("error", `更新失败: ${err?.message || err.toString()}`); + showNotice.success("rules.feedback.notifications.provider.allUpdated"); + } catch (err) { + showNotice.error("rules.feedback.notifications.provider.genericError", { + message: String(err), + }); } finally { // 清除所有更新状态 setUpdating({}); @@ -129,7 +136,7 @@ export const ProviderButton = () => { startIcon={} onClick={() => setOpen(true)} > - {t("Rule Provider")} + {t("rules.page.provider.trigger")} @@ -139,13 +146,15 @@ export const ProviderButton = () => { justifyContent="space-between" alignItems="center" > - {t("Rule Providers")} + + {t("rules.page.provider.dialogTitle")} + @@ -216,7 +225,7 @@ export const ProviderButton = () => { color="text.secondary" noWrap > - {t("Update At")}: + {t("shared.labels.updateAt")}: {time.fromNow()} @@ -246,6 +255,7 @@ export const ProviderButton = () => { color="primary" onClick={() => updateProvider(key)} disabled={isUpdating} + aria-label={t("rules.page.provider.actions.update")} sx={{ animation: isUpdating ? "spin 1s linear infinite" @@ -255,7 +265,7 @@ export const ProviderButton = () => { "100%": { transform: "rotate(360deg)" }, }, }} - title={t("Update Provider") as string} + title={t("rules.page.provider.actions.update")} > @@ -268,7 +278,7 @@ export const ProviderButton = () => { diff --git a/src/components/setting/mods/backup-config-viewer.tsx b/src/components/setting/mods/backup-config-viewer.tsx index 443cf961e..b1323db6f 100644 --- a/src/components/setting/mods/backup-config-viewer.tsx +++ b/src/components/setting/mods/backup-config-viewer.tsx @@ -84,22 +84,22 @@ export const BackupConfigViewer = memo( if (!url) { urlRef.current?.focus(); - showNotice("error", t("WebDAV URL Required")); - throw new Error(t("WebDAV URL Required")); + showNotice.error("settings.modals.backup.messages.webdavUrlRequired"); + throw new Error(t("settings.modals.backup.messages.webdavUrlRequired")); } else if (!isValidUrl(url)) { urlRef.current?.focus(); - showNotice("error", t("Invalid WebDAV URL")); - throw new Error(t("Invalid WebDAV URL")); + showNotice.error("settings.modals.backup.messages.invalidWebdavUrl"); + throw new Error(t("settings.modals.backup.messages.invalidWebdavUrl")); } if (!username) { usernameRef.current?.focus(); - showNotice("error", t("WebDAV URL Required")); - throw new Error(t("Username Required")); + showNotice.error("settings.modals.backup.messages.usernameRequired"); + throw new Error(t("settings.modals.backup.messages.usernameRequired")); } if (!password) { passwordRef.current?.focus(); - showNotice("error", t("WebDAV URL Required")); - throw new Error(t("Password Required")); + showNotice.error("settings.modals.backup.messages.passwordRequired"); + throw new Error(t("settings.modals.backup.messages.passwordRequired")); } }; @@ -112,11 +112,17 @@ export const BackupConfigViewer = memo( data.username.trim(), data.password, ).then(() => { - showNotice("success", t("WebDAV Config Saved")); + showNotice.success( + "settings.modals.backup.messages.webdavConfigSaved", + ); onSaveSuccess(); }); } catch (error) { - showNotice("error", t("WebDAV Config Save Failed", { error }), 3000); + showNotice.error( + "settings.modals.backup.messages.webdavConfigSaveFailed", + { error }, + 3000, + ); } finally { setLoading(false); } @@ -127,11 +133,13 @@ export const BackupConfigViewer = memo( try { setLoading(true); await createWebdavBackup().then(async () => { - showNotice("success", t("Backup Created")); + showNotice.success("settings.modals.backup.messages.backupCreated"); await onBackupSuccess(); }); } catch (error) { - showNotice("error", t("Backup Failed", { error })); + showNotice.error("settings.modals.backup.messages.backupFailed", { + error, + }); } finally { setLoading(false); } @@ -145,7 +153,7 @@ export const BackupConfigViewer = memo( - {t("Save")} + {t("shared.actions.save")} ) : ( <> @@ -225,7 +233,7 @@ export const BackupConfigViewer = memo( type="button" size="large" > - {t("Backup")} + {t("settings.modals.backup.actions.backup")} )} diff --git a/src/components/setting/mods/backup-table-viewer.tsx b/src/components/setting/mods/backup-table-viewer.tsx index 4ea6828f5..13c9f9824 100644 --- a/src/components/setting/mods/backup-table-viewer.tsx +++ b/src/components/setting/mods/backup-table-viewer.tsx @@ -75,7 +75,7 @@ export const BackupTableViewer = memo( const handleRestore = useLockFn(async (filename: string) => { await onRestore(filename).then(() => { - showNotice("success", t("Restore Success, App will restart in 1s")); + showNotice.success("settings.modals.backup.messages.restoreSuccess"); }); await restartApp(); }); @@ -92,10 +92,14 @@ export const BackupTableViewer = memo( return; } await onExport(filename, savePath); - showNotice("success", t("Local Backup Exported")); + showNotice.success( + "settings.modals.backup.messages.localBackupExported", + ); } catch (error) { console.error(error); - showNotice("error", t("Local Backup Export Failed")); + showNotice.error( + "settings.modals.backup.messages.localBackupExportFailed", + ); } }); @@ -104,9 +108,15 @@ export const BackupTableViewer = memo( - {t("Filename")} - {t("Backup Time")} - {t("Actions")} + + {t("settings.modals.backup.table.filename")} + + + {t("settings.modals.backup.table.backupTime")} + + + {t("settings.modals.backup.table.actions")} + @@ -140,9 +150,13 @@ export const BackupTableViewer = memo( <> { e.preventDefault(); await handleExport(file.filename); @@ -159,13 +173,17 @@ export const BackupTableViewer = memo( )} { e.preventDefault(); const confirmed = await confirmAsync( - t("Confirm to delete this backup file?"), + t( + "settings.modals.backup.messages.confirmDelete", + ), ); if (confirmed) { await handleDelete(file.filename); @@ -181,14 +199,20 @@ export const BackupTableViewer = memo( /> { e.preventDefault(); const confirmed = await confirmAsync( - t("Confirm to restore this backup file?"), + t( + "settings.modals.backup.messages.confirmRestore", + ), ); if (confirmed) { await handleRestore(file.filename); @@ -219,7 +243,7 @@ export const BackupTableViewer = memo( color="textSecondary" align="center" > - {t("No Backups")} + {t("settings.modals.backup.table.noBackups")} @@ -234,7 +258,7 @@ export const BackupTableViewer = memo( rowsPerPage={DEFAULT_ROWS_PER_PAGE} page={page} onPageChange={onPageChange} - labelRowsPerPage={t("Rows per page")} + labelRowsPerPage={t("settings.modals.backup.table.rowsPerPage")} /> ); diff --git a/src/components/setting/mods/backup-viewer.tsx b/src/components/setting/mods/backup-viewer.tsx index b3e532b0c..3a1c1ecca 100644 --- a/src/components/setting/mods/backup-viewer.tsx +++ b/src/components/setting/mods/backup-viewer.tsx @@ -127,7 +127,6 @@ export function BackupViewer({ ref }: { ref?: Ref }) { setBackupFiles([]); setTotal(0); console.error(error); - // Notice.error(t("Failed to fetch backup files")); } finally { setIsLoading(false); } @@ -247,7 +246,7 @@ export function BackupViewer({ ref }: { ref?: Ref }) { return ( }) { - - + + {source === "local" ? ( }) { backgroundColor: (theme) => theme.palette.background.paper, }} > - {t("Close")} + {t("shared.actions.close")} , dialogPaper, diff --git a/src/components/setting/mods/clash-core-viewer.tsx b/src/components/setting/mods/clash-core-viewer.tsx index be951de6c..614617788 100644 --- a/src/components/setting/mods/clash-core-viewer.tsx +++ b/src/components/setting/mods/clash-core-viewer.tsx @@ -24,8 +24,16 @@ import { changeClashCore, restartCore } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; const VALID_CORE = [ - { name: "Mihomo", core: "verge-mihomo", chip: "Release Version" }, - { name: "Mihomo Alpha", core: "verge-mihomo-alpha", chip: "Alpha Version" }, + { + name: "Mihomo", + core: "verge-mihomo", + chipKey: "settings.modals.clashCore.variants.release", + }, + { + name: "Mihomo Alpha", + core: "verge-mihomo-alpha", + chipKey: "settings.modals.clashCore.variants.alpha", + }, ]; export function ClashCoreViewer({ ref }: { ref?: Ref }) { @@ -54,7 +62,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { const errorMsg = await changeClashCore(core); if (errorMsg) { - showNotice("error", errorMsg); + showNotice.error(errorMsg); setChangingCore(null); return; } @@ -65,9 +73,9 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { mutate("getVersion"); setChangingCore(null); }, 500); - } catch (err: any) { + } catch (err) { setChangingCore(null); - showNotice("error", err.message || err.toString()); + showNotice.error(err); } }); @@ -75,11 +83,13 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { try { setRestarting(true); await restartCore(); - showNotice("success", t(`Clash Core Restarted`)); + showNotice.success( + t("settings.feedback.notifications.clash.restartSuccess"), + ); setRestarting(false); - } catch (err: any) { + } catch (err) { setRestarting(false); - showNotice("error", err.message || err.toString()); + showNotice.error(err); } }); @@ -88,14 +98,16 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { setUpgrading(true); await upgradeCore(); setUpgrading(false); - showNotice("success", t(`Core Version Updated`)); + showNotice.success( + t("settings.feedback.notifications.clash.versionUpdated"), + ); } catch (err: any) { setUpgrading(false); - const errMsg = err.response?.data?.message || err.toString(); + const errMsg = err?.response?.data?.message ?? String(err); const showMsg = errMsg.includes("already using latest version") - ? "Already Using Latest Core Version" + ? t("settings.feedback.notifications.clash.alreadyLatestVersion") : errMsg; - showNotice("error", t(showMsg)); + showNotice.info(showMsg); } }); @@ -104,7 +116,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { open={open} title={ - {t("Clash Core")} + {t("settings.sections.clash.form.fields.clashCore")} }) { sx={{ marginRight: "8px" }} onClick={onUpgrade} > - {t("Upgrade")} + {t("shared.actions.upgrade")} }) { disabled={upgrading} onClick={onRestart} > - {t("Restart")} + {t("shared.actions.restart")} @@ -141,7 +153,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { marginTop: "-8px", }} disableOk - cancelBtn={t("Close")} + cancelBtn={t("shared.actions.close")} onClose={() => setOpen(false)} onCancel={() => setOpen(false)} > @@ -157,7 +169,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref }) { {changingCore === each.core ? ( ) : ( - + )} ))} diff --git a/src/components/setting/mods/clash-port-viewer.tsx b/src/components/setting/mods/clash-port-viewer.tsx index 6b9d9c8b0..b0ed403fa 100644 --- a/src/components/setting/mods/clash-port-viewer.tsx +++ b/src/components/setting/mods/clash-port-viewer.tsx @@ -69,11 +69,13 @@ export const ClashPortViewer = forwardRef((_, ref) => { manual: true, onSuccess: () => { setOpen(false); - showNotice("success", t("Port settings saved")); + showNotice.success("settings.modals.clashPort.messages.saved"); }, - onError: (e) => { - showNotice("error", e.message || t("Failed to save port settings")); - // showNotice("error", t("Failed to save port settings")); + onError: (error) => { + showNotice.error( + "settings.modals.clashPort.messages.saveFailed", + error, + ); }, }, ); @@ -150,7 +152,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { return ( ((_, ref) => { loading ? ( - {t("Saving...")} + {t("shared.statuses.saving")} ) : ( - t("Save") + t("shared.actions.save") ) } - cancelBtn={t("Cancel")} + cancelBtn={t("shared.actions.cancel")} onClose={() => setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} @@ -172,7 +174,7 @@ export const ClashPortViewer = forwardRef((_, ref) => {
    @@ -188,7 +190,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { setMixedPort(generateRandomPort())} - title={t("Random Port")} + title={t("settings.modals.clashPort.actions.random")} sx={{ mr: 0.5 }} > @@ -204,7 +206,7 @@ export const ClashPortViewer = forwardRef((_, ref) => {
    @@ -221,7 +223,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { setSocksPort(generateRandomPort())} - title={t("Random Port")} + title={t("settings.modals.clashPort.actions.random")} disabled={!socksEnabled} sx={{ mr: 0.5 }} > @@ -238,7 +240,7 @@ export const ClashPortViewer = forwardRef((_, ref) => {
    @@ -255,7 +257,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { setHttpPort(generateRandomPort())} - title={t("Random Port")} + title={t("settings.modals.clashPort.actions.random")} disabled={!httpEnabled} sx={{ mr: 0.5 }} > @@ -273,7 +275,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { {OS !== "windows" && (
    @@ -290,7 +292,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { setRedirPort(generateRandomPort())} - title={t("Random Port")} + title={t("settings.modals.clashPort.actions.random")} disabled={!redirEnabled} sx={{ mr: 0.5 }} > @@ -309,7 +311,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { {OS === "linux" && (
    @@ -326,7 +328,7 @@ export const ClashPortViewer = forwardRef((_, ref) => { setTproxyPort(generateRandomPort())} - title={t("Random Port")} + title={t("settings.modals.clashPort.actions.random")} disabled={!tproxyEnabled} sx={{ mr: 0.5 }} > diff --git a/src/components/setting/mods/config-viewer.tsx b/src/components/setting/mods/config-viewer.tsx index 26609caa0..564a56dcc 100644 --- a/src/components/setting/mods/config-viewer.tsx +++ b/src/components/setting/mods/config-viewer.tsx @@ -27,8 +27,8 @@ export const ConfigViewer = forwardRef((_, ref) => { open={true} title={ - {t("Runtime Config")} - + {t("settings.components.verge.advanced.fields.runtimeConfig")} + } initialData={Promise.resolve(runtimeConfig)} diff --git a/src/components/setting/mods/controller-viewer.tsx b/src/components/setting/mods/controller-viewer.tsx index 105fb34e9..7b1067591 100644 --- a/src/components/setting/mods/controller-viewer.tsx +++ b/src/components/setting/mods/controller-viewer.tsx @@ -56,12 +56,16 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { // 如果启用了外部控制器,则保存控制器地址和密钥 if (enableController) { if (!controller.trim()) { - showNotice("error", t("Controller address cannot be empty")); + showNotice.error( + "settings.sections.externalController.messages.addressRequired", + ); return; } if (!secret.trim()) { - showNotice("error", t("Secret cannot be empty")); + showNotice.error( + "settings.sections.externalController.messages.secretRequired", + ); return; } @@ -71,12 +75,12 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { await patchInfo({ "external-controller": "" }); } - showNotice("success", t("Configuration saved successfully")); + showNotice.success("shared.feedback.notifications.common.saveSuccess"); setOpen(false); - } catch (err: any) { - showNotice( - "error", - err.message || t("Failed to save configuration"), + } catch (err) { + showNotice.error( + "shared.feedback.notifications.common.saveFailed", + err, 4000, ); } finally { @@ -93,7 +97,9 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { setTimeout(() => setCopySuccess(null)); } catch (err) { console.warn("[ControllerViewer] copy to clipboard failed:", err); - showNotice("error", t("Failed to copy")); + showNotice.error( + "settings.sections.externalController.messages.copyFailed", + ); } }, ); @@ -101,19 +107,19 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { return ( - {t("Saving...")} + {t("shared.statuses.saving")} ) : ( - t("Save") + t("shared.actions.save") ) } - cancelBtn={t("Cancel")} + cancelBtn={t("shared.actions.cancel")} onClose={() => setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} @@ -126,7 +132,9 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { justifyContent: "space-between", }} > - + }) { justifyContent: "space-between", }} > - + }) { pointerEvents: enableController ? "auto" : "none", }} value={controller} - placeholder="Required" + placeholder={t( + "settings.sections.externalController.placeholders.address", + )} onChange={(e) => setController(e.target.value)} disabled={isSaving || !enableController} /> - + handleCopyToClipboard(controller, "controller")} @@ -176,7 +190,9 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { justifyContent: "space-between", }} > - + }) { pointerEvents: enableController ? "auto" : "none", }} value={secret} - placeholder={t("Recommended")} + placeholder={t( + "settings.sections.externalController.placeholders.secret", + )} onChange={(e) => setSecret(e.target.value)} disabled={isSaving || !enableController} /> - + handleCopyToClipboard(secret, "secret")} @@ -211,8 +231,10 @@ export function ControllerViewer({ ref }: { ref?: Ref }) { > {copySuccess === "controller" - ? t("Controller address copied to clipboard") - : t("Secret copied to clipboard")} + ? t( + "settings.sections.externalController.messages.controllerCopied", + ) + : t("settings.sections.externalController.messages.secretCopied")} diff --git a/src/components/setting/mods/dns-viewer.tsx b/src/components/setting/mods/dns-viewer.tsx index 9054ec2ff..41a227b4a 100644 --- a/src/components/setting/mods/dns-viewer.tsx +++ b/src/components/setting/mods/dns-viewer.tsx @@ -424,9 +424,9 @@ export function DnsViewer({ ref }: { ref?: Ref }) { skipYamlSyncRef.current = true; updateValuesFromConfig(parsedYaml); } catch { - showNotice("error", t("Invalid YAML format")); + showNotice.error("settings.modals.dns.errors.invalidYaml"); } - }, [yamlContent, t, updateValuesFromConfig]); + }, [yamlContent, updateValuesFromConfig]); useEffect(() => { if (skipYamlSyncRef.current) { @@ -509,7 +509,7 @@ export function DnsViewer({ ref }: { ref?: Ref }) { // 使用YAML编辑器的值 const parsedConfig = yaml.load(yamlContent); if (typeof parsedConfig !== "object" || parsedConfig === null) { - throw new Error(t("Invalid configuration")); + throw new Error(t("settings.modals.dns.errors.invalid")); } config = parsedConfig as Record; } @@ -547,9 +547,9 @@ export function DnsViewer({ ref }: { ref?: Ref }) { } } - showNotice( - "error", - t("DNS configuration error") + ": " + cleanErrorMsg, + showNotice.error( + "settings.modals.dns.messages.configError", + cleanErrorMsg, ); return; } @@ -561,9 +561,9 @@ export function DnsViewer({ ref }: { ref?: Ref }) { } setOpen(false); - showNotice("success", t("DNS settings saved")); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + showNotice.success("settings.modals.dns.messages.saved"); + } catch (err) { + showNotice.error(err); } }); @@ -613,7 +613,7 @@ export function DnsViewer({ ref }: { ref?: Ref }) { open={open} title={ - {t("DNS Overwrite")} + {t("settings.modals.dns.dialog.title")} @@ -643,8 +645,8 @@ export function DnsViewer({ ref }: { ref?: Ref }) { ? {} : { padding: "0 24px", display: "flex", flexDirection: "column" }), }} - okBtn={t("Save")} - cancelBtn={t("Cancel")} + okBtn={t("shared.actions.save")} + cancelBtn={t("shared.actions.cancel")} onClose={() => setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} @@ -655,7 +657,7 @@ export function DnsViewer({ ref }: { ref?: Ref }) { color="warning.main" sx={{ mb: 2, mt: 0, fontStyle: "italic" }} > - {t("DNS Settings Warning")} + {t("settings.modals.dns.dialog.warning")} {visualization ? ( @@ -664,11 +666,11 @@ export function DnsViewer({ ref }: { ref?: Ref }) { variant="subtitle1" sx={{ mt: 1, mb: 1, fontWeight: "bold" }} > - {t("DNS Settings")} + {t("settings.modals.dns.sections.general")} - + }) { - + }) { - + }) { }) { }) { }) { }) { }) { }) { }) { }) { }) { }) { }) { }) { }) { variant="subtitle2" sx={{ mt: 2, mb: 1, fontWeight: "bold" }} > - {t("Fallback Filter Settings")} + {t("settings.modals.dns.sections.fallbackFilter")} }) { - + }) { }) { }) { variant="subtitle1" sx={{ mt: 3, mb: 0, fontWeight: "bold" }} > - {t("Hosts Settings")} + {t("settings.modals.dns.sections.hosts")} ( manual: true, onSuccess: () => { setOpen(false); - showNotice("success", t("Configuration saved successfully")); + showNotice.success( + "shared.feedback.notifications.common.saveSuccess", + ); }, onError: () => { - showNotice("error", t("Failed to save configuration")); + showNotice.error("shared.feedback.notifications.common.saveFailed"); }, }, ); @@ -181,10 +183,10 @@ export const HeaderConfiguration = forwardRef( return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={handleSave} @@ -198,7 +200,7 @@ export const HeaderConfiguration = forwardRef( width="100%" > - {t("Allow private network access")} + {t("settings.sections.externalCors.fields.allowPrivateNetwork")} (
    - {t("Allowed Origins")} + {t("settings.sections.externalCors.fields.allowedOrigins")}
    {originEntries.map(({ origin, index, key }) => (
    ( sx={{ fontSize: 14, marginRight: 2 }} value={origin} onChange={(e) => handleUpdateOrigin(index, e.target.value)} - placeholder={t("Please enter a valid url")} + placeholder={t( + "settings.sections.externalCors.placeholders.origin", + )} inputProps={{ style: { fontSize: 14 } }} />
    (
    - {t("Always included origins: {{urls}}", { + {t("settings.sections.externalCors.messages.alwaysIncluded", { urls: DEV_URLS.join(", "), })}
    diff --git a/src/components/setting/mods/hotkey-input.tsx b/src/components/setting/mods/hotkey-input.tsx index 8198f1e95..9270d0633 100644 --- a/src/components/setting/mods/hotkey-input.tsx +++ b/src/components/setting/mods/hotkey-input.tsx @@ -102,7 +102,7 @@ export const HotkeyInput = (props: Props) => { { onChange([]); diff --git a/src/components/setting/mods/hotkey-viewer.tsx b/src/components/setting/mods/hotkey-viewer.tsx index d034af300..574abea4b 100644 --- a/src/components/setting/mods/hotkey-viewer.tsx +++ b/src/components/setting/mods/hotkey-viewer.tsx @@ -24,7 +24,19 @@ const HOTKEY_FUNC = [ "toggle_system_proxy", "toggle_tun_mode", "entry_lightweight_mode", -]; +] as const; + +const HOTKEY_FUNC_LABELS: Record<(typeof HOTKEY_FUNC)[number], string> = { + open_or_close_dashboard: + "settings.modals.hotkey.functions.openOrCloseDashboard", + clash_mode_rule: "settings.modals.hotkey.functions.rule", + clash_mode_global: "settings.modals.hotkey.functions.global", + clash_mode_direct: "settings.modals.hotkey.functions.direct", + toggle_system_proxy: "settings.modals.hotkey.functions.toggleSystemProxy", + toggle_tun_mode: "settings.modals.hotkey.functions.toggleTunMode", + entry_lightweight_mode: + "settings.modals.hotkey.functions.entryLightweightMode", +}; export const HotkeyViewer = forwardRef((props, ref) => { const { t } = useTranslation(); @@ -81,24 +93,26 @@ export const HotkeyViewer = forwardRef((props, ref) => { enable_global_hotkey: enableGlobalHotkey, }); setOpen(false); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} > - {t("Enable Global Hotkey")} + + {t("settings.modals.hotkey.toggles.enableGlobal")} + ((props, ref) => { {HOTKEY_FUNC.map((func) => ( - {t(func)} + {t(HOTKEY_FUNC_LABELS[func])} setHotkeyMap((m) => ({ ...m, [func]: v }))} diff --git a/src/components/setting/mods/layout-viewer.tsx b/src/components/setting/mods/layout-viewer.tsx index d300822ab..6f1482f4d 100644 --- a/src/components/setting/mods/layout-viewer.tsx +++ b/src/components/setting/mods/layout-viewer.tsx @@ -104,7 +104,7 @@ export const LayoutViewer = forwardRef((_, ref) => { const onSwitchFormat = (_e: any, value: boolean) => value; const onError = (err: any) => { - showNotice("error", err.message || err.toString()); + showNotice.error(err); }; const onChangeData = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); @@ -113,16 +113,20 @@ export const LayoutViewer = forwardRef((_, ref) => { return ( setOpen(false)} onCancel={() => setOpen(false)} > - + ((_, ref) => { - + ((_, ref) => { - + ((_, ref) => { - + ((_, ref) => { - {t("Hover Jump Navigator")} + + {t("settings.components.verge.layout.fields.hoverNavigator")} + @@ -206,9 +222,15 @@ export const LayoutViewer = forwardRef((_, ref) => { - {t("Hover Jump Navigator Delay")} + + {t( + "settings.components.verge.layout.fields.hoverNavigatorDelay", + )} + @@ -241,7 +263,7 @@ export const LayoutViewer = forwardRef((_, ref) => { input: { endAdornment: ( - {t("millis")} + {t("shared.units.milliseconds")} ), }, @@ -256,7 +278,9 @@ export const LayoutViewer = forwardRef((_, ref) => { - + ((_, ref) => { onGuard={(value) => patchVerge({ menu_icon: value })} > {OS === "macos" && ( - + ((_, ref) => { size="small" sx={{ width: 140, "> div": { py: "7.5px" } }} > - {t("Monochrome")} - {t("Colorful")} + + {t( + "settings.components.verge.layout.options.icon.monochrome", + )} + + + {t("settings.components.verge.layout.options.icon.colorful")} + )} {/* {OS === "macos" && ( - + ((_, ref) => { )} */} {/* {OS === "macos" && ( - + ((_, ref) => { )} */} - + ((_, ref) => { - + ((_, ref) => { } }} > - {verge?.common_tray_icon ? t("Clear") : t("Browse")} + {verge?.common_tray_icon + ? t("shared.actions.clear") + : t("settings.components.verge.basic.actions.browse")} - + ((_, ref) => { } }} > - {verge?.sysproxy_tray_icon ? t("Clear") : t("Browse")} + {verge?.sysproxy_tray_icon + ? t("shared.actions.clear") + : t("settings.components.verge.basic.actions.browse")} - + ((_, ref) => { } }} > - {verge?.tun_tray_icon ? t("Clear") : t("Browse")} + {verge?.tun_tray_icon + ? t("shared.actions.clear") + : t("settings.components.verge.basic.actions.browse")} diff --git a/src/components/setting/mods/lite-mode-viewer.tsx b/src/components/setting/mods/lite-mode-viewer.tsx index 241b84b9d..cabd10d32 100644 --- a/src/components/setting/mods/lite-mode-viewer.tsx +++ b/src/components/setting/mods/lite-mode-viewer.tsx @@ -45,25 +45,27 @@ export function LiteModeViewer({ ref }: { ref?: Ref }) { auto_light_weight_minutes: values.autoEnterLiteModeDelay, }); setOpen(false); - } catch (err: any) { - showNotice("error", err.message || err.toString()); + } catch (err) { + showNotice.error(err); } }); return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} > - + }) { }} onClick={async () => await entry_lightweight_mode()} > - {t("Enable")} + {t("shared.actions.enable")} }) { {values.autoEnterLiteMode && ( <> - + }) { input: { endAdornment: ( - {t("mins")} + {t("shared.units.minutes")} ), }, @@ -133,10 +137,9 @@ export function LiteModeViewer({ ref }: { ref?: Ref }) { color="text.secondary" sx={{ fontStyle: "italic" }} > - {t( - "When closing the window, LightWeight Mode will be automatically activated after _n minutes", - { n: values.autoEnterLiteModeDelay }, - )} + {t("settings.modals.liteMode.messages.autoEnterHint", { + n: values.autoEnterLiteModeDelay, + })} diff --git a/src/components/setting/mods/local-backup-actions.tsx b/src/components/setting/mods/local-backup-actions.tsx index ff4ed4e11..e2dd5bd50 100644 --- a/src/components/setting/mods/local-backup-actions.tsx +++ b/src/components/setting/mods/local-backup-actions.tsx @@ -20,11 +20,13 @@ export const LocalBackupActions = memo( try { setLoading(true); await createLocalBackup(); - showNotice("success", t("Local Backup Created")); + showNotice.success( + "settings.modals.backup.messages.localBackupCreated", + ); await onBackupSuccess(); } catch (error) { console.error(error); - showNotice("error", t("Local Backup Failed")); + showNotice.error("settings.modals.backup.messages.localBackupFailed"); } finally { setLoading(false); } @@ -43,7 +45,7 @@ export const LocalBackupActions = memo( - {t("Local Backup Info")} + {t("settings.modals.backup.fields.info")} @@ -60,7 +62,7 @@ export const LocalBackupActions = memo( type="button" size="large" > - {t("Backup")} + {t("settings.modals.backup.actions.backup")} diff --git a/src/components/setting/mods/misc-viewer.tsx b/src/components/setting/mods/misc-viewer.tsx index b8dc3120a..dcdf924c6 100644 --- a/src/components/setting/mods/misc-viewer.tsx +++ b/src/components/setting/mods/misc-viewer.tsx @@ -69,25 +69,27 @@ export const MiscViewer = forwardRef((props, ref) => { auto_log_clean: values.autoLogClean as any, }); setOpen(false); - } catch (err: any) { - showNotice("error", err.toString()); + } catch (err) { + showNotice.error(err); } }); return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} > - + div": { py: "7.5px" } }} @@ -230,7 +240,7 @@ export const MiscViewer = forwardRef((props, ref) => { } > - {t("Auto Columns")} + {t("settings.modals.misc.options.proxyLayoutColumns.auto")} {[1, 2, 3, 4, 5].map((i) => ( @@ -241,7 +251,9 @@ export const MiscViewer = forwardRef((props, ref) => { - + div": { py: "7.5px" } }}> - Debug - Info - Warn - Error - Silent + + {t("settings.sections.clash.form.options.logLevel.debug")} + + + {t("settings.sections.clash.form.options.logLevel.info")} + + + {t("settings.sections.clash.form.options.logLevel.warning")} + + + {t("settings.sections.clash.form.options.logLevel.error")} + + + {t("settings.sections.clash.form.options.logLevel.silent")} + - + { {t("External")}} + label={t("settings.sections.clash.form.fields.external")} extra={ { e.stopPropagation(); @@ -234,10 +249,13 @@ const SettingClash = ({ onError }: Props) => { }} /> - webRef.current?.open()} label={t("Web UI")} /> + webRef.current?.open()} + label={t("settings.sections.clash.form.fields.webUI")} + /> { {isWIN && ( } /> )} - + ); }; diff --git a/src/components/setting/setting-system.tsx b/src/components/setting/setting-system.tsx index fcc03a8a9..bcaf47f65 100644 --- a/src/components/setting/setting-system.tsx +++ b/src/components/setting/setting-system.tsx @@ -41,20 +41,26 @@ const SettingSystem = ({ onError }: Props) => { }; return ( - + - + - + @@ -72,9 +78,8 @@ const SettingSystem = ({ onError }: Props) => { }} onGuard={async (e) => { if (isAdminMode) { - showNotice( - "info", - t("Administrator mode may not support auto launch"), + showNotice.info( + "settings.sections.system.tooltips.autoLaunchAdmin", ); } @@ -96,9 +101,12 @@ const SettingSystem = ({ onError }: Props) => { + } > { try { const info = await checkUpdate(); if (!info?.available) { - showNotice("success", t("Currently on the Latest Version")); + showNotice.success( + "settings.components.verge.advanced.notifications.latestVersion", + ); } else { updateRef.current?.open(); } } catch (err: any) { - showNotice("error", err.message || err.toString()); + showNotice.error(err); } }; const onExportDiagnosticInfo = useCallback(async () => { await exportDiagnosticInfo(); - showNotice("success", t("Copy Success"), 1000); - }, [t]); + showNotice.success( + "shared.feedback.notifications.common.copySuccess", + 1000, + ); + }, []); const copyVersion = useCallback(() => { navigator.clipboard.writeText(`v${version}`).then(() => { - showNotice("success", t("Version copied to clipboard"), 1000); + showNotice.success( + "settings.components.verge.advanced.notifications.versionCopied", + 1000, + ); }); - }, [t]); + }, []); return ( - + @@ -80,10 +88,10 @@ const SettingVergeAdvanced = ({ onError: _ }: Props) => { backupRef.current?.open()} - label={t("Backup Setting")} + label={t("settings.components.verge.advanced.fields.backupSetting")} extra={ } @@ -91,33 +99,45 @@ const SettingVergeAdvanced = ({ onError: _ }: Props) => { configRef.current?.open()} - label={t("Runtime Config")} + label={t("settings.components.verge.advanced.fields.runtimeConfig")} /> } /> - - - - - - - + + + + + + + } @@ -128,11 +148,11 @@ const SettingVergeAdvanced = ({ onError: _ }: Props) => { onClick={() => { exitApp(); }} - label={t("Exit")} + label={t("settings.components.verge.advanced.fields.exit")} /> { > } > diff --git a/src/components/setting/setting-verge-basic.tsx b/src/components/setting/setting-verge-basic.tsx index 15b48132e..2f3667798 100644 --- a/src/components/setting/setting-verge-basic.tsx +++ b/src/components/setting/setting-verge-basic.tsx @@ -76,11 +76,14 @@ const SettingVergeBasic = ({ onError }: Props) => { const onCopyClashEnv = useCallback(async () => { await copyClashEnv(); - showNotice("success", t("Copy Success"), 1000); - }, [t]); + showNotice.success( + "shared.feedback.notifications.common.copySuccess", + 1000, + ); + }, []); return ( - + @@ -89,7 +92,7 @@ const SettingVergeBasic = ({ onError }: Props) => { - + { - + { {OS !== "linux" && ( - + { onGuard={(e) => patchVerge({ tray_event: e })} > )} } @@ -161,7 +180,9 @@ const SettingVergeBasic = ({ onError }: Props) => { - + { - + { } }} > - {t("Browse")} + {t("settings.components.verge.basic.actions.browse")} {startup_script && ( )} @@ -234,22 +257,22 @@ const SettingVergeBasic = ({ onError }: Props) => { themeRef.current?.open()} - label={t("Theme Setting")} + label={t("settings.components.verge.basic.fields.themeSetting")} /> layoutRef.current?.open()} - label={t("Layout Setting")} + label={t("settings.components.verge.basic.fields.layoutSetting")} /> miscRef.current?.open()} - label={t("Miscellaneous")} + label={t("settings.components.verge.basic.fields.misc")} /> hotkeyRef.current?.open()} - label={t("Hotkey Setting")} + label={t("settings.components.verge.basic.fields.hotkeySetting")} /> ); diff --git a/src/components/shared/ProxyControlSwitches.tsx b/src/components/shared/ProxyControlSwitches.tsx index 5d9304bf3..c26eeb41a 100644 --- a/src/components/shared/ProxyControlSwitches.tsx +++ b/src/components/shared/ProxyControlSwitches.tsx @@ -126,15 +126,15 @@ const ProxyControlSwitches = ({ const { enable_tun_mode, enable_system_proxy } = verge ?? {}; const showErrorNotice = useCallback( - (msg: string) => showNotice("error", t(msg)), - [t], + (msg: string) => showNotice.error(msg), + [], ); const handleTunToggle = async (value: boolean) => { if (!isTunModeAvailable) { - const msg = "TUN requires Service Mode or Admin Mode"; - showErrorNotice(msg); - throw new Error(t(msg)); + const msgKey = "settings.sections.proxyControl.tooltips.tunUnavailable"; + showErrorNotice(msgKey); + throw new Error(t(msgKey)); } mutateVerge({ ...verge, enable_tun_mode: value }, false); await patchVerge({ enable_tun_mode: value }); @@ -145,7 +145,7 @@ const ProxyControlSwitches = ({ await installServiceAndRestartCore(); await mutateSystemState(); } catch (err) { - showNotice("error", (err as Error).message || String(err)); + showNotice.error(err); } }); @@ -157,20 +157,21 @@ const ProxyControlSwitches = ({ await uninstallServiceAndRestartCore(); await mutateSystemState(); } catch (err) { - showNotice("error", (err as Error).message || String(err)); + showNotice.error(err); } }); - const isSystemProxyMode = label === t("System Proxy") || !label; - const isTunMode = label === t("Tun Mode"); + const isSystemProxyMode = + label === t("settings.sections.system.toggles.systemProxy") || !label; + const isTunMode = label === t("settings.sections.system.toggles.tunMode"); return ( {isSystemProxyMode && ( sysproxyRef.current?.open()} onToggle={(value) => toggleSystemProxy(value)} onError={onError} @@ -180,9 +181,9 @@ const ProxyControlSwitches = ({ {isTunMode && ( tunRef.current?.open()} onToggle={handleTunToggle} onError={onError} @@ -193,12 +194,16 @@ const ProxyControlSwitches = ({ {!isTunModeAvailable && ( <> - {t("Test")} + {t("tests.components.item.actions.test")} )} diff --git a/src/components/test/test-viewer.tsx b/src/components/test/test-viewer.tsx index 3dd5d3b6d..0ca2ebc68 100644 --- a/src/components/test/test-viewer.tsx +++ b/src/components/test/test-viewer.tsx @@ -101,7 +101,7 @@ export const TestViewer = forwardRef((props, ref) => { setLoading(false); setTimeout(() => formIns.reset(), 500); } catch (err: any) { - showNotice("error", err.message || err.toString()); + showNotice.error(err); setLoading(false); } }), @@ -124,10 +124,14 @@ export const TestViewer = forwardRef((props, ref) => { return ( ((props, ref) => { name="name" control={control} render={({ field }) => ( - + )} /> ((props, ref) => { {...field} multiline maxRows={5} - label={t("Icon")} + label={t("shared.labels.icon")} /> )} /> @@ -162,7 +166,7 @@ export const TestViewer = forwardRef((props, ref) => { {...field} multiline maxRows={3} - label={t("Test URL")} + label={t("tests.modals.test.fields.url")} /> )} /> diff --git a/src/hooks/use-system-state.ts b/src/hooks/use-system-state.ts index 374252707..474a743df 100644 --- a/src/hooks/use-system-state.ts +++ b/src/hooks/use-system-state.ts @@ -1,5 +1,4 @@ import { useEffect } from "react"; -import { useTranslation } from "react-i18next"; import useSWR from "swr"; import { getRunningMode, isAdmin, isServiceAvailable } from "@/services/cmds"; @@ -26,7 +25,6 @@ let disablingTunMode = false; * 包括运行模式、管理员状态、系统服务是否可用 */ export function useSystemState() { - const { t } = useTranslation(); const { verge, patchVerge } = useVerge(); const { @@ -67,14 +65,15 @@ export function useSystemState() { disablingTunMode = true; patchVerge({ enable_tun_mode: false }) .then(() => { - showNotice( - "info", - t("TUN Mode automatically disabled due to service unavailable"), + showNotice.info( + "settings.sections.system.notifications.tunMode.autoDisabled", ); }) .catch((err) => { console.error("[useVerge] 自动关闭TUN模式失败:", err); - showNotice("error", t("Failed to disable TUN Mode automatically")); + showNotice.error( + "settings.sections.system.notifications.tunMode.autoDisableFailed", + ); }) .finally(() => { const tid = setTimeout(() => { @@ -84,7 +83,7 @@ export function useSystemState() { }, 1000); }); } - }, [enable_tun_mode, isTunModeAvailable, patchVerge, isLoading, t]); + }, [enable_tun_mode, isTunModeAvailable, patchVerge, isLoading]); return { runningMode: systemState.runningMode, diff --git a/src/hooks/useServiceInstaller.ts b/src/hooks/useServiceInstaller.ts index 2f2168767..51985980d 100644 --- a/src/hooks/useServiceInstaller.ts +++ b/src/hooks/useServiceInstaller.ts @@ -1,4 +1,3 @@ -import { t } from "i18next"; import { useCallback } from "react"; import { installService, restartCore } from "@/services/cmds"; @@ -8,18 +7,17 @@ import { useSystemState } from "./use-system-state"; const executeWithErrorHandling = async ( operation: () => Promise, - loadingMessage: string, - successMessage?: string, + loadingKey: string, + successKey?: string, ) => { try { - showNotice("info", t(loadingMessage)); + showNotice.info(loadingKey); await operation(); - if (successMessage) { - showNotice("success", t(successMessage)); + if (successKey) { + showNotice.success(successKey); } } catch (err) { - const msg = (err as Error)?.message || String(err); - showNotice("error", msg); + showNotice.error(err); throw err; } }; @@ -30,14 +28,14 @@ export const useServiceInstaller = () => { const installServiceAndRestartCore = useCallback(async () => { await executeWithErrorHandling( () => installService(), - "Installing Service...", - "Service Installed Successfully", + "settings.statuses.clashService.installing", + "settings.feedback.notifications.clashService.installSuccess", ); await executeWithErrorHandling( () => restartCore(), - "Restarting Core...", - "Clash Core Restarted", + "settings.statuses.clash.restarting", + "settings.feedback.notifications.clash.restartSuccess", ); await mutateSystemState(); diff --git a/src/hooks/useServiceUninstaller.ts b/src/hooks/useServiceUninstaller.ts index fbcd76a52..a02c272a5 100644 --- a/src/hooks/useServiceUninstaller.ts +++ b/src/hooks/useServiceUninstaller.ts @@ -1,4 +1,3 @@ -import { t } from "i18next"; import { useCallback } from "react"; import { restartCore, stopCore, uninstallService } from "@/services/cmds"; @@ -8,18 +7,17 @@ import { useSystemState } from "./use-system-state"; const executeWithErrorHandling = async ( operation: () => Promise, - loadingMessage: string, - successMessage?: string, + loadingKey: string, + successKey?: string, ) => { try { - showNotice("info", t(loadingMessage)); + showNotice.info(loadingKey); await operation(); - if (successMessage) { - showNotice("success", t(successMessage)); + if (successKey) { + showNotice.success(successKey); } } catch (err) { - const msg = (err as Error)?.message || String(err); - showNotice("error", msg); + showNotice.error(err); throw err; } }; @@ -29,18 +27,21 @@ export const useServiceUninstaller = () => { const uninstallServiceAndRestartCore = useCallback(async () => { try { - await executeWithErrorHandling(() => stopCore(), "Stopping Core..."); + await executeWithErrorHandling( + () => stopCore(), + "settings.statuses.clash.stopping", + ); await executeWithErrorHandling( () => uninstallService(), - "Uninstalling Service...", - "Service Uninstalled Successfully", + "settings.statuses.clashService.uninstalling", + "settings.feedback.notifications.clashService.uninstallSuccess", ); } catch (ignore) { } finally { await executeWithErrorHandling( () => restartCore(), - "Restarting Core...", - "Clash Core Restarted", + "settings.statuses.clash.restarting", + "settings.feedback.notifications.clash.restartSuccess", ); await mutateSystemState(); } diff --git a/src/locales/ar.json b/src/locales/ar.json deleted file mode 100644 index ded40404b..000000000 --- a/src/locales/ar.json +++ /dev/null @@ -1,463 +0,0 @@ -{ - "millis": "ميلي ثانية", - "seconds": "ثواني", - "mins": "دقائق", - "Back": "رجوع", - "Close": "إغلاق", - "Cancel": "إلغاء", - "Confirm": "تأكيد", - "Maximize": "تكبير", - "Minimize": "تصغير", - "Format document": "تنسيق المستند", - "Empty": "فارغ", - "New": "جديد", - "Edit": "تعديل", - "Save": "حفظ", - "Delete": "حذف", - "Enable": "تمكين", - "Disable": "تعطيل", - "Label-Proxies": "الوكلاء", - "Label-Profiles": "الملفات الشخصية", - "Label-Connections": "الاتصالات", - "Label-Rules": "القواعد", - "Label-Logs": "السجلات", - "Label-Settings": "الإعدادات", - "Proxies": "الوكلاء", - "Proxy Groups": "مجموعات الوكلاء", - "Proxy Provider": "مزود الوكيل", - "Update All": "تحديث الكل", - "Update At": "التحديث عند", - "rule": "قاعدة", - "global": "عالمي", - "direct": "مباشر", - "Chain Proxy": "🔗 بروكسي السلسلة", - "script": "سكريبت", - "locate": "الموقع", - "Delay check": "فحص التأخير", - "Sort by default": "الترتيب الافتراضي", - "Sort by delay": "الترتيب حسب التأخير", - "Sort by name": "الترتيب حسب الاسم", - "Delay check URL": "رابط فحص التأخير", - "Delay check to cancel fixed": "فحص التأخير لإلغاء الثابت", - "Proxy basic": "إعدادات الوكيل الأساسية", - "Proxy detail": "تفاصيل الوكيل", - "Profiles": "الملفات الشخصية", - "Update All Profiles": "تحديث جميع الملفات الشخصية", - "View Runtime Config": "عرض تكوين وقت التشغيل", - "Reactivate Profiles": "إعادة تنشيط الملفات الشخصية", - "Paste": "لصق", - "Profile URL": "رابط الملف الشخصي", - "Import": "استيراد", - "From": "من", - "Update Time": "وقت التحديث", - "Used / Total": "المستخدم / الإجمالي", - "Expire Time": "وقت الانتهاء", - "Create Profile": "إنشاء ملف شخصي", - "Edit Profile": "تعديل الملف الشخصي", - "Edit Proxies": "تعديل الوكلاء", - "Use newlines for multiple uri": "استخدم أسطرًا جديدة لعدّة عناوين URI (يدعم التشفير Base64)", - "Edit Rules": "تعديل القواعد", - "Rule Type": "نوع القاعدة", - "Rule Content": "محتوى القاعدة", - "Proxy Policy": "سياسة الوكيل", - "No Resolve": "لا يوجد حل", - "Prepend Rule": "إضافة قاعدة في البداية", - "Append Rule": "إضافة قاعدة في النهاية", - "Prepend Group": "إضافة مجموعة في البداية", - "Append Group": "إضافة مجموعة في النهاية", - "Prepend Proxy": "إضافة وكيل في البداية", - "Append Proxy": "إضافة وكيل في النهاية", - "Rule Condition Required": "شرط القاعدة مطلوب", - "Invalid Rule": "قاعدة غير صالحة", - "Advanced": "متقدم", - "Visualization": "تصور", - "DOMAIN": "مطابقة اسم المجال الكامل", - "DOMAIN-SUFFIX": "مطابقة لاحقة المجال", - "DOMAIN-KEYWORD": "مطابقة كلمة مفتاحية في المجال", - "DOMAIN-REGEX": "مطابقة المجال باستخدام التعبيرات العادية", - "GEOSITE": "مطابقة المجالات ضمن Geosite", - "GEOIP": "مطابقة رمز البلد لعنوان IP", - "SRC-GEOIP": "مطابقة رمز البلد لعنوان IP المصدر", - "IP-ASN": "مطابقة ASN لعنوان IP", - "SRC-IP-ASN": "مطابقة ASN لعنوان IP المصدر", - "IP-CIDR": "مطابقة نطاق عنوان IP", - "IP-CIDR6": "مطابقة نطاق عناوين IPv6", - "SRC-IP-CIDR": "مطابقة نطاق عنوان IP المصدر", - "IP-SUFFIX": "مطابقة لاحقة عنوان IP", - "SRC-IP-SUFFIX": "مطابقة لاحقة عنوان IP المصدر", - "SRC-PORT": "مطابقة نطاق المنفذ المصدر", - "DST-PORT": "مطابقة نطاق المنفذ الوجهة", - "IN-PORT": "مطابقة المنفذ الوارد", - "DSCP": "علامة DSCP (لـ tproxy على UDP فقط)", - "PROCESS-NAME": "مطابقة اسم العملية (اسم حزمة Android)", - "PROCESS-PATH": "مطابقة المسار الكامل للعملية", - "PROCESS-NAME-REGEX": "مطابقة اسم العملية باستخدام التعبيرات العادية (اسم حزمة Android)", - "PROCESS-PATH-REGEX": "مطابقة المسار الكامل للعملية باستخدام التعبيرات العادية", - "NETWORK": "مطابقة بروتوكول النقل (TCP/UDP)", - "UID": "مطابقة معرف المستخدم في Linux", - "IN-TYPE": "مطابقة نوع الإدخال", - "IN-USER": "مطابقة اسم المستخدم للإدخال", - "IN-NAME": "مطابقة اسم الإدخال", - "SUB-RULE": "قاعدة فرعية", - "RULE-SET": "مطابقة مجموعة القواعد", - "AND": "منطقي AND", - "OR": "منطقي OR", - "NOT": "منطقي NOT", - "MATCH": "مطابقة جميع الطلبات", - "DIRECT": "البيانات تخرج مباشرة", - "REJECT": "رفض الطلبات", - "REJECT-DROP": "تجاهل الطلبات", - "PASS": "تخطي هذه القاعدة عند المطابقة", - "Edit Groups": "تعديل مجموعات الوكلاء", - "Group Type": "نوع المجموعة", - "select": "اختيار الوكيل يدويًا", - "url-test": "اختيار الوكيل بناءً على تأخير اختبار الرابط", - "fallback": "التبديل إلى وكيل آخر عند حدوث خطأ", - "load-balance": "توزيع التحميل بين الوكلاء", - "relay": "التمرير عبر سلسلة الوكلاء المحددة", - "Group Name": "اسم المجموعة", - "Use Proxies": "استخدام الوكلاء", - "Use Provider": "استخدام المزود", - "Health Check Url": "رابط فحص الصحة", - "Expected Status": "الحالة المتوقعة", - "Interval": "الفاصل الزمني", - "Lazy": "كسول", - "Timeout": "مهلة", - "Max Failed Times": "الحد الأقصى لمحاولات الفشل", - "Interface Name": "اسم الواجهة", - "Routing Mark": "علامة التوجيه", - "Include All": "تضمين جميع الوكلاء والمزودين", - "Include All Providers": "تضمين جميع المزودين", - "Include All Proxies": "تضمين جميع الوكلاء", - "Exclude Filter": "استبعاد المرشح", - "Exclude Type": "استبعاد النوع", - "Disable UDP": "تعطيل UDP", - "Hidden": "مخفي", - "Group Name Required": "اسم المجموعة مطلوب", - "Group Name Already Exists": "اسم المجموعة موجود بالفعل", - "Extend Config": "توسيع الإعدادات", - "Extend Script": "توسيع السكربت", - "Global Merge": "دمج عالمي للإعدادات", - "Global Script": "سكريبت عالمي", - "Type": "النوع", - "Name": "الاسم", - "Descriptions": "الوصف", - "Subscription URL": "رابط الاشتراك", - "Update Interval": "فاصل التحديث", - "Choose File": "اختر ملف", - "Use System Proxy": "استخدام وكيل النظام", - "Use Clash Proxy": "استخدام وكيل Clash", - "Accept Invalid Certs (Danger)": "قبول الشهادات غير الصالحة (خطر)", - "Refresh": "تحديث", - "Home": "الصفحة الرئيسية", - "Select": "اختيار", - "Edit Info": "تعديل المعلومات", - "Edit File": "تعديل الملف", - "Open File": "فتح الملف", - "Update": "تحديث", - "Update(Proxy)": "تحديث (الوكيل)", - "Confirm deletion": "تأكيد الحذف", - "This operation is not reversible": "لا يمكن التراجع عن هذه العملية", - "Script Console": "وحدة التحكم للسكريبت", - "To Top": "إلى الأعلى", - "To End": "إلى النهاية", - "Connections": "الاتصالات", - "Table View": "عرض الجدول", - "List View": "عرض القائمة", - "Close All": "إغلاق الكل", - "Download Speed": "سرعة التنزيل", - "Upload Speed": "سرعة الرفع", - "Host": "المضيف", - "Downloaded": "تم التنزيل", - "Uploaded": "تم الرفع", - "DL Speed": "سرعة التنزيل", - "UL Speed": "سرعة الرفع", - "Chains": "السلاسل", - "Rule": "قاعدة", - "Process": "عملية", - "Time": "الوقت", - "Source": "المصدر", - "Destination": "عنوان IP الوجهة", - "DestinationPort": "ميناء الوجهة", - "Close Connection": "إغلاق الاتصال", - "Rules": "القواعد", - "Rule Provider": "مزود القواعد", - "Logs": "السجلات", - "Pause": "إيقاف مؤقت", - "Resume": "استأنف", - "Clear": "مسح", - "Test": "اختبار", - "Test All": "اختبار الكل", - "Create Test": "إنشاء اختبار", - "Edit Test": "تعديل الاختبار", - "Icon": "أيقونة", - "Test URL": "رابط الاختبار", - "Settings": "الإعدادات", - "System Setting": "إعدادات النظام", - "Tun Mode": "وضع TUN", - "TUN requires Service Mode": "يتطلب وضع TUN خدمة", - "Install Service": "تثبيت الخدمة ", - "Reset to Default": "إعادة تعيين إلى الافتراضي", - "Tun Mode Info": "وضع TUN (بطاقة شبكة افتراضية): يلتقط كل حركة المرور في النظام. عند تمكينه، لا حاجة لتفعيل وكيل النظام.", - "Stack": "مكدس TUN", - "System and Mixed Can Only be Used in Service Mode": "لا يمكن استخدام النظام والمختلط إلا في وضع الخدمة", - "Device": "اسم الجهاز", - "Auto Route": "توجيه تلقائي", - "Strict Route": "توجيه صارم", - "Auto Detect Interface": "الكشف التلقائي عن الواجهة", - "DNS Hijack": "اختطاف DNS", - "MTU": "وحدة الإرسال القصوى", - "Service Mode": "وضع الخدمة", - "Service Mode Info": "يرجى تثبيت وضع الخدمة قبل تمكين وضع TUN. يمكن للعمليات الأساسية التي يبدأها وضع الخدمة الحصول على إذن لتثبيت بطاقة الشبكة الافتراضية (TUN).", - "Current State": "الحالة الحالية", - "pending": "معلق", - "installed": "مثبت", - "uninstall": "إلغاء التثبيت", - "active": "نشط", - "unknown": "غير معروف", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "معلومة: يرجى التأكد من تثبيت وتشغيل خدمة Clash Verge", - "Install": "تثبيت", - "Uninstall": "إلغاء التثبيت", - "Disable Service Mode": "تعطيل وضع الخدمة", - "System Proxy": "وكيل النظام", - "System Proxy Info": "عند التمكين، سيتم تعديل إعدادات الوكيل في نظام التشغيل. إذا فشل التمكين، فقم بتعديل إعدادات الوكيل في النظام يدويًا.", - "System Proxy Setting": "إعداد وكيل النظام", - "Current System Proxy": "الوكيل الحالي للنظام", - "Enable status": "حالة التمكين:", - "Enabled": "ممكّن", - "Disabled": "معطّل", - "Server Addr": "عنوان الخادم:", - "Proxy Host": "مضيف الوكيل", - "Invalid Proxy Host Format": "تنسيق مضيف الوكيل غير صالح", - "Not available": "غير متوفر", - "Proxy Guard": "حماية الوكيل", - "Proxy Guard Info": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام", - "Guard Duration": "مدة الحماية", - "Always use Default Bypass": "استخدام التخطي الافتراضي دائمًا", - "Proxy Bypass": "إعدادات تخطي الوكيل:", - "Bypass": "تخطي:", - "Use PAC Mode": "استخدام وضع PAC", - "PAC Script Content": "محتوى سكريبت PAC", - "PAC URL": "رابط PAC:", - "Auto Launch": "إطلاق تلقائي", - "Silent Start": "بدء صامت", - "Silent Start Info": "بدء البرنامج في الخلفية دون عرض الواجهة", - "TG Channel": "قناة تيليجرام", - "Manual": "دليل", - "Github Repo": "مستودع Github", - "Clash Setting": "إعدادات Clash", - "Allow Lan": "السماح بالشبكة المحلية", - "Network Interface": "واجهة الشبكة", - "Ip Address": "عنوان IP", - "Mac Address": "عنوان MAC", - "IPv6": "IPv6", - "Unified Delay": "تأخير موحد", - "Unified Delay Info": "عند تفعيل التأخير الموحد، سيتم إجراء اختبارين للتأخير لتقليل الفروقات الناتجة عن مفاوضات الاتصال", - "Log Level": "مستوى السجلات", - "Port Config": "تكوين المنافذ", - "Random Port": "منفذ عشوائي", - "Mixed Port": "منفذ مختلط", - "Socks Port": "منفذ SOCKS", - "Http Port": "منفذ HTTP(S)", - "Redir Port": "منفذ إعادة التوجيه", - "Tproxy Port": "منفذ Tproxy", - "External": "خارجي", - "External Controller": "وحدة التحكم الخارجية", - "Core Secret": "المفتاح السري للنواة", - "Recommended": "موصى به", - "Open URL": "فتح الرابط", - "Replace host, port, secret with %host, %port, %secret": "استبدل المضيف والمنفذ والمفتاح بـ %host و%port و%secret", - "Support %host, %port, %secret": "يدعم %host و%port و%secret", - "Clash Core": "نواة Clash", - "Upgrade": "ترقية", - "Restart": "إعادة التشغيل", - "Release Version": "إصدار مستقر", - "Alpha Version": "إصدار ألفا", - "Please Enable Service Mode": "يرجى تثبيت وتفعيل وضع الخدمة أولاً", - "Please enter your root password": "يرجى إدخال كلمة مرور الرووت", - "Grant": "منح الصلاحيات", - "Open UWP tool": "فتح أداة UWP", - "Open UWP tool Info": "منذ نظام ويندوز 8، يتم تقييد تطبيقات UWP من الوصول المباشر إلى المضيف المحلي. هذه الأداة تتيح تجاوز هذا التقييد", - "Update GeoData": "تحديث البيانات الجغرافية", - "Verge Basic Setting": "الإعدادات الأساسية Verge", - "Verge Advanced Setting": "الإعدادات الأساسية Verge", - "Language": "اللغة", - "Theme Mode": "وضع السمة", - "theme.light": "سمة فاتحة", - "theme.dark": "سمة داكنة", - "theme.system": "سمة النظام", - "Tray Click Event": "حدث النقر على الأيقونة في شريط المهام", - "Show Main Window": "إظهار النافذة الرئيسية", - "Copy Env Type": "نسخ نوع البيئة", - "Copy Success": "تم النسخ بنجاح", - "Start Page": "صفحة البدء", - "Startup Script": "سكريبت بدء التشغيل", - "Browse": "استعراض", - "Theme Setting": "إعدادات السمة", - "Primary Color": "اللون الأساسي", - "Secondary Color": "اللون الثانوي", - "Primary Text": "النص الأساسي", - "Secondary Text": "النص الثانوي", - "Info Color": "لون المعلومات", - "Warning Color": "لون التحذير", - "Error Color": "لون الخطأ", - "Success Color": "لون النجاح", - "Font Family": "عائلة الخط", - "CSS Injection": "حقن CSS", - "Layout Setting": "إعدادات التخطيط", - "Traffic Graph": "مخطط حركة المرور", - "Memory Usage": "استهلاك الذاكرة", - "Memory Cleanup": "انقر لتنظيف الذاكرة", - "Proxy Group Icon": "أيقونة مجموعة الوكلاء", - "Nav Icon": "أيقونة التنقل", - "Monochrome": "أحادي اللون", - "Colorful": "ملون", - "Tray Icon": "أيقونة شريط المهام", - "Common Tray Icon": "أيقونة شريط مهام عامة", - "System Proxy Tray Icon": "أيقونة شريط المهام لوكيل النظام", - "Tun Tray Icon": "أيقونة شريط المهام لـ TUN", - "Miscellaneous": "متفرقات", - "App Log Level": "مستوى سجلات التطبيق", - "Auto Close Connections": "إغلاق الاتصالات تلقائيًا", - "Auto Close Connections Info": "إنهاء الاتصالات القائمة عند تغيير اختيار مجموعة الوكيل أو وضع الوكيل", - "Auto Check Update": "فحص التحديث تلقائيًا", - "Enable Builtin Enhanced": "تفعيل التحسين المدمج", - "Enable Builtin Enhanced Info": "معالجة توافق ملف التكوين", - "Proxy Layout Columns": "أعمدة عرض الوكيل", - "Auto Columns": "أعمدة تلقائية", - "Auto Log Clean": "تنظيف السجلات تلقائيًا", - "Never Clean": "عدم التنظيف أبدًا", - "Retain _n Days": "الاحتفاظ لمدة {{n}} يومًا", - "Auto Delay Detection": "اكتشاف التأخير التلقائي", - "Auto Delay Detection Info": "يختبر زمن استجابة العقدة الحالية على نحو دوري في الخلفية", - "Default Latency Test": "اختبار التأخير الافتراضي", - "Default Latency Test Info": "يُستخدم فقط لاختبار طلب HTTP العميل. لن يؤثر على ملف التكوين", - "Default Latency Timeout": "مهلة التأخير الافتراضية", - "Hotkey Setting": "إعدادات الاختصارات", - "Enable Global Hotkey": "تمكين مفتاح التشغيل السريع العالمي", - "open_or_close_dashboard": "فتح/إغلاق لوحة التحكم", - "clash_mode_rule": "وضع القواعد", - "clash_mode_global": "الوضع العالمي", - "clash_mode_direct": "الوضع المباشر", - "toggle_system_proxy": "تفعيل/تعطيل وكيل النظام", - "toggle_tun_mode": "تفعيل/تعطيل وضع TUN", - "Backup Setting": "إعداد النسخ الاحتياطي", - "Runtime Config": "تكوين وقت التشغيل", - "Open Conf Dir": "فتح مجلد التكوين", - "Open Conf Dir Info": "إذا عمل البرنامج بشكل غير طبيعي، قم بالنسخ الاحتياطي ثم حذف جميع الملفات في هذا المجلد ثم أعد تشغيل البرنامج", - "Open Core Dir": "فتح مجلد النواة", - "Open Logs Dir": "فتح مجلد السجلات", - "Check for Updates": "التحقق من وجود تحديثات", - "Go to Release Page": "الانتقال إلى صفحة الإصدارات", - "Portable Updater Error": "الإصدار المحمول لا يدعم التحديث داخل التطبيق. يرجى التنزيل والاستبدال يدويًا", - "Break Change Update Error": "هذا الإصدار هو تحديث رئيسي ولا يدعم التحديث داخل التطبيق. يرجى إلغاء التثبيت وتنزيل الإصدار الجديد وتثبيته يدويًا", - "Open Dev Tools": "أدوات المطور", - "Exit": "خروج", - "Verge Version": "إصدار Verge", - "ReadOnly": "للقراءة فقط", - "ReadOnlyMessage": "لا يمكن التعديل في محرر القراءة فقط", - "Filter": "تصفية", - "Filter conditions": "شروط التصفية", - "Match Case": "مطابقة الحالة", - "Match Whole Word": "مطابقة الكلمة بأكملها", - "Use Regular Expression": "استخدام التعبيرات العادية", - "Profile Imported Successfully": "تم استيراد الملف الشخصي بنجاح", - "Profile Switched": "تم التبديل إلى الملف الشخصي", - "Profile Reactivated": "تم إعادة تنشيط الملف الشخصي", - "Only YAML Files Supported": "لا يتم دعم سوى ملفات YAML", - "Settings Applied": "تم تطبيق الإعدادات", - "Installing Service...": "جاري تثبيت الخدمة...", - "Service Installed Successfully": "تم تثبيت الخدمة بنجاح", - "Service Uninstalled Successfully": "تم إلغاء تثبيت الخدمة بنجاح", - "Proxy Daemon Duration Cannot be Less than 1 Second": "لا يمكن أن تقل مدة خادم الوكيل عن ثانية واحدة", - "Invalid Bypass Format": "تنسيق التخطي غير صالح", - "Clash Port Modified": "تم تعديل منفذ Clash", - "Port Conflict": "تعارض في المنفذ", - "Restart Application to Apply Modifications": "أعد تشغيل التطبيق لتطبيق التعديلات", - "External Controller Address Modified": "تم تعديل عنوان وحدة التحكم الخارجية", - "Permissions Granted Successfully for _clash Core": "تم منح الأذونات بنجاح لـ {{core}} Core", - "Core Version Updated": "تم تحديث إصدار النواة", - "Clash Core Restarted": "تم إعادة تشغيل نواة Clash", - "GeoData Updated": "تم تحديث البيانات الجغرافية", - "Currently on the Latest Version": "أنت على أحدث إصدار حاليًا", - "Import Subscription Successful": "تم استيراد الاشتراك بنجاح", - "WebDAV Server URL": "عنوان خادم WebDAV", - "Username": "اسم المستخدم", - "Password": "كلمة المرور", - "Backup": "نسخ احتياطي", - "Filename": "اسم الملف", - "Actions": "الإجراءات", - "Restore": "استعادة", - "No Backups": "لا توجد نسخ احتياطية متاحة", - "WebDAV URL Required": "لا يمكن ترك رابط WebDAV فارغًا", - "Invalid WebDAV URL": "تنسيق رابط WebDAV غير صالح", - "Username Required": "لا يمكن ترك اسم المستخدم فارغًا", - "Password Required": "لا يمكن ترك كلمة المرور فارغة", - "Failed to Fetch Backups": "فشل في جلب ملفات النسخ الاحتياطي", - "WebDAV Config Saved": "تم حفظ إعدادات WebDAV بنجاح", - "WebDAV Config Save Failed": "فشل حفظ إعدادات WebDAV: {{error}}", - "Backup Created": "تم إنشاء النسخة الاحتياطية بنجاح", - "Backup Failed": "فشل في النسخ الاحتياطي: {{error}}", - "Delete Backup": "حذف النسخة الاحتياطية", - "Restore Backup": "استعادة النسخة الاحتياطية", - "Backup Time": "وقت النسخ الاحتياطي", - "Confirm to delete this backup file?": "هل تريد بالتأكيد حذف ملف النسخة الاحتياطية هذا؟", - "Confirm to restore this backup file?": "هل تريد بالتأكيد استعادة ملف النسخة الاحتياطية هذا؟", - "Restore Success, App will restart in 1s": "تمت الاستعادة بنجاح، سيعاد تشغيل التطبيق خلال ثانية واحدة", - "Failed to fetch backup files": "فشل في جلب ملفات النسخ الاحتياطي", - "Profile": "الملف الشخصي", - "Help": "مساعدة", - "About": "حول", - "Theme": "السمة", - "Main Window": "النافذة الرئيسية", - "Group Icon": "أيقونة المجموعة", - "Menu Icon": "أيقونة القائمة", - "PAC File": "ملف PAC", - "Web UI": "واجهة الويب", - "Hotkeys": "اختصارات لوحة المفاتيح", - "Verge Mixed Port": "منفذ Verge المختلط", - "Verge Socks Port": "منفذ Verge SOCKS", - "Verge Redir Port": "منفذ إعادة التوجيه لـ Verge", - "Verge Tproxy Port": "منفذ Tproxy لـ Verge", - "Verge Port": "منفذ Verge", - "Verge HTTP Enabled": "تمكين Verge HTTP", - "WebDAV URL": "رابط WebDAV", - "WebDAV Username": "اسم المستخدم لـ WebDAV", - "WebDAV Password": "كلمة مرور WebDAV", - "Dashboard": "لوحة التحكم", - "Restart App": "إعادة تشغيل التطبيق", - "Restart Clash Core": "إعادة تشغيل نواة Clash", - "TUN Mode": "وضع TUN", - "Copy Env": "نسخ البيئة", - "Conf Dir": "مجلد الإعدادات", - "Core Dir": "مجلد النواة", - "Logs Dir": "مجلد السجلات", - "Open Dir": "فتح المجلد", - "More": "المزيد", - "Rule Mode": "وضع القواعد", - "Global Mode": "الوضع العالمي", - "Direct Mode": "الوضع المباشر", - "Enable Tray Speed": "تفعيل سرعة التراي", - "LightWeight Mode": "وضع الأداء الخفيف", - "LightWeight Mode Info": "إيقاف الواجهة الرسومية والإبقاء على تشغيل النواة", - "Config Validation Failed": "فشل التحقق من تكوين الاشتراك، يرجى فحص ملف التكوين، تم التراجع عن التغييرات، تفاصيل الخطأ:", - "Boot Config Validation Failed": "فشل التحقق من التكوين عند الإقلاع، تم استخدام التكوين الافتراضي، يرجى فحص ملف التكوين، تفاصيل الخطأ:", - "Core Change Config Validation Failed": "فشل التحقق من التكوين عند تغيير النواة، تم استخدام التكوين الافتراضي، يرجى فحص ملف التكوين، تفاصيل الخطأ:", - "Config Validation Process Terminated": "تم إنهاء عملية التحقق", - "Script Syntax Error": "خطأ في بناء جملة السكريبت، تم التراجع عن التغييرات", - "Script Missing Main": "خطأ في السكريبت، تم التراجع عن التغييرات", - "File Not Found": "الملف غير موجود، تم التراجع عن التغييرات", - "Script File Error": "خطأ في ملف السكريبت، تم التراجع عن التغييرات", - "Core Changed Successfully": "تم تغيير النواة بنجاح", - "Failed to Change Core": "فشل تغيير النواة", - "Service Administrator Prompt": "يتطلب Clash Verge امتيازات المسؤول لإعادة تثبيت خدمة النظام", - "Auto Close Connection": "إغلاق الاتصال تلقائيًا", - "Default": "افتراضي", - "Enable Built-in Enhanced": "تفعيل التحسين المدمج", - "Enable Random Port": "تفعيل المنفذ العشوائي", - "Label-Test": "اختبار", - "Proxy Layout Column": "عمود عرض الوكيل", - "System Proxy Bypass": "تخطي وكيل النظام", - "Test List": "قائمة الاختبارات", - "Verge Setting": "إعدادات Verge" -} diff --git a/src/locales/ar/connections.json b/src/locales/ar/connections.json new file mode 100644 index 000000000..ad88bf120 --- /dev/null +++ b/src/locales/ar/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "الاتصالات" + }, + "components": { + "fields": { + "host": "المضيف", + "dlSpeed": "سرعة التنزيل", + "ulSpeed": "سرعة الرفع", + "chains": "السلاسل", + "rule": "قاعدة", + "process": "عملية", + "time": "الوقت", + "source": "المصدر", + "destination": "عنوان IP الوجهة", + "destinationPort": "ميناء الوجهة", + "type": "النوع" + }, + "order": { + "default": "Default", + "uploadSpeed": "سرعة الرفع", + "downloadSpeed": "سرعة التنزيل" + }, + "actions": { + "closeConnection": "إغلاق الاتصال" + } + } +} diff --git a/src/locales/ar/home.json b/src/locales/ar/home.json new file mode 100644 index 000000000..823a2f070 --- /dev/null +++ b/src/locales/ar/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "وضع الأداء الخفيف", + "manual": "دليل", + "settings": "Home Settings" + }, + "cards": { + "trafficStats": "Traffic Stats", + "networkSettings": "Network Settings", + "proxyMode": "Proxy Mode" + }, + "settings": { + "cards": { + "profile": "Profile Card", + "currentProxy": "Current Proxy Card", + "network": "Network Settings Card", + "proxyMode": "Proxy Mode Card", + "traffic": "Traffic Stats Card", + "tests": "Website Tests Card", + "ip": "IP Information Card", + "clashInfo": "Clash Info Cards", + "systemInfo": "System Info Cards" + }, + "title": "Home Settings" + }, + "title": "Home" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "System proxy is enabled, your applications will access the network through the proxy", + "systemProxyDisabled": "System proxy is disabled, it is recommended for most users to turn on this option", + "tunModeServiceRequired": "TUN mode requires service mode, please install the service first", + "tunModeEnabled": "TUN mode is enabled, applications will access the network through the virtual network card", + "tunModeDisabled": "TUN mode is disabled, suitable for special applications" + }, + "tooltips": { + "systemProxy": "عند التمكين، سيتم تعديل إعدادات الوكيل في نظام التشغيل. إذا فشل التمكين، فقم بتعديل إعدادات الوكيل في النظام يدويًا.", + "tunMode": "TUN mode can take over all application traffic, suitable for special applications that do not follow the system proxy settings" + } + }, + "clashInfo": { + "title": "Clash Info", + "fields": { + "coreVersion": "Core Version", + "systemProxyAddress": "System Proxy Address", + "mixedPort": "Mixed Port", + "uptime": "Uptime", + "rulesCount": "Rules Count" + } + }, + "systemInfo": { + "title": "System Info", + "fields": { + "osInfo": "OS Info", + "autoLaunch": "إطلاق تلقائي", + "runningMode": "Running Mode", + "lastCheckUpdate": "Last Check Update", + "vergeVersion": "إصدار Verge" + }, + "actions": { + "settings": "الإعدادات" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "وضع الخدمة", + "sidecarMode": "User Mode", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP Information", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Auto refresh", + "unknown": "Unknown" + }, + "errors": { + "load": "فشل الحصول على معلومات الـ IP" + } + }, + "currentProxy": { + "title": "Current Node", + "actions": { + "refreshDelay": "فحص التأخير" + }, + "labels": { + "globalMode": "الوضع العالمي", + "directMode": "الوضع المباشر", + "group": "Group", + "proxy": "Proxy", + "noActiveNode": "No active proxy node" + } + }, + "tests": { + "title": "Website Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "سرعة الرفع", + "downloadSpeed": "سرعة التنزيل", + "activeConnections": "Active Connections", + "memoryUsage": "استهلاك الذاكرة" + }, + "legends": { + "upload": "Upload", + "download": "Download" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "وضع القواعد", + "global": "الوضع العالمي", + "direct": "الوضع المباشر" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/ar/index.ts b/src/locales/ar/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/ar/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/ar/layout.json b/src/locales/ar/layout.json new file mode 100644 index 000000000..fba5415b1 --- /dev/null +++ b/src/locales/ar/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Home", + "proxies": "الوكلاء", + "profiles": "الملفات الشخصية", + "connections": "الاتصالات", + "rules": "القواعد", + "logs": "السجلات", + "unlock": "Test", + "settings": "الإعدادات" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/ar/logs.json b/src/locales/ar/logs.json new file mode 100644 index 000000000..06f3c65e0 --- /dev/null +++ b/src/locales/ar/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "السجلات" + } +} diff --git a/src/locales/ar/profiles.json b/src/locales/ar/profiles.json new file mode 100644 index 000000000..28264c07f --- /dev/null +++ b/src/locales/ar/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "تحديث جميع الملفات الشخصية", + "viewRuntimeConfig": "عرض تكوين وقت التشغيل", + "reactivate": "إعادة تنشيط الملفات الشخصية", + "import": "استيراد" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "رابط الملف الشخصي", + "actions": { + "paste": "لصق" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "لا يتم دعم سوى ملفات YAML" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "تم التبديل إلى الملف الشخصي", + "profileReactivated": "تم إعادة تنشيط الملف الشخصي", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "الملفات الشخصية" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Click to import subscription" + } + }, + "fileInput": { + "chooseFile": "اختر ملف" + }, + "menu": { + "home": "Home", + "select": "اختيار", + "editInfo": "تعديل المعلومات", + "editFile": "تعديل الملف", + "editRules": "تعديل القواعد", + "editProxies": "تعديل الوكلاء", + "editGroups": "تعديل مجموعات الوكلاء", + "extendConfig": "توسيع الإعدادات", + "extendScript": "توسيع السكربت", + "openFile": "فتح الملف", + "update": "تحديث", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "إنشاء ملف شخصي", + "edit": "تعديل الملف الشخصي" + }, + "fields": { + "type": "النوع", + "description": "الوصف", + "subscriptionUrl": "رابط الاشتراك", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "فاصل التحديث", + "useSystemProxy": "استخدام وكيل النظام", + "useClashProxy": "استخدام وكيل Clash", + "acceptInvalidCerts": "قبول الشهادات غير الصالحة (خطر)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "تعديل الوكلاء", + "placeholders": { + "multiUri": "استخدم أسطرًا جديدة لعدّة عناوين URI (يدعم التشفير Base64)" + }, + "actions": { + "prepend": "إضافة وكيل في البداية", + "append": "إضافة وكيل في النهاية" + } + }, + "groupsEditor": { + "title": "تعديل مجموعات الوكلاء", + "errors": { + "nameRequired": "اسم المجموعة مطلوب", + "nameExists": "اسم المجموعة موجود بالفعل" + }, + "fields": { + "type": "نوع المجموعة", + "name": "اسم المجموعة", + "icon": "أيقونة مجموعة الوكلاء", + "proxies": "استخدام الوكلاء", + "provider": "استخدام المزود", + "healthCheckUrl": "رابط فحص الصحة", + "expectedStatus": "الحالة المتوقعة", + "interval": "الفاصل الزمني", + "maxFailedTimes": "الحد الأقصى لمحاولات الفشل", + "interfaceName": "اسم الواجهة", + "routingMark": "علامة التوجيه", + "filter": "تصفية", + "excludeFilter": "استبعاد المرشح", + "excludeType": "استبعاد النوع", + "includeAll": "تضمين جميع الوكلاء والمزودين", + "includeAllProxies": "تضمين جميع الوكلاء", + "includeAllProviders": "تضمين جميع المزودين" + }, + "toggles": { + "lazy": "كسول", + "disableUdp": "تعطيل UDP", + "hidden": "مخفي" + }, + "actions": { + "prepend": "إضافة مجموعة في البداية", + "append": "إضافة مجموعة في النهاية" + } + }, + "editor": { + "actions": { + "format": "تنسيق المستند" + }, + "messages": { + "readOnly": "لا يمكن التعديل في محرر القراءة فقط" + } + }, + "confirmDelete": { + "title": "تأكيد الحذف", + "message": "لا يمكن التراجع عن هذه العملية" + }, + "logViewer": { + "title": "وحدة التحكم للسكريبت" + } + } +} diff --git a/src/locales/ar/proxies.json b/src/locales/ar/proxies.json new file mode 100644 index 000000000..995a4d39f --- /dev/null +++ b/src/locales/ar/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 بروكسي السلسلة", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "مزود الوكيل", + "actions": { + "updateAll": "تحديث الكل", + "update": "تحديث" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "فحص التأخير لإلغاء الثابت" + }, + "tooltips": { + "locate": "الموقع", + "delayCheck": "فحص التأخير", + "sortDefault": "الترتيب الافتراضي", + "sortDelay": "الترتيب حسب التأخير", + "sortName": "الترتيب حسب الاسم", + "delayCheckUrl": "رابط فحص التأخير", + "showBasic": "إعدادات الوكيل الأساسية", + "showDetail": "تفاصيل الوكيل", + "filter": "تصفية" + }, + "placeholders": { + "delayCheckUrl": "رابط فحص التأخير" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "الوضع المباشر" + }, + "title": { + "default": "مجموعات الوكلاء", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "اختيار الوكيل يدويًا", + "url-test": "اختيار الوكيل بناءً على تأخير اختبار الرابط", + "fallback": "التبديل إلى وكيل آخر عند حدوث خطأ", + "load-balance": "توزيع التحميل بين الوكلاء", + "relay": "التمرير عبر سلسلة الوكلاء المحددة" + }, + "policies": { + "DIRECT": "البيانات تخرج مباشرة", + "REJECT": "رفض الطلبات", + "REJECT-DROP": "تجاهل الطلبات", + "PASS": "تخطي هذه القاعدة عند المطابقة" + } + } + } +} diff --git a/src/locales/ar/rules.json b/src/locales/ar/rules.json new file mode 100644 index 000000000..b813c0fb9 --- /dev/null +++ b/src/locales/ar/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "مزود القواعد", + "dialogTitle": "مزود القواعد", + "actions": { + "updateAll": "تحديث الكل", + "update": "تحديث" + } + }, + "title": "القواعد" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "نوع القاعدة", + "content": "محتوى القاعدة", + "proxyPolicy": "سياسة الوكيل" + }, + "toggles": { + "noResolve": "لا يوجد حل" + }, + "actions": { + "prependRule": "إضافة قاعدة في البداية", + "appendRule": "إضافة قاعدة في النهاية" + }, + "validation": { + "conditionRequired": "شرط القاعدة مطلوب", + "invalidRule": "قاعدة غير صالحة" + } + }, + "ruleTypes": { + "DOMAIN": "مطابقة اسم المجال الكامل", + "DOMAIN-SUFFIX": "مطابقة لاحقة المجال", + "DOMAIN-KEYWORD": "مطابقة كلمة مفتاحية في المجال", + "DOMAIN-REGEX": "مطابقة المجال باستخدام التعبيرات العادية", + "GEOSITE": "مطابقة المجالات ضمن Geosite", + "GEOIP": "مطابقة رمز البلد لعنوان IP", + "SRC-GEOIP": "مطابقة رمز البلد لعنوان IP المصدر", + "IP-ASN": "مطابقة ASN لعنوان IP", + "SRC-IP-ASN": "مطابقة ASN لعنوان IP المصدر", + "IP-CIDR": "مطابقة نطاق عنوان IP", + "IP-CIDR6": "مطابقة نطاق عناوين IPv6", + "SRC-IP-CIDR": "مطابقة نطاق عنوان IP المصدر", + "IP-SUFFIX": "مطابقة لاحقة عنوان IP", + "SRC-IP-SUFFIX": "مطابقة لاحقة عنوان IP المصدر", + "SRC-PORT": "مطابقة نطاق المنفذ المصدر", + "DST-PORT": "مطابقة نطاق المنفذ الوجهة", + "IN-PORT": "مطابقة المنفذ الوارد", + "DSCP": "علامة DSCP (لـ tproxy على UDP فقط)", + "PROCESS-NAME": "مطابقة اسم العملية (اسم حزمة Android)", + "PROCESS-PATH": "مطابقة المسار الكامل للعملية", + "PROCESS-NAME-REGEX": "مطابقة اسم العملية باستخدام التعبيرات العادية (اسم حزمة Android)", + "PROCESS-PATH-REGEX": "مطابقة المسار الكامل للعملية باستخدام التعبيرات العادية", + "NETWORK": "مطابقة بروتوكول النقل (TCP/UDP)", + "UID": "مطابقة معرف المستخدم في Linux", + "IN-TYPE": "مطابقة نوع الإدخال", + "IN-USER": "مطابقة اسم المستخدم للإدخال", + "IN-NAME": "مطابقة اسم الإدخال", + "SUB-RULE": "قاعدة فرعية", + "RULE-SET": "مطابقة مجموعة القواعد", + "AND": "منطقي AND", + "OR": "منطقي OR", + "NOT": "منطقي NOT", + "MATCH": "مطابقة جميع الطلبات" + }, + "title": "تعديل القواعد" + } + } +} diff --git a/src/locales/ar/settings.json b/src/locales/ar/settings.json new file mode 100644 index 000000000..4c01bff35 --- /dev/null +++ b/src/locales/ar/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "دليل", + "telegram": "قناة تيليجرام", + "github": "مستودع Github" + }, + "title": "الإعدادات" + }, + "sections": { + "system": { + "title": "إعدادات النظام", + "toggles": { + "tunMode": "وضع TUN", + "systemProxy": "وكيل النظام" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "بدء البرنامج في الخلفية دون عرض الواجهة" + }, + "fields": { + "autoLaunch": "تشغيل تلقائي", + "silentStart": "تشغيل صامت" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "عند التمكين، سيتم تعديل إعدادات الوكيل في نظام التشغيل. إذا فشل التمكين، فقم بتعديل إعدادات الوكيل في النظام يدويًا.", + "tunMode": "وضع TUN (بطاقة شبكة افتراضية): يلتقط كل حركة المرور في النظام. عند تمكينه، لا حاجة لتفعيل وكيل النظام.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "تثبيت الخدمة ", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "وكيل النظام", + "tunMode": "وضع TUN" + } + }, + "externalController": { + "title": "وحدة التحكم الخارجية", + "fields": { + "enable": "Enable External Controller", + "address": "وحدة التحكم الخارجية", + "secret": "المفتاح السري للنواة" + }, + "placeholders": { + "address": "Required", + "secret": "موصى به" + }, + "tooltips": { + "copy": "Copy to clipboard" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Failed to copy", + "controllerCopied": "Controller address copied to clipboard", + "secretCopied": "Secret copied to clipboard" + } + }, + "externalCors": { + "title": "External Cors Configuration", + "fields": { + "allowPrivateNetwork": "Allow private network access", + "allowedOrigins": "Allowed Origins" + }, + "placeholders": { + "origin": "Please enter a valid url" + }, + "actions": { + "add": "Add" + }, + "messages": { + "alwaysIncluded": "Always included origins: {{urls}}" + }, + "tooltips": { + "open": "External Cors Settings" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "إعدادات Clash", + "form": { + "fields": { + "allowLan": "السماح بالشبكة المحلية", + "dnsOverwrite": "DNS Overwrite", + "ipv6": "IPv6", + "unifiedDelay": "تأخير موحد", + "logLevel": "مستوى السجلات", + "portConfig": "تكوين المنافذ", + "external": "خارجي", + "webUI": "واجهة الويب", + "clashCore": "نواة Clash", + "openUwpTool": "فتح أداة UWP", + "updateGeoData": "تحديث البيانات الجغرافية" + }, + "tooltips": { + "networkInterface": "واجهة الشبكة", + "unifiedDelay": "عند تفعيل التأخير الموحد، سيتم إجراء اختبارين للتأخير لتقليل الفروقات الناتجة عن مفاوضات الاتصال", + "logLevel": "This parameter is valid only for kernel log files in the log directory Service folder", + "openUwpTool": "منذ نظام ويندوز 8، يتم تقييد تطبيقات UWP من الوصول المباشر إلى المضيف المحلي. هذه الأداة تتيح تجاوز هذا التقييد" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "الإعدادات الأساسية Verge", + "actions": { + "browse": "استعراض" + }, + "trayOptions": { + "showMainWindow": "إظهار النافذة الرئيسية", + "showTrayMenu": "Show Tray Menu", + "disable": "تعطيل" + }, + "fields": { + "language": "اللغة", + "themeMode": "وضع السمة", + "trayClickEvent": "حدث النقر على الأيقونة في شريط المهام", + "copyEnvType": "نسخ نوع البيئة", + "startPage": "صفحة البدء", + "startupScript": "سكريبت بدء التشغيل", + "themeSetting": "إعدادات السمة", + "layoutSetting": "إعدادات التخطيط", + "misc": "متفرقات", + "hotkeySetting": "إعدادات الاختصارات" + } + }, + "advanced": { + "title": "الإعدادات الأساسية Verge", + "tooltips": { + "backupInfo": "Support local or WebDAV backup of configuration files", + "openConfDir": "إذا عمل البرنامج بشكل غير طبيعي، قم بالنسخ الاحتياطي ثم حذف جميع الملفات في هذا المجلد ثم أعد تشغيل البرنامج", + "liteMode": "إيقاف الواجهة الرسومية والإبقاء على تشغيل النواة" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "أنت على أحدث إصدار حاليًا", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "إعداد النسخ الاحتياطي", + "runtimeConfig": "تكوين وقت التشغيل", + "openConfDir": "فتح مجلد التكوين", + "openCoreDir": "فتح مجلد النواة", + "openLogsDir": "فتح مجلد السجلات", + "checkUpdates": "التحقق من وجود تحديثات", + "openDevTools": "أدوات المطور", + "liteModeSettings": "LightWeight Mode Settings", + "exit": "خروج", + "exportDiagnostics": "Export Diagnostic Info", + "vergeVersion": "إصدار Verge" + } + }, + "theme": { + "title": "إعدادات السمة", + "fields": { + "primaryColor": "اللون الأساسي", + "secondaryColor": "اللون الثانوي", + "primaryText": "النص الأساسي", + "secondaryText": "النص الثانوي", + "infoColor": "لون المعلومات", + "warningColor": "لون التحذير", + "errorColor": "لون الخطأ", + "successColor": "لون النجاح", + "fontFamily": "عائلة الخط", + "cssInjection": "حقن CSS" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "إعدادات التخطيط", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "مخطط حركة المرور", + "memoryUsage": "استهلاك الذاكرة", + "proxyGroupIcon": "أيقونة مجموعة الوكلاء", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "أيقونة التنقل", + "trayIcon": "أيقونة شريط المهام", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "أيقونة شريط مهام عامة", + "systemProxyTrayIcon": "أيقونة شريط المهام لوكيل النظام", + "tunTrayIcon": "أيقونة شريط المهام لـ TUN", + "enableTrayIcon": "Enable Tray Icon", + "enableTraySpeed": "تفعيل سرعة التراي" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "أحادي اللون", + "colorful": "ملون", + "disable": "تعطيل" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "تكوين المنافذ", + "fields": { + "mixed": "منفذ مختلط", + "socks": "منفذ SOCKS", + "http": "منفذ HTTP(S)", + "redir": "منفذ إعادة التوجيه", + "tproxy": "منفذ Tproxy" + }, + "actions": { + "random": "منفذ عشوائي" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "الإصدار المستقر", + "alpha": "الإصدار التجريبي" + } + }, + "liteMode": { + "title": "LightWeight Mode Settings", + "actions": { + "enterNow": "Enter LightWeight Mode Now" + }, + "toggles": { + "autoEnter": "Auto Enter LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time" + }, + "fields": { + "delay": "Auto Enter LightWeight Mode Delay" + }, + "messages": { + "autoEnterHint": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes" + } + }, + "backup": { + "title": "إعداد النسخ الاحتياطي", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "نسخ احتياطي", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "حذف النسخة الاحتياطية", + "restore": "استعادة", + "restoreBackup": "استعادة النسخة الاحتياطية" + }, + "fields": { + "webdavUrl": "عنوان خادم WebDAV", + "username": "اسم المستخدم", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "لا يمكن ترك رابط WebDAV فارغًا", + "invalidWebdavUrl": "تنسيق رابط WebDAV غير صالح", + "usernameRequired": "لا يمكن ترك اسم المستخدم فارغًا", + "passwordRequired": "لا يمكن ترك كلمة المرور فارغة", + "webdavConfigSaved": "تم حفظ إعدادات WebDAV بنجاح", + "webdavConfigSaveFailed": "فشل حفظ إعدادات WebDAV: {{error}}", + "backupCreated": "تم إنشاء النسخة الاحتياطية بنجاح", + "backupFailed": "فشل في النسخ الاحتياطي: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "تمت الاستعادة بنجاح، سيعاد تشغيل التطبيق خلال ثانية واحدة", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "هل تريد بالتأكيد حذف ملف النسخة الاحتياطية هذا؟", + "confirmRestore": "هل تريد بالتأكيد استعادة ملف النسخة الاحتياطية هذا؟" + }, + "table": { + "filename": "اسم الملف", + "backupTime": "وقت النسخ الاحتياطي", + "actions": "الإجراءات", + "noBackups": "لا توجد نسخ احتياطية متاحة", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "متفرقات", + "fields": { + "appLogLevel": "مستوى سجلات التطبيق", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "إغلاق الاتصالات تلقائيًا", + "autoCheckUpdate": "فحص التحديث تلقائيًا", + "enableBuiltinEnhanced": "تفعيل التحسين المدمج", + "proxyLayoutColumns": "أعمدة عرض الوكيل", + "autoLogClean": "تنظيف السجلات تلقائيًا", + "autoDelayDetection": "اكتشاف التأخير التلقائي", + "defaultLatencyTest": "اختبار التأخير الافتراضي", + "defaultLatencyTimeout": "مهلة التأخير الافتراضية" + }, + "tooltips": { + "autoCloseConnections": "إنهاء الاتصالات القائمة عند تغيير اختيار مجموعة الوكيل أو وضع الوكيل", + "enableBuiltinEnhanced": "معالجة توافق ملف التكوين", + "autoDelayDetection": "يختبر زمن استجابة العقدة الحالية على نحو دوري في الخلفية", + "defaultLatencyTest": "يُستخدم فقط لاختبار طلب HTTP العميل. لن يؤثر على ملف التكوين" + }, + "options": { + "proxyLayoutColumns": { + "auto": "أعمدة تلقائية" + }, + "autoLogClean": { + "never": "عدم التنظيف أبدًا", + "retainDays": "الاحتفاظ لمدة {{n}} يومًا" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "الانتقال إلى صفحة الإصدارات", + "update": "تحديث" + }, + "messages": { + "portableError": "الإصدار المحمول لا يدعم التحديث داخل التطبيق. يرجى التنزيل والاستبدال يدويًا", + "breakChangeError": "هذا الإصدار هو تحديث رئيسي ولا يدعم التحديث داخل التطبيق. يرجى إلغاء التثبيت وتنزيل الإصدار الجديد وتثبيته يدويًا" + } + }, + "sysproxy": { + "title": "إعداد وكيل النظام", + "fieldsets": { + "currentStatus": "الوكيل الحالي للنظام" + }, + "fields": { + "enableStatus": "حالة التمكين:", + "serverAddr": "عنوان الخادم:", + "pacUrl": "رابط PAC:", + "proxyHost": "مضيف الوكيل", + "usePacMode": "استخدام وضع PAC", + "proxyGuard": "حماية الوكيل", + "guardDuration": "مدة الحماية", + "alwaysUseDefaultBypass": "استخدام التخطي الافتراضي دائمًا", + "proxyBypass": "إعدادات تخطي الوكيل:", + "bypass": "تخطي:", + "pacScriptContent": "محتوى سكريبت PAC" + }, + "tooltips": { + "proxyGuard": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام" + }, + "messages": { + "durationTooShort": "لا يمكن أن تقل مدة خادم الوكيل عن ثانية واحدة", + "invalidBypass": "تنسيق التخطي غير صالح", + "invalidProxyHost": "تنسيق مضيف الوكيل غير صالح" + }, + "actions": { + "editPac": "تعديل PAC" + } + }, + "tun": { + "title": "وضع TUN", + "fields": { + "stack": "مكدس TUN", + "device": "Device Name", + "autoRoute": "توجيه تلقائي", + "strictRoute": "توجيه صارم", + "autoDetectInterface": "الكشف التلقائي عن الواجهة", + "dnsHijack": "اختطاف DNS", + "mtu": "وحدة الإرسال القصوى" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "تم تطبيق الإعدادات" + } + }, + "dns": { + "dialog": { + "title": "DNS Overwrite", + "warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled" + }, + "sections": { + "general": "DNS Settings", + "fallbackFilter": "Fallback Filter Settings", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Enable DNS", + "listen": "DNS Listen", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Fake IP Range", + "fakeIpFilterMode": "Fake IP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Prefer H3", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Respect Rules", + "description": "DNS connections follow routing rules" + }, + "useHosts": { + "label": "Use Hosts", + "description": "Enable to resolve hosts through hosts file" + }, + "useSystemHosts": { + "label": "Use System Hosts", + "description": "Enable to resolve hosts through system hosts file" + }, + "directPolicy": { + "label": "Direct Nameserver Follow Policy", + "description": "Whether to follow nameserver policy" + }, + "defaultNameserver": { + "label": "Default Nameserver", + "description": "Default DNS servers used to resolve DNS servers" + }, + "nameserver": { + "label": "Nameserver", + "description": "List of DNS servers, comma separated" + }, + "fallback": { + "label": "Fallback", + "description": "List of fallback DNS servers, comma separated" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS servers for proxy node domain resolution" + }, + "directNameserver": { + "label": "Direct Nameserver", + "description": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated" + }, + "fakeIpFilter": { + "label": "Fake IP Filter", + "description": "Domains that skip fake IP resolution, comma separated" + }, + "nameserverPolicy": { + "label": "Nameserver Policy", + "description": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtering", + "description": "Enable GeoIP filtering for fallback" + }, + "geoipCode": "GeoIP Code", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "IP CIDRs not using fallback servers, comma separated" + }, + "fallbackDomain": { + "label": "Fallback Domain", + "description": "Domains using fallback servers, comma separated" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "فتح الرابط" + }, + "title": "واجهة الويب", + "messages": { + "supportedPlaceholders": "يدعم %host و%port و%secret", + "placeholderInstruction": "استبدل المضيف والمنفذ والمفتاح بـ %host و%port و%secret" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "تمكين مفتاح التشغيل السريع العالمي" + }, + "title": "إعدادات الاختصارات", + "functions": { + "rule": "وضع القواعد", + "global": "الوضع العالمي", + "openOrCloseDashboard": "فتح/إغلاق لوحة التحكم", + "toggleSystemProxy": "تفعيل/تعطيل وكيل النظام", + "toggleTunMode": "تفعيل/تعطيل وضع TUN", + "entryLightweightMode": "Entry Lightweight Mode", + "direct": "الوضع المباشر" + } + }, + "password": { + "prompts": { + "enterRoot": "يرجى إدخال كلمة مرور الرووت" + } + }, + "networkInterface": { + "title": "واجهة الشبكة", + "fields": { + "ipAddress": "عنوان IP", + "macAddress": "عنوان MAC" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "تم إعادة تشغيل نواة Clash", + "versionUpdated": "تم تحديث إصدار النواة", + "alreadyLatestVersion": "أنت تستخدم بالفعل أحدث إصدار من النواة", + "changeSuccess": "تم تغيير النواة بنجاح", + "changeFailed": "فشل تغيير النواة", + "geoDataUpdated": "تم تحديث البيانات الجغرافية" + }, + "clashService": { + "installSuccess": "تم تثبيت الخدمة بنجاح", + "uninstallSuccess": "تم إلغاء تثبيت الخدمة بنجاح" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "جاري تثبيت الخدمة...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/ar/shared.json b/src/locales/ar/shared.json new file mode 100644 index 000000000..604109371 --- /dev/null +++ b/src/locales/ar/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "إلغاء", + "close": "إغلاق", + "confirm": "تأكيد", + "save": "حفظ", + "delete": "حذف", + "edit": "تعديل", + "new": "جديد", + "enable": "تمكين", + "upgrade": "ترقية", + "restart": "إعادة التشغيل", + "resetToDefault": "إعادة تعيين إلى الافتراضي", + "refresh": "تحديث", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "عرض القائمة", + "tableView": "عرض الجدول", + "pause": "إيقاف مؤقت", + "resume": "استأنف", + "closeAll": "إغلاق الكل", + "clear": "مسح" + }, + "labels": { + "updateAt": "التحديث عند", + "timeout": "Timeout", + "icon": "أيقونة", + "name": "الاسم", + "readOnly": "للقراءة فقط", + "expireTime": "وقت الانتهاء", + "updateTime": "وقت التحديث", + "usedTotal": "المستخدم / الإجمالي", + "from": "من", + "password": "كلمة المرور", + "retryAttempts": "Retry attempts", + "downloaded": "تم التنزيل", + "uploaded": "تم الرفع" + }, + "statuses": { + "enabled": "ممكّن", + "disabled": "معطّل", + "saving": "Saving...", + "empty": "فارغ" + }, + "units": { + "milliseconds": "ميلي ثانية", + "seconds": "ثواني", + "minutes": "دقائق", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "شروط التصفية", + "matchCase": "مطابقة الحالة", + "matchWholeWord": "مطابقة الكلمة بأكملها", + "useRegex": "استخدام التعبيرات العادية" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "تكبير", + "minimize": "تصغير" + }, + "editorModes": { + "visualization": "تصور", + "advanced": "متقدم" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "تم استيراد الملف الشخصي بنجاح", + "importSubscriptionSuccess": "تم استيراد الاشتراك بنجاح", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "تم النسخ بنجاح", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "فشل التحقق من تكوين الاشتراك، يرجى فحص ملف التكوين، تم التراجع عن التغييرات، تفاصيل الخطأ:", + "bootFailed": "فشل التحقق من التكوين عند الإقلاع، تم استخدام التكوين الافتراضي، يرجى فحص ملف التكوين، تفاصيل الخطأ:", + "coreChangeFailed": "فشل التحقق من التكوين عند تغيير النواة، تم استخدام التكوين الافتراضي، يرجى فحص ملف التكوين، تفاصيل الخطأ:", + "processTerminated": "تم إنهاء عملية التحقق" + }, + "script": { + "syntaxError": "خطأ في بناء جملة السكريبت، تم التراجع عن التغييرات", + "missingMain": "خطأ في السكريبت، تم التراجع عن التغييرات", + "fileNotFound": "الملف غير موجود، تم التراجع عن التغييرات", + "fileError": "خطأ في ملف السكريبت، تم التراجع عن التغييرات" + }, + "yaml": { + "syntaxError": "YAML syntax error, changes reverted", + "readError": "YAML read error, changes reverted", + "mappingError": "YAML mapping error, changes reverted", + "keyError": "YAML key error, changes reverted", + "generalError": "YAML error, changes reverted" + }, + "merge": { + "syntaxError": "Merge file syntax error, changes reverted", + "mappingError": "Merge file mapping error, changes reverted", + "keyError": "Merge file key error, changes reverted", + "generalError": "Merge file error, changes reverted" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/ar/tests.json b/src/locales/ar/tests.json new file mode 100644 index 000000000..3f4d17072 --- /dev/null +++ b/src/locales/ar/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "اختبار الكل" + }, + "title": "اختبار" + }, + "components": { + "item": { + "actions": { + "test": "اختبار" + } + } + }, + "modals": { + "test": { + "title": { + "create": "إنشاء اختبار", + "edit": "تعديل الاختبار" + }, + "fields": { + "url": "رابط الاختبار" + } + } + }, + "statuses": { + "test": { + "pending": "Pending", + "yes": "Yes", + "no": "No", + "failed": "Failed", + "completed": "Completed", + "disallowedIsp": "Disallowed ISP", + "originalsOnly": "Originals Only", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Unsupported Country/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Testing..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "فشل الكشف لـ {{name}}", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Unlock Test" + } + } +} diff --git a/src/locales/de.json b/src/locales/de.json deleted file mode 100644 index 2c989cfce..000000000 --- a/src/locales/de.json +++ /dev/null @@ -1,563 +0,0 @@ -{ - "millis": "Millisekunden", - "seconds": "Sekunden", - "mins": "Minuten", - "Back": "Zurück", - "Close": "Schließen", - "Cancel": "Abbrechen", - "Confirm": "Bestätigen", - "Maximize": "Maximieren", - "Minimize": "Minimieren", - "Format document": "Dokument formatieren", - "Empty": "Leer", - "New": "Neu", - "Edit": "Bearbeiten", - "Save": "Speichern", - "Delete": "Löschen", - "Enable": "Aktivieren", - "Disable": "Deaktivieren", - "Label-Home": "Startseite", - "Label-Proxies": "Proxy", - "Label-Profiles": "Abonnement", - "Label-Connections": "Verbindungen", - "Label-Rules": "Regeln", - "Label-Logs": "Protokolle", - "Label-Unlock": "Testen", - "Label-Settings": "Einstellungen", - "Proxy Groups": "Proxy-Gruppen", - "Proxy Provider": "Proxy-Sammlung", - "Proxy Count": "Anzahl der Knoten", - "Update All": "Alle aktualisieren", - "Update At": "Aktualisiert am", - "rule": "Regel", - "global": "Global", - "direct": "Direktverbindung", - "Chain Proxy": "🔗 Ketten-Proxy", - "script": "Skript", - "locate": "Aktueller Knoten", - "Delay check": "Latenztest", - "Sort by default": "Standard Sortierung", - "Sort by delay": "Nach Latenz sortieren", - "Sort by name": "Nach Name sortieren", - "Delay check URL": "Latenztest-URL", - "Delay check to cancel fixed": "Latenztest durchführen, um Fixierung aufzuheben", - "Proxy basic": "Knotendetails ausblenden", - "Proxy detail": "Knotendetails anzeigen", - "Profiles": "Abonnement", - "Update All Profiles": "Alle Abonnements aktualisieren", - "View Runtime Config": "Laufzeit-Abonnement anzeigen", - "Reactivate Profiles": "Abonnement erneut aktivieren", - "Paste": "Einfügen", - "Profile URL": "Abonnement-Datei-Link", - "Import": "Importieren", - "From": "Von", - "Update Time": "Aktualisierungszeit", - "Used / Total": "Verwendet / Gesamt", - "Expire Time": "Ablaufzeit", - "Create Profile": "Neue Konfiguration erstellen", - "Edit Profile": "Konfiguration bearbeiten", - "Edit Proxies": "Knoten bearbeiten", - "Use newlines for multiple uri": "Für mehrere URI verwenden Sie Zeilenumbrüche (Base64-Codierung wird unterstützt)", - "Edit Rules": "Regeln bearbeiten", - "Rule Type": "Regeltyp", - "Rule Content": "Regelinhalt", - "Proxy Policy": "Proxy-Strategie", - "No Resolve": "DNS-Auflösung überspringen", - "Prepend Rule": "Vorherige Regel hinzufügen", - "Append Rule": "Nachfolgende Regel hinzufügen", - "Prepend Group": "Vorherige Proxy-Gruppe hinzufügen", - "Append Group": "Nachfolgende Proxy-Gruppe hinzufügen", - "Prepend Proxy": "Vorherigen Proxy-Knoten hinzufügen", - "Append Proxy": "Nachfolgenden Proxy-Knoten hinzufügen", - "Rule Condition Required": "Regelbedingung fehlt", - "Invalid Rule": "Ungültige Regel", - "Advanced": "Erweitert", - "Visualization": "Visualisierung", - "DOMAIN": "Vollständigen Domainnamen übereinstimmen", - "DOMAIN-SUFFIX": "Domain-Suffix übereinstimmen", - "DOMAIN-KEYWORD": "Domain-Schlüsselwort übereinstimmen", - "DOMAIN-REGEX": "Domain-Regulärer Ausdruck übereinstimmen", - "GEOSITE": "Domainnamen in Geosite übereinstimmen", - "GEOIP": "IP-Ländercode übereinstimmen", - "SRC-GEOIP": "Quell-IP-Ländercode übereinstimmen", - "IP-ASN": "IP-ASN übereinstimmen", - "SRC-IP-ASN": "Quell-IP-ASN übereinstimmen", - "IP-CIDR": "IP-Adressbereich übereinstimmen", - "IP-CIDR6": "IP-Adressbereich übereinstimmen", - "SRC-IP-CIDR": "Quell-IP-Adressbereich übereinstimmen", - "IP-SUFFIX": "IP-Suffix-Bereich übereinstimmen", - "SRC-IP-SUFFIX": "Quell-IP-Suffix-Bereich übereinstimmen", - "SRC-PORT": "Quellportbereich der Anfrage übereinstimmen", - "DST-PORT": "Zielportbereich der Anfrage übereinstimmen", - "IN-PORT": "Eingangsport übereinstimmen", - "DSCP": "DSCP-Markierung (nur für TPROXY UDP-Eingang)", - "PROCESS-NAME": "Prozessnamen übereinstimmen (Android-Paketname)", - "PROCESS-PATH": "Vollständigen Prozesspfad übereinstimmen", - "PROCESS-NAME-REGEX": "Regulärer Ausdruck für vollständigen Prozessnamen übereinstimmen (Android-Paketname)", - "PROCESS-PATH-REGEX": "Regulärer Ausdruck für vollständigen Prozesspfad übereinstimmen", - "NETWORK": "Übertragungsprotokoll übereinstimmen (TCP/UDP)", - "UID": "Linux-USER-ID übereinstimmen", - "IN-TYPE": "Eingangstyp übereinstimmen", - "IN-USER": "Eingangsbenutzername übereinstimmen", - "IN-NAME": "Eingangsname übereinstimmen", - "SUB-RULE": "Unterregel", - "RULE-SET": "Regelsatz übereinstimmen", - "AND": "Logisches UND", - "OR": "Logisches ODER", - "NOT": "Logisches NICHT", - "MATCH": "Alle Anfragen übereinstimmen", - "DIRECT": "Direktverbindung", - "REJECT": "Anfrage ablehnen", - "REJECT-DROP": "Anfrage verwerfen", - "PASS": "Diese Regel überspringen", - "Edit Groups": "Proxy-Gruppen bearbeiten", - "Group Type": "Proxy-Gruppentyp", - "select": "Proxy manuell auswählen", - "url-test": "Proxy basierend auf URL-Latenztest auswählen", - "fallback": "Bei Nichtverfügbarkeit zu einem anderen Proxy wechseln", - "load-balance": "Proxy basierend auf Lastverteilung zuweisen", - "relay": "Basierend auf definiertem Proxy-Kette weiterleiten", - "Group Name": "Proxy-Gruppenname", - "Use Proxies": "Proxy einführen", - "Use Provider": "Proxy-Sammlung einführen", - "Health Check Url": "URL für Gesundheitstest", - "Expected Status": "Erwarteter Statuscode", - "Interval": "Prüfintervall", - "Lazy": "Lazy-Status", - "Timeout": "Timeout", - "Max Failed Times": "Maximale Anzahl fehlgeschlagener Versuche", - "Interface Name": "Ausgangsschnittstelle", - "Routing Mark": "Routierungsmarkierung", - "Include All": "Alle Ausgangsproxy und Proxy-Sammlungen einführen", - "Include All Providers": "Alle Proxy-Sammlungen einführen", - "Include All Proxies": "Alle Ausgangsproxy einführen", - "Exclude Filter": "Knoten ausschließen", - "Exclude Type": "Typ der auszuschließenden Knoten", - "Disable UDP": "UDP deaktivieren", - "Hidden": "Proxy-Gruppe ausblenden", - "Group Name Required": "Der Proxy-Gruppenname darf nicht leer sein", - "Group Name Already Exists": "Der Proxy-Gruppenname existiert bereits", - "Extend Config": "Erweiterte Überdeckungskonfiguration", - "Extend Script": "Erweitertes Skript", - "Type": "Typ", - "Name": "Name", - "Descriptions": "Beschreibung", - "Subscription URL": "Abonnement-Link", - "Update Interval": "Aktualisierungsintervall", - "Choose File": "Datei auswählen", - "Use System Proxy": "Systemproxy zur Aktualisierung verwenden", - "Use Clash Proxy": "Kernel-Proxy zur Aktualisierung verwenden", - "Refresh": "Aktualisieren", - "Home": "Startseite", - "Select": "Verwenden", - "Edit Info": "Informationen bearbeiten", - "Edit File": "Datei bearbeiten", - "Open File": "Datei öffnen", - "Update": "Aktualisieren", - "Confirm deletion": "Löschung bestätigen", - "This operation is not reversible": "Diese Operation kann nicht rückgängig gemacht werden", - "Script Console": "Skript-Konsole-Ausgabe", - "Connections": "Verbindungen", - "Table View": "Tabellenansicht", - "List View": "Listenansicht", - "Close All": "Alle schließen", - "Upload": "Hochladen", - "Download": "Herunterladen", - "Download Speed": "Download-Geschwindigkeit", - "Upload Speed": "Upload-Geschwindigkeit", - "Host": "Host", - "Downloaded": "Heruntergeladen", - "Uploaded": "Hochgeladen", - "DL Speed": "Download-Geschwindigkeit", - "UL Speed": "Upload-Geschwindigkeit", - "Active Connections": "Aktive Verbindungen", - "Chains": "Ketten", - "Rule": "Regel", - "Process": "Prozess", - "Time": "Verbindungszeit", - "Source": "Quelladresse", - "Destination": "Zieladresse", - "DestinationPort": "Zielport", - "Close Connection": "Verbindung schließen", - "Rules": "Regeln", - "Rule Provider": "Regelsammlung", - "Logs": "Protokolle", - "Pause": "Pausieren", - "Resume": "Fortsetzen", - "Clear": "Löschen", - "Test": "Testen", - "Test All": "Alle testen", - "Testing...": "Wird getestet...", - "Create Test": "Neuen Test erstellen", - "Edit Test": "Test bearbeiten", - "Icon": "Symbol", - "Test URL": "Test-URL", - "Settings": "Einstellungen", - "System Setting": "Systemeinstellungen", - "Tun Mode": "Virtual Network Interface-Modus", - "Install Service": "Service installieren", - "Uninstall Service": "Dienst deinstallieren", - "Reset to Default": "Auf Standardwerte zurücksetzen", - "Tun Mode Info": "Der TUN-Modus (Virtual Network Interface) übernimmt den gesamten Systemverkehr. Wenn dieser Modus aktiviert ist, muss der Systemproxy nicht geöffnet werden.", - "TUN requires Service Mode or Admin Mode": "TUN-Modus erfordert Service-Modus oder Administrator-Modus", - "System Proxy Enabled": "Der Systemproxy ist aktiviert. Ihre Anwendungen werden über den Proxy auf das Netzwerk zugreifen.", - "System Proxy Disabled": "Der Systemproxy ist deaktiviert. Es wird empfohlen, diesen Eintrag für die meisten Benutzer zu aktivieren.", - "TUN Mode Enabled": "Der TUN-Modus ist aktiviert. Die Anwendungen werden über die virtuelle Netzwerkschnittstelle auf das Netzwerk zugreifen.", - "TUN Mode Disabled": "Der TUN-Modus ist deaktiviert. Dies ist für spezielle Anwendungen geeignet.", - "TUN Mode Service Required": "Der TUN-Modus erfordert den Service-Modus. Bitte installieren Sie zuerst den Service.", - "TUN Mode Intercept Info": "Der TUN-Modus kann den gesamten Anwendungsverkehr übernehmen und eignet sich für spezielle Anwendungen, die die Systemproxy-Einstellungen nicht befolgen.", - "Stack": "TUN-Modus-Stack", - "Device": "TUN-Netzwerkkartenname", - "Auto Route": "Globale Routing automatisch einstellen", - "Strict Route": "Strenges Routing", - "Auto Detect Interface": "Netzwerkschnittstelle automatisch auswählen", - "DNS Hijack": "DNS-Hijacking", - "MTU": "Maximale Übertragungseinheit", - "Service Mode": "Service-Modus", - "active": "Aktiviert", - "unknown": "Unbekannt", - "Install": "Installieren", - "Uninstall": "Deinstallieren", - "System Proxy": "Systemproxy", - "System Proxy Info": "Ändern Sie die Proxy-Einstellungen des Betriebssystems. Wenn die Aktivierung fehlschlägt, können Sie die Proxy-Einstellungen des Betriebssystems manuell ändern.", - "System Proxy Setting": "Systemproxy-Einstellungen", - "Current System Proxy": "Aktueller Systemproxy", - "Enable status": "Aktivierungsstatus: ", - "Enabled": "Aktiviert", - "Disabled": "Deaktiviert", - "Server Addr": "Serveradresse: ", - "Proxy Host": "Proxy-Host", - "Invalid Proxy Host Format": "Ungültiges Format für den Proxy-Host", - "Not available": "Nicht verfügbar", - "Proxy Guard": "Systemproxy-Schutz", - "Proxy Guard Info": "Aktivieren Sie diese Option, um zu verhindern, dass andere Software die Proxy-Einstellungen des Betriebssystems ändert.", - "Guard Duration": "Proxy-Schutz-Intervall", - "Always use Default Bypass": "Immer die Standard-Umgehung verwenden", - "Proxy Bypass": "Proxy-Umgehungseinstellungen: ", - "Bypass": "Aktuelle Umgehung: ", - "Use PAC Mode": "PAC-Modus verwenden", - "PAC Script Content": "PAC-Skriptinhalt", - "PAC URL": "PAC-Adresse: ", - "Auto Launch": "Beim Start automatisch starten", - "Administrator mode may not support auto launch": "Der Administrator-Modus unterstützt möglicherweise keine automatische Startfunktion.", - "Silent Start": "Stillstart", - "Silent Start Info": "Die Anwendung wird im Hintergrund gestartet, ohne dass das Programmfenster angezeigt wird.", - "TG Channel": "Telegram-Kanal", - "Manual": "Bedienungsanleitung", - "Github Repo": "GitHub-Projektadresse", - "Clash Setting": "Clash-Einstellungen", - "Allow Lan": "Netzwerkverbindung im lokalen Netzwerk zulassen", - "Network Interface": "Netzwerkschnittstelle", - "Ip Address": "IP-Adresse", - "Mac Address": "MAC-Adresse", - "IPv6": "IPv6", - "Unified Delay": "Einheitliche Latenz", - "Unified Delay Info": "Wenn die einheitliche Latenz aktiviert ist, werden zwei Latenztests durchgeführt, um die Latenzunterschiede zwischen verschiedenen Knotentypen aufgrund von Verbindungsaufbau und anderen Faktoren zu eliminieren.", - "Log Level": "Protokolliergrad", - "Log Level Info": "Dies wirkt sich nur auf die Kernprotokolldateien im Verzeichnis Service im Protokollverzeichnis aus.", - "Port Config": "Port-Konfiguration", - "Random Port": "Zufälliger Port", - "Mixed Port": "Mischter Proxy-Port", - "Socks Port": "SOCKS-Proxy-Port", - "Http Port": "HTTP(S)-Proxy-Port", - "Redir Port": "Redir-Transparenter Proxy-Port", - "Tproxy Port": "TPROXY-Transparenter Proxy-Port", - "External": "Externe Steuerung", - "External Controller": "Adresse des externen Controllers", - "Core Secret": "API-Zugangsschlüssel", - "Recommended": "Empfohlene Einstellung", - "Open URL": "Link öffnen", - "Replace host, port, secret with %host, %port, %secret": "Verwenden Sie %host, %port, %secret für Host, Port und Zugangsschlüssel", - "Support %host, %port, %secret": "Unterstützt %host, %port, %secret", - "Clash Core": "Clash-Kern", - "Upgrade": "Kern aktualisieren", - "Restart": "Kern neustarten", - "Release Version": "Stabile Version", - "Alpha Version": "Vorschauversion", - "Please enter your root password": "Bitte geben Sie Ihr Root-Passwort ein.", - "Open UWP tool": "UWP-Tool öffnen", - "Open UWP tool Info": "Ab Windows 8 wird die direkte Netzwerkverbindung von UWP-Anwendungen (z. B. Microsoft Store) zu lokalen Hosts eingeschränkt. Mit diesem Tool können Sie diese Einschränkung umgehen.", - "Update GeoData": "Geo-Daten aktualisieren", - "Verge Basic Setting": "Verge-Grundeinstellungen", - "Verge Advanced Setting": "Verge-Erweiterte Einstellungen", - "Language": "Spracheinstellungen", - "Theme Mode": "Thema", - "Tray Click Event": "Tray-Klickereignis", - "Show Main Window": "Hauptfenster anzeigen", - "Show Tray Menu": "Tray-Menü anzeigen", - "Copy Env Type": "Umgebungsvariablentyp kopieren", - "Copy Success": "Kopieren erfolgreich", - "Start Page": "Startseite", - "Startup Script": "Startskript", - "Browse": "Durchsuchen", - "Theme Setting": "Thema-Einstellungen", - "Primary Color": "Hauptfarbe", - "Secondary Color": "Sekundärfarbe", - "Primary Text": "Haupttextfarbe", - "Secondary Text": "Sekundärtextfarbe", - "Info Color": "Informationsfarbe", - "Warning Color": "Warnfarbe", - "Error Color": "Fehlerfarbe", - "Success Color": "Erfolgsfarbe", - "Font Family": "Schriftfamilie", - "CSS Injection": "CSS-Einbindung", - "Layout Setting": "Layout-Einstellungen", - "Traffic Graph": "Verkehrsdiagramm", - "Memory Usage": "Kern-Speichernutzung", - "Memory Cleanup": "Klicken Sie hier, um den Speicher zu bereinigen.", - "Proxy Group Icon": "Proxy-Gruppen-Symbol", - "Nav Icon": "Navigationsleiste-Symbol", - "Monochrome": "Monochromes Symbol", - "Colorful": "Farbiges Symbol", - "Tray Icon": "Tray-Symbol", - "Common Tray Icon": "Standard-Tray-Symbol", - "System Proxy Tray Icon": "Systemproxy-Tray-Symbol", - "Tun Tray Icon": "TUN-Modus-Tray-Symbol", - "Miscellaneous": "Sonstige Einstellungen", - "App Log Level": "Anwendungs-Protokolliergrad", - "Auto Close Connections": "Verbindungen automatisch schließen", - "Auto Close Connections Info": "Wenn der ausgewählte Knoten in der Proxy-Gruppe oder der Proxy-Modus geändert wird, werden die bestehenden Verbindungen geschlossen.", - "Auto Check Update": "Automatisch auf Updates prüfen", - "Enable Builtin Enhanced": "Eingebaute Verbesserungen aktivieren", - "Enable Builtin Enhanced Info": "Kompatibilitätsbehandlung der Konfigurationsdatei", - "Proxy Layout Columns": "Anzahl der Spalten im Proxy-Layout", - "Auto Columns": "Automatische Anzahl der Spalten", - "Auto Log Clean": "Protokolle automatisch bereinigen", - "Never Clean": "Nie bereinigen", - "Retain _n Days": "{{n}} Tage behalten", - "Auto Delay Detection": "Automatische Latenzprüfung", - "Auto Delay Detection Info": "Überprüft regelmäßig im Hintergrund die Latenz des aktuellen Knotens", - "Default Latency Test": "Standard-Testlink", - "Default Latency Test Info": "Dies wird nur für HTTP-Client-Anfragentests verwendet und hat keine Auswirkungen auf die Konfigurationsdatei.", - "Default Latency Timeout": "Test-Timeout", - "Hotkey Setting": "Tastenkombinationseinstellungen", - "Enable Global Hotkey": "Globale Tastenkombinationen aktivieren", - "open_or_close_dashboard": "Dashboard öffnen/schließen", - "clash_mode_rule": "Regel-Modus", - "clash_mode_global": "Globaler Modus", - "clash_mode_direct": "Direktverbindungs-Modus", - "toggle_system_proxy": "Systemproxy ein/ausschalten", - "toggle_tun_mode": "TUN-Modus ein/ausschalten", - "entry_lightweight_mode": "Leichtgewichtigen Modus betreten", - "Backup Setting": "Sicherungseinstellungen", - "Backup Setting Info": "Unterstützt die Sicherung von Konfigurationsdateien über WebDAV", - "Runtime Config": "Aktuelle Konfiguration", - "Open Conf Dir": "Konfigurationsverzeichnis", - "Open Conf Dir Info": "Wenn die Software fehlerhaft funktioniert, !sichern Sie! alle Dateien in diesem Verzeichnis, löschen Sie sie und starten Sie die Software neu.", - "Open Core Dir": "Kernverzeichnis", - "Open Logs Dir": "Protokollverzeichnis", - "Check for Updates": "Auf Updates prüfen", - "Go to Release Page": "Zur Veröffentlichungsseite gehen", - "Portable Updater Error": "Die portable Version unterstützt keine In-App-Aktualisierung. Bitte laden Sie die Dateien manuell herunter und ersetzen Sie sie.", - "Break Change Update Error": "Dies ist eine wichtige Aktualisierung. Die In-App-Aktualisierung wird nicht unterstützt. Bitte deinstallieren Sie die Software und laden Sie die neue Version manuell herunter und installieren Sie sie.", - "Open Dev Tools": "Entwicklertools öffnen", - "Export Diagnostic Info": "Diagnoseinformationen exportieren", - "Exit": "Beenden", - "Verge Version": "Verge-Version", - "ReadOnly": "Schreibgeschützt", - "ReadOnlyMessage": "Bearbeitung im schreibgeschützten Modus nicht möglich", - "Filter": "Knoten filtern", - "Filter conditions": "Filterbedingungen", - "Match Case": "Groß-/Kleinschreibung beachten", - "Match Whole Word": "Ganzes Wort übereinstimmen", - "Use Regular Expression": "Regulären Ausdruck verwenden", - "Profile Imported Successfully": "Abonnement erfolgreich importiert", - "Profile Switched": "Abonnement gewechselt", - "Profile Reactivated": "Abonnement erneut aktiviert", - "Only YAML Files Supported": "Nur YAML-Dateien werden unterstützt", - "Settings Applied": "Einstellungen angewendet", - "Stopping Core...": "Kern wird gestoppt...", - "Restarting Core...": "Kern wird neu gestartet...", - "Installing Service...": "Service wird installiert...", - "Uninstalling Service...": "Service wird deinstalliert...", - "Service Installed Successfully": "Service erfolgreich installiert", - "Service Uninstalled Successfully": "Service erfolgreich deinstalliert", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Das Intervall des Proxy-Daemons darf nicht weniger als 1 Sekunde betragen.", - "Invalid Bypass Format": "Ungültiges Format für die Proxy-Umgehung", - "Waiting for service to be ready...": "Auf Service-Bereitschaft gewartet...", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "Der Dienst war bereit, aber beim Neustart des Kerns könnten Probleme aufgetreten sein oder der Dienst ist möglicherweise nicht verfügbar. Bitte überprüfen Sie dies.", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "Bei der Dienstinstallation oder dem Neustart des Kerns sind Probleme aufgetreten. Der Dienst ist möglicherweise nicht verfügbar. Bitte prüfen Sie die Systemprotokolle.", - "Service is ready and core restarted": "Service ist bereit und Kern wurde neu gestartet", - "Core restarted. Service is now available.": "Kern wurde neu gestartet. Service ist jetzt verfügbar", - "Core Version Updated": "Kernversion wurde aktualisiert", - "Clash Core Restarted": "Clash-Kern wurde neu gestartet", - "GeoData Updated": "Geo-Daten wurden aktualisiert", - "Currently on the Latest Version": "Sie verwenden bereits die neueste Version", - "Import Subscription Successful": "Abonnement erfolgreich importiert", - "WebDAV Server URL": "WebDAV-Serveradresse http(s)://", - "Username": "Benutzername", - "Password": "Passwort", - "Backup": "Sichern", - "Filename": "Dateiname", - "Actions": "Aktionen", - "Restore": "Wiederherstellen", - "No Backups": "Keine Sicherungen vorhanden", - "WebDAV URL Required": "Die WebDAV-Serveradresse darf nicht leer sein", - "Invalid WebDAV URL": "Ungültiges Format für die WebDAV-Serveradresse", - "Username Required": "Der Benutzername darf nicht leer sein", - "Password Required": "Das Passwort darf nicht leer sein", - "WebDAV Config Saved": "WebDAV-Konfiguration erfolgreich gespeichert", - "WebDAV Config Save Failed": "Speichern der WebDAV-Konfiguration fehlgeschlagen: {{error}}", - "Backup Created": "Sicherung erfolgreich erstellt", - "Backup Failed": "Sicherung fehlgeschlagen: {{error}}", - "Delete Backup": "Sicherung löschen", - "Restore Backup": "Sicherung wiederherstellen", - "Backup Time": "Sicherungszeit", - "Restore Success, App will restart in 1s": "Wiederherstellung erfolgreich. Die App wird in 1 Sekunde neu starten.", - "Failed to fetch backup files": "Abrufen der Sicherungsdateien fehlgeschlagen", - "Profile": "Konfiguration", - "Web UI": "Web-Oberfläche", - "Dashboard": "Dashboard", - "Restart App": "App neu starten", - "Restart Clash Core": "Clash-Kern neu starten", - "TUN Mode": "TUN-Modus", - "Copy Env": "Umgebungsvariablen kopieren", - "Conf Dir": "Konfigurationsverzeichnis", - "Core Dir": "Kernverzeichnis", - "Logs Dir": "Protokollverzeichnis", - "Open Dir": "Verzeichnis öffnen", - "More": "Mehr", - "Rule Mode": "Rule Mode", - "Global Mode": "Global Mode", - "Direct Mode": "Direct Mode", - "Enable Tray Speed": "Tray-Geschwindigkeit aktivieren", - "Enable Tray Icon": "Tray-Symbol aktivieren", - "LightWeight Mode": "Leichtgewichtiger Modus", - "LightWeight Mode Info": "GUI-Oberfläche schließen, nur den Kern laufen lassen", - "LightWeight Mode Settings": "Einstellungen für den Leichtgewichtigen Modus", - "Enter LightWeight Mode Now": "Sofort in den Leichtgewichtigen Modus wechseln", - "Auto Enter LightWeight Mode": "Automatisch in den Leichtgewichtigen Modus wechseln", - "Auto Enter LightWeight Mode Info": "Wenn diese Option aktiviert ist, wird der Leichtgewichtige Modus automatisch aktiviert, nachdem das Fenster für eine bestimmte Zeit geschlossen wurde.", - "Auto Enter LightWeight Mode Delay": "Verzögerung beim automatischen Wechsel in den Leichtgewichtigen Modus", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "Nach dem Schließen des Fensters wird der Leichtgewichtige Modus automatisch nach {{n}} Minuten aktiviert.", - "Config Validation Failed": "Abonnement-Konfigurationsüberprüfung fehlgeschlagen. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Die Änderungen wurden rückgängig gemacht. Fehlerdetails: ", - "Boot Config Validation Failed": "Start-Abonnement-Konfigurationsüberprüfung fehlgeschlagen. Die Standardkonfiguration wurde verwendet, um die App zu starten. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Fehlerdetails: ", - "Core Change Config Validation Failed": "Konfigurationsüberprüfung beim Wechsel des Kerns fehlgeschlagen. Die Standardkonfiguration wurde verwendet, um die App zu starten. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Fehlerdetails: ", - "Config Validation Process Terminated": "Validierungsprozess abgebrochen", - "Script Syntax Error": "Skript-Syntaxfehler. Die Änderungen wurden rückgängig gemacht.", - "Script Missing Main": "Skriptfehler. Die Änderungen wurden rückgängig gemacht.", - "File Not Found": "Datei nicht gefunden. Die Änderungen wurden rückgängig gemacht.", - "Script File Error": "Skript-Dateifehler. Die Änderungen wurden rückgängig gemacht.", - "Core Changed Successfully": "Kern erfolgreich gewechselt", - "Failed to Change Core": "Kernwechsel fehlgeschlagen", - "YAML Syntax Error": "YAML-Syntaxfehler. Die Änderungen wurden rückgängig gemacht.", - "YAML Read Error": "YAML-Lesefehler. Die Änderungen wurden rückgängig gemacht.", - "YAML Mapping Error": "YAML-Mappingfehler. Die Änderungen wurden rückgängig gemacht.", - "YAML Key Error": "YAML-Schlüsselfehler. Die Änderungen wurden rückgängig gemacht.", - "YAML Error": "YAML-Fehler. Die Änderungen wurden rückgängig gemacht.", - "Merge File Syntax Error": "Syntaxfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", - "Merge File Mapping Error": "Mappingfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", - "Merge File Key Error": "Schlüsselfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", - "Merge File Error": "Fehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", - "Service Administrator Prompt": "Clash Verge benötigt Administratorrechte, um den Systemdienst zu installieren.", - "DNS Settings": "DNS-Einstellungen", - "DNS settings saved": "DNS-Einstellungen wurden gespeichert", - "DNS Overwrite": "DNS-Überschreibung", - "DNS Settings Warning": "Wenn Sie sich nicht mit diesen Einstellungen auskennen, ändern Sie sie nicht und lassen Sie die DNS-Überschreibung aktiviert.", - "Enable DNS": "DNS aktivieren", - "DNS Listen": "DNS-Lauschangabe", - "Enhanced Mode": "Erweiterter Modus", - "Fake IP Range": "Fake-IP-Bereich", - "Fake IP Filter Mode": "Fake-IP-Filtermodus", - "Enable IPv6 DNS resolution": "IPv6-DNS-Auflösung aktivieren", - "Prefer H3": "HTTP/3 bevorzugen", - "DNS DOH使用HTTP/3": "DNS DOH verwendet HTTP/3-Protokoll", - "Respect Rules": "Routierungsregeln beachten", - "DNS connections follow routing rules": "DNS-Verbindungen folgen den Routierungsregeln", - "Use Hosts": "Hosts verwenden", - "Enable to resolve hosts through hosts file": "Aktivieren Sie die Auflösung von Hosts über die hosts-Datei", - "Use System Hosts": "System-Hosts verwenden", - "Enable to resolve hosts through system hosts file": "Aktivieren Sie die Auflösung von Hosts über die System-hosts-Datei", - "Direct Nameserver Follow Policy": "Direkte Namenserver folgen der Strategie", - "Whether to follow nameserver policy": "Ob die Namenserver-Strategie befolgt werden soll", - "Default Nameserver": "Standard-Namenserver", - "Default DNS servers used to resolve DNS servers": "Standard-DNS-Server, die zum Auflösen von DNS-Servern verwendet werden", - "Nameserver": "Namenserver", - "List of DNS servers": "Liste der DNS-Server, getrennt durch Kommas", - "Fallback": "Rückfallserver", - "List of fallback DNS servers": "Liste der Rückfall-DNS-Server, getrennt durch Kommas", - "Proxy Server Nameserver": "Proxy-Server-Namenserver", - "Proxy Node Nameserver": "Proxy-Knoten-Namenserver, nur für die Auflösung der Domains von Proxy-Knoten verwendet, getrennt durch Kommas", - "Direct Nameserver": "Direkter Namenserver", - "Direct outbound Nameserver": "Direkter Ausgangs-Namenserver, unterstützt das Schlüsselwort system, getrennt durch Kommas", - "Fake IP Filter": "Fake-IP-Filter", - "Domains that skip fake IP resolution": "Domains, die die Fake-IP-Auflösung überspringen, getrennt durch Kommas", - "Nameserver Policy": "Namenserver-Strategie", - "Domain-specific DNS server": "Domain-spezifischer DNS-Server, mehrere Server getrennt durch Semikolons, Format: domain=server1;server2", - "Fallback Filter Settings": "Rückfallfilter-Einstellungen", - "GeoIP Filtering": "GeoIP-Filterung", - "Enable GeoIP filtering for fallback": "GeoIP-Rückfallfilterung aktivieren", - "GeoIP Code": "GeoIP-Ländercode", - "Fallback IP CIDR": "Rückfall-IP-CIDR", - "IP CIDRs not using fallback servers": "IP-CIDRs, die keine Rückfallserver verwenden, getrennt durch Kommas", - "Fallback Domain": "Rückfall-Domäne", - "Domains using fallback servers": "Domains, die Rückfallserver verwenden, getrennt durch Kommas", - "Hosts Settings": "Hosts-Einstellungen", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "Benutzerdefinierte Zuordnung von Domains zu IPs oder Domains, getrennt durch Kommas", - "Home Settings": "Startseite-Einstellungen", - "Profile Card": "Abonnement-Karte", - "Current Proxy Card": "Aktueller Proxy-Karte", - "Network Settings Card": "Netzwerkeinstellungen-Karte", - "Proxy Mode Card": "Proxy-Modus-Karte", - "Traffic Stats Card": "Verkehrsstatistik-Karte", - "Clash Info Cards": "Clash-Informationen-Karten", - "System Info Cards": "Systeminformationen-Karten", - "Website Tests Card": "Website-Tests-Karte", - "Traffic Stats": "Verkehrsstatistik", - "Website Tests": "Website-Tests", - "Clash Info": "Clash-Informationen", - "Core Version": "Kernversion", - "System Proxy Address": "Systemproxy-Adresse", - "Uptime": "Laufzeit", - "Rules Count": "Anzahl der Regeln", - "System Info": "Systeminformationen", - "OS Info": "Betriebssysteminformationen", - "Running Mode": "Betriebsmodus", - "Sidecar Mode": "Benutzermodus", - "Administrator Mode": "Administrator-Modus", - "Last Check Update": "Letzte Aktualitätsprüfung", - "Click to import subscription": "Klicken Sie hier, um ein Abonnement zu importieren.", - "Last Update failed": "Letzte Aktualisierung fehlgeschlagen", - "Next Up": "Nächste Aktualisierung", - "No schedule": "Kein Zeitplan", - "Unknown": "Unbekannt", - "Auto update disabled": "Automatische Aktualisierung deaktiviert", - "Update subscription successfully": "Abonnement erfolgreich aktualisiert", - "Update with Clash proxy successfully": "Aktualisierung mit Clash-Proxy erfolgreich", - "Update failed even with Clash proxy": "Aktualisierung auch mit Clash-Proxy fehlgeschlagen", - "Profile creation failed, retrying with Clash proxy...": "Erstellung des Abonnements fehlgeschlagen. Versuche es mit dem Clash-Proxy erneut...", - "Profile creation succeeded with Clash proxy": "Erstellung des Abonnements mit Clash-Proxy erfolgreich", - "Import failed, retrying with Clash proxy...": "Import des Abonnements fehlgeschlagen. Versuche es mit dem Clash-Proxy erneut...", - "Profile Imported with Clash proxy": "Abonnement mit Clash-Proxy importiert", - "Import failed even with Clash proxy": "Import des Abonnements auch mit Clash-Proxy fehlgeschlagen", - "Current Node": "Aktueller Knoten", - "No active proxy node": "Kein aktiver Proxy-Knoten", - "Network Settings": "Netzwerkeinstellungen", - "Proxy Mode": "Proxy-Modus", - "Group": "Proxy-Gruppe", - "Proxy": "Knoten", - "IP Information Card": "IP-Informationen-Karte", - "IP Information": "IP-Informationen", - "Failed to get IP info": "Abrufen der IP-Informationen fehlgeschlagen", - "ISP": "Internetdienstanbieter", - "ASN": "Autonomes Systemnummer", - "ORG": "Organisation", - "Location": "Standort", - "Timezone": "Zeitzone", - "Auto refresh": "Automatische Aktualisierung", - "Unlock Test": "Entsperrungstest", - "Pending": "Wartend auf Prüfung", - "Yes": "Unterstützt", - "No": "Nicht unterstützt", - "Failed": "Test fehlgeschlagen", - "Completed": "Prüfung abgeschlossen", - "Disallowed ISP": "Nicht zugelassener Internetdienstanbieter", - "Originals Only": "Nur Original", - "Unsupported Country/Region": "Nicht unterstütztes Land/Region", - "Configuration saved successfully": "Zufalls-Konfiguration erfolgreich gespeichert", - "Controller address copied to clipboard": "API-Port in die Zwischenablage kopiert", - "Secret copied to clipboard": "API-Schlüssel in die Zwischenablage kopiert", - "Copy to clipboard": "Klicken Sie hier, um zu kopieren", - "Enable one-click random API port and key. Click to randomize the port and key": "Einstellsichere Zufalls-API-Port- und Schlüsselgenerierung aktivieren. Klicken Sie, um Port und Schlüssel zu randomisieren" -} diff --git a/src/locales/de/connections.json b/src/locales/de/connections.json new file mode 100644 index 000000000..97af29ee3 --- /dev/null +++ b/src/locales/de/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Verbindungen" + }, + "components": { + "fields": { + "host": "Host", + "dlSpeed": "Download-Geschwindigkeit", + "ulSpeed": "Upload-Geschwindigkeit", + "chains": "Ketten", + "rule": "Regel", + "process": "Prozess", + "time": "Verbindungszeit", + "source": "Quelladresse", + "destination": "Zieladresse", + "destinationPort": "Zielport", + "type": "Typ" + }, + "order": { + "default": "Default", + "uploadSpeed": "Upload-Geschwindigkeit", + "downloadSpeed": "Download-Geschwindigkeit" + }, + "actions": { + "closeConnection": "Verbindung schließen" + } + } +} diff --git a/src/locales/de/home.json b/src/locales/de/home.json new file mode 100644 index 000000000..f657ae90f --- /dev/null +++ b/src/locales/de/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Leichtgewichtiger Modus", + "manual": "Bedienungsanleitung", + "settings": "Startseite-Einstellungen" + }, + "cards": { + "trafficStats": "Verkehrsstatistik", + "networkSettings": "Netzwerkeinstellungen", + "proxyMode": "Proxy-Modus" + }, + "settings": { + "cards": { + "profile": "Abonnement-Karte", + "currentProxy": "Aktueller Proxy-Karte", + "network": "Netzwerkeinstellungen-Karte", + "proxyMode": "Proxy-Modus-Karte", + "traffic": "Verkehrsstatistik-Karte", + "tests": "Website-Tests-Karte", + "ip": "IP-Informationen-Karte", + "clashInfo": "Clash-Informationen-Karten", + "systemInfo": "Systeminformationen-Karten" + }, + "title": "Startseite-Einstellungen" + }, + "title": "Startseite" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "Der Systemproxy ist aktiviert. Ihre Anwendungen werden über den Proxy auf das Netzwerk zugreifen.", + "systemProxyDisabled": "Der Systemproxy ist deaktiviert. Es wird empfohlen, diesen Eintrag für die meisten Benutzer zu aktivieren.", + "tunModeServiceRequired": "Der TUN-Modus erfordert den Service-Modus. Bitte installieren Sie zuerst den Service.", + "tunModeEnabled": "Der TUN-Modus ist aktiviert. Die Anwendungen werden über die virtuelle Netzwerkschnittstelle auf das Netzwerk zugreifen.", + "tunModeDisabled": "Der TUN-Modus ist deaktiviert. Dies ist für spezielle Anwendungen geeignet." + }, + "tooltips": { + "systemProxy": "Ändern Sie die Proxy-Einstellungen des Betriebssystems. Wenn die Aktivierung fehlschlägt, können Sie die Proxy-Einstellungen des Betriebssystems manuell ändern.", + "tunMode": "Der TUN-Modus kann den gesamten Anwendungsverkehr übernehmen und eignet sich für spezielle Anwendungen, die die Systemproxy-Einstellungen nicht befolgen." + } + }, + "clashInfo": { + "title": "Clash-Informationen", + "fields": { + "coreVersion": "Kernversion", + "systemProxyAddress": "Systemproxy-Adresse", + "mixedPort": "Mixed Port", + "uptime": "Laufzeit", + "rulesCount": "Anzahl der Regeln" + } + }, + "systemInfo": { + "title": "Systeminformationen", + "fields": { + "osInfo": "Betriebssysteminformationen", + "autoLaunch": "Beim Start automatisch starten", + "runningMode": "Betriebsmodus", + "lastCheckUpdate": "Letzte Aktualitätsprüfung", + "vergeVersion": "Verge-Version" + }, + "actions": { + "settings": "Einstellungen" + }, + "tooltips": { + "autoLaunchAdmin": "Der Administrator-Modus unterstützt möglicherweise keine automatische Startfunktion." + }, + "badges": { + "adminMode": "Administrator-Modus", + "serviceMode": "Service-Modus", + "sidecarMode": "Benutzermodus", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP-Informationen", + "labels": { + "ip": "IP", + "asn": "Autonomes Systemnummer", + "isp": "Internetdienstanbieter", + "org": "Organisation", + "location": "Standort", + "timezone": "Zeitzone", + "autoRefresh": "Automatische Aktualisierung", + "unknown": "Unbekannt" + }, + "errors": { + "load": "IP-Informationen konnten nicht abgerufen werden" + } + }, + "currentProxy": { + "title": "Aktueller Knoten", + "actions": { + "refreshDelay": "Latenztest" + }, + "labels": { + "globalMode": "Global Mode", + "directMode": "Direct Mode", + "group": "Proxy-Gruppe", + "proxy": "Knoten", + "noActiveNode": "Kein aktiver Proxy-Knoten" + } + }, + "tests": { + "title": "Website-Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Upload-Geschwindigkeit", + "downloadSpeed": "Download-Geschwindigkeit", + "activeConnections": "Aktive Verbindungen", + "memoryUsage": "Kern-Speichernutzung" + }, + "legends": { + "upload": "Hochladen", + "download": "Herunterladen" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Regel-Modus", + "global": "Globaler Modus", + "direct": "Direktverbindungs-Modus" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/de/index.ts b/src/locales/de/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/de/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/de/layout.json b/src/locales/de/layout.json new file mode 100644 index 000000000..b3026730c --- /dev/null +++ b/src/locales/de/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Startseite", + "proxies": "Proxy", + "profiles": "Abonnement", + "connections": "Verbindungen", + "rules": "Regeln", + "logs": "Protokolle", + "unlock": "Testen", + "settings": "Einstellungen" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/de/logs.json b/src/locales/de/logs.json new file mode 100644 index 000000000..aec2ccf02 --- /dev/null +++ b/src/locales/de/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Protokolle" + } +} diff --git a/src/locales/de/profiles.json b/src/locales/de/profiles.json new file mode 100644 index 000000000..1628bb116 --- /dev/null +++ b/src/locales/de/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Alle Abonnements aktualisieren", + "viewRuntimeConfig": "Laufzeit-Abonnement anzeigen", + "reactivate": "Abonnement erneut aktivieren", + "import": "Importieren" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "Abonnement-Datei-Link", + "actions": { + "paste": "Einfügen" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Nur YAML-Dateien werden unterstützt" + }, + "notifications": { + "importRetry": "Import des Abonnements fehlgeschlagen. Versuche es mit dem Clash-Proxy erneut...", + "importFail": "Import des Abonnements auch mit Clash-Proxy fehlgeschlagen", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Abonnement gewechselt", + "profileReactivated": "Abonnement erneut aktiviert", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Abonnement" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Klicken Sie hier, um ein Abonnement zu importieren." + } + }, + "fileInput": { + "chooseFile": "Datei auswählen" + }, + "menu": { + "home": "Startseite", + "select": "Verwenden", + "editInfo": "Informationen bearbeiten", + "editFile": "Datei bearbeiten", + "editRules": "Regeln bearbeiten", + "editProxies": "Knoten bearbeiten", + "editGroups": "Proxy-Gruppen bearbeiten", + "extendConfig": "Erweiterte Überdeckungskonfiguration", + "extendScript": "Erweitertes Skript", + "openFile": "Datei öffnen", + "update": "Aktualisieren", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Letzte Aktualisierung fehlgeschlagen", + "nextUp": "Nächste Aktualisierung", + "noSchedule": "Kein Zeitplan", + "unknown": "Unbekannt", + "autoUpdateDisabled": "Automatische Aktualisierung deaktiviert" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Neue Konfiguration erstellen", + "edit": "Konfiguration bearbeiten" + }, + "fields": { + "type": "Typ", + "description": "Beschreibung", + "subscriptionUrl": "Abonnement-Link", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Aktualisierungsintervall", + "useSystemProxy": "Systemproxy zur Aktualisierung verwenden", + "useClashProxy": "Kernel-Proxy zur Aktualisierung verwenden", + "acceptInvalidCerts": "Allows Invalid Certificates (Danger)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Erstellung des Abonnements fehlgeschlagen. Versuche es mit dem Clash-Proxy erneut...", + "creationSuccess": "Erstellung des Abonnements mit Clash-Proxy erfolgreich" + } + } + }, + "proxiesEditor": { + "title": "Knoten bearbeiten", + "placeholders": { + "multiUri": "Für mehrere URI verwenden Sie Zeilenumbrüche (Base64-Codierung wird unterstützt)" + }, + "actions": { + "prepend": "Vorherigen Proxy-Knoten hinzufügen", + "append": "Nachfolgenden Proxy-Knoten hinzufügen" + } + }, + "groupsEditor": { + "title": "Proxy-Gruppen bearbeiten", + "errors": { + "nameRequired": "Der Proxy-Gruppenname darf nicht leer sein", + "nameExists": "Der Proxy-Gruppenname existiert bereits" + }, + "fields": { + "type": "Proxy-Gruppentyp", + "name": "Proxy-Gruppenname", + "icon": "Proxy-Gruppen-Symbol", + "proxies": "Proxy einführen", + "provider": "Proxy-Sammlung einführen", + "healthCheckUrl": "URL für Gesundheitstest", + "expectedStatus": "Erwarteter Statuscode", + "interval": "Prüfintervall", + "maxFailedTimes": "Maximale Anzahl fehlgeschlagener Versuche", + "interfaceName": "Ausgangsschnittstelle", + "routingMark": "Routierungsmarkierung", + "filter": "Knoten filtern", + "excludeFilter": "Knoten ausschließen", + "excludeType": "Typ der auszuschließenden Knoten", + "includeAll": "Alle Ausgangsproxy und Proxy-Sammlungen einführen", + "includeAllProxies": "Alle Ausgangsproxy einführen", + "includeAllProviders": "Alle Proxy-Sammlungen einführen" + }, + "toggles": { + "lazy": "Lazy-Status", + "disableUdp": "UDP deaktivieren", + "hidden": "Proxy-Gruppe ausblenden" + }, + "actions": { + "prepend": "Vorherige Proxy-Gruppe hinzufügen", + "append": "Nachfolgende Proxy-Gruppe hinzufügen" + } + }, + "editor": { + "actions": { + "format": "Dokument formatieren" + }, + "messages": { + "readOnly": "Bearbeitung im schreibgeschützten Modus nicht möglich" + } + }, + "confirmDelete": { + "title": "Löschung bestätigen", + "message": "Diese Operation kann nicht rückgängig gemacht werden" + }, + "logViewer": { + "title": "Skript-Konsole-Ausgabe" + } + } +} diff --git a/src/locales/de/proxies.json b/src/locales/de/proxies.json new file mode 100644 index 000000000..022f60302 --- /dev/null +++ b/src/locales/de/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Ketten-Proxy", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Proxy-Sammlung", + "actions": { + "updateAll": "Alle aktualisieren", + "update": "Aktualisieren" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Anzahl der Knoten", + "delayCheckReset": "Latenztest durchführen, um Fixierung aufzuheben" + }, + "tooltips": { + "locate": "Aktueller Knoten", + "delayCheck": "Latenztest", + "sortDefault": "Standard Sortierung", + "sortDelay": "Nach Latenz sortieren", + "sortName": "Nach Name sortieren", + "delayCheckUrl": "Latenztest-URL", + "showBasic": "Knotendetails ausblenden", + "showDetail": "Knotendetails anzeigen", + "filter": "Knoten filtern" + }, + "placeholders": { + "delayCheckUrl": "Latenztest-URL" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Direktverbindungs-Modus" + }, + "title": { + "default": "Proxy-Gruppen", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Proxy manuell auswählen", + "url-test": "Proxy basierend auf URL-Latenztest auswählen", + "fallback": "Bei Nichtverfügbarkeit zu einem anderen Proxy wechseln", + "load-balance": "Proxy basierend auf Lastverteilung zuweisen", + "relay": "Basierend auf definiertem Proxy-Kette weiterleiten" + }, + "policies": { + "DIRECT": "Direktverbindung", + "REJECT": "Anfrage ablehnen", + "REJECT-DROP": "Anfrage verwerfen", + "PASS": "Diese Regel überspringen" + } + } + } +} diff --git a/src/locales/de/rules.json b/src/locales/de/rules.json new file mode 100644 index 000000000..71b4d2628 --- /dev/null +++ b/src/locales/de/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Regelsammlung", + "dialogTitle": "Regelsammlung", + "actions": { + "updateAll": "Alle aktualisieren", + "update": "Aktualisieren" + } + }, + "title": "Regeln" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Regeltyp", + "content": "Regelinhalt", + "proxyPolicy": "Proxy-Strategie" + }, + "toggles": { + "noResolve": "DNS-Auflösung überspringen" + }, + "actions": { + "prependRule": "Vorherige Regel hinzufügen", + "appendRule": "Nachfolgende Regel hinzufügen" + }, + "validation": { + "conditionRequired": "Regelbedingung fehlt", + "invalidRule": "Ungültige Regel" + } + }, + "ruleTypes": { + "DOMAIN": "Vollständigen Domainnamen übereinstimmen", + "DOMAIN-SUFFIX": "Domain-Suffix übereinstimmen", + "DOMAIN-KEYWORD": "Domain-Schlüsselwort übereinstimmen", + "DOMAIN-REGEX": "Domain-Regulärer Ausdruck übereinstimmen", + "GEOSITE": "Domainnamen in Geosite übereinstimmen", + "GEOIP": "IP-Ländercode übereinstimmen", + "SRC-GEOIP": "Quell-IP-Ländercode übereinstimmen", + "IP-ASN": "IP-ASN übereinstimmen", + "SRC-IP-ASN": "Quell-IP-ASN übereinstimmen", + "IP-CIDR": "IP-Adressbereich übereinstimmen", + "IP-CIDR6": "IP-Adressbereich übereinstimmen", + "SRC-IP-CIDR": "Quell-IP-Adressbereich übereinstimmen", + "IP-SUFFIX": "IP-Suffix-Bereich übereinstimmen", + "SRC-IP-SUFFIX": "Quell-IP-Suffix-Bereich übereinstimmen", + "SRC-PORT": "Quellportbereich der Anfrage übereinstimmen", + "DST-PORT": "Zielportbereich der Anfrage übereinstimmen", + "IN-PORT": "Eingangsport übereinstimmen", + "DSCP": "DSCP-Markierung (nur für TPROXY UDP-Eingang)", + "PROCESS-NAME": "Prozessnamen übereinstimmen (Android-Paketname)", + "PROCESS-PATH": "Vollständigen Prozesspfad übereinstimmen", + "PROCESS-NAME-REGEX": "Regulärer Ausdruck für vollständigen Prozessnamen übereinstimmen (Android-Paketname)", + "PROCESS-PATH-REGEX": "Regulärer Ausdruck für vollständigen Prozesspfad übereinstimmen", + "NETWORK": "Übertragungsprotokoll übereinstimmen (TCP/UDP)", + "UID": "Linux-USER-ID übereinstimmen", + "IN-TYPE": "Eingangstyp übereinstimmen", + "IN-USER": "Eingangsbenutzername übereinstimmen", + "IN-NAME": "Eingangsname übereinstimmen", + "SUB-RULE": "Unterregel", + "RULE-SET": "Regelsatz übereinstimmen", + "AND": "Logisches UND", + "OR": "Logisches ODER", + "NOT": "Logisches NICHT", + "MATCH": "Alle Anfragen übereinstimmen" + }, + "title": "Regeln bearbeiten" + } + } +} diff --git a/src/locales/de/settings.json b/src/locales/de/settings.json new file mode 100644 index 000000000..29a3cc39b --- /dev/null +++ b/src/locales/de/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Bedienungsanleitung", + "telegram": "Telegram-Kanal", + "github": "GitHub-Projektadresse" + }, + "title": "Einstellungen" + }, + "sections": { + "system": { + "title": "Systemeinstellungen", + "toggles": { + "tunMode": "Virtual Network Interface-Modus", + "systemProxy": "Systemproxy" + }, + "tooltips": { + "autoLaunchAdmin": "Der Administrator-Modus unterstützt möglicherweise keine automatische Startfunktion.", + "silentStart": "Die Anwendung wird im Hintergrund gestartet, ohne dass das Programmfenster angezeigt wird." + }, + "fields": { + "autoLaunch": "Automatischer Start", + "silentStart": "Leiser Start" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Ändern Sie die Proxy-Einstellungen des Betriebssystems. Wenn die Aktivierung fehlschlägt, können Sie die Proxy-Einstellungen des Betriebssystems manuell ändern.", + "tunMode": "Der TUN-Modus (Virtual Network Interface) übernimmt den gesamten Systemverkehr. Wenn dieser Modus aktiviert ist, muss der Systemproxy nicht geöffnet werden.", + "tunUnavailable": "TUN-Modus erfordert Service-Modus oder Administrator-Modus" + }, + "actions": { + "installService": "Service installieren", + "uninstallService": "Dienst deinstallieren" + }, + "fields": { + "systemProxy": "Systemproxy", + "tunMode": "Virtual Network Interface-Modus" + } + }, + "externalController": { + "title": "Adresse des externen Controllers", + "fields": { + "enable": "Enable External Controller", + "address": "Adresse des externen Controllers", + "secret": "API-Zugangsschlüssel" + }, + "placeholders": { + "address": "Erforderlich", + "secret": "Empfohlene Einstellung" + }, + "tooltips": { + "copy": "In die Zwischenablage kopieren" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Kopieren fehlgeschlagen", + "controllerCopied": "API-Port in die Zwischenablage kopiert", + "secretCopied": "API-Schlüssel in die Zwischenablage kopiert" + } + }, + "externalCors": { + "title": "Externe CORS-Konfiguration", + "fields": { + "allowPrivateNetwork": "Zugriff auf privates Netzwerk erlauben", + "allowedOrigins": "Erlaubte Ursprünge" + }, + "placeholders": { + "origin": "Bitte eine gültige URL eingeben" + }, + "actions": { + "add": "Hinzufügen" + }, + "messages": { + "alwaysIncluded": "Immer enthaltene Ursprünge: {{urls}}" + }, + "tooltips": { + "open": "Einstellungen für externe CORS" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Clash-Einstellungen", + "form": { + "fields": { + "allowLan": "Netzwerkverbindung im lokalen Netzwerk zulassen", + "dnsOverwrite": "DNS-Überschreibung", + "ipv6": "IPv6", + "unifiedDelay": "Einheitliche Latenz", + "logLevel": "Protokolliergrad", + "portConfig": "Port-Konfiguration", + "external": "Externe Steuerung", + "webUI": "Web-Oberfläche", + "clashCore": "Clash-Kern", + "openUwpTool": "UWP-Tool öffnen", + "updateGeoData": "Geo-Daten aktualisieren" + }, + "tooltips": { + "networkInterface": "Netzwerkschnittstelle", + "unifiedDelay": "Wenn die einheitliche Latenz aktiviert ist, werden zwei Latenztests durchgeführt, um die Latenzunterschiede zwischen verschiedenen Knotentypen aufgrund von Verbindungsaufbau und anderen Faktoren zu eliminieren.", + "logLevel": "Dies wirkt sich nur auf die Kernprotokolldateien im Verzeichnis Service im Protokollverzeichnis aus.", + "openUwpTool": "Ab Windows 8 wird die direkte Netzwerkverbindung von UWP-Anwendungen (z. B. Microsoft Store) zu lokalen Hosts eingeschränkt. Mit diesem Tool können Sie diese Einschränkung umgehen." + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge-Grundeinstellungen", + "actions": { + "browse": "Durchsuchen" + }, + "trayOptions": { + "showMainWindow": "Hauptfenster anzeigen", + "showTrayMenu": "Tray-Menü anzeigen", + "disable": "Deaktivieren" + }, + "fields": { + "language": "Spracheinstellungen", + "themeMode": "Thema", + "trayClickEvent": "Tray-Klickereignis", + "copyEnvType": "Umgebungsvariablentyp kopieren", + "startPage": "Startseite", + "startupScript": "Startskript", + "themeSetting": "Thema-Einstellungen", + "layoutSetting": "Layout-Einstellungen", + "misc": "Sonstige Einstellungen", + "hotkeySetting": "Tastenkombinationseinstellungen" + } + }, + "advanced": { + "title": "Verge-Erweiterte Einstellungen", + "tooltips": { + "backupInfo": "Unterstützt die Sicherung von Konfigurationsdateien über WebDAV", + "openConfDir": "Wenn die Software fehlerhaft funktioniert, !sichern Sie! alle Dateien in diesem Verzeichnis, löschen Sie sie und starten Sie die Software neu.", + "liteMode": "GUI-Oberfläche schließen, nur den Kern laufen lassen" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Sie verwenden bereits die neueste Version", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Sicherungseinstellungen", + "runtimeConfig": "Aktuelle Konfiguration", + "openConfDir": "Konfigurationsverzeichnis", + "openCoreDir": "Kernverzeichnis", + "openLogsDir": "Protokollverzeichnis", + "checkUpdates": "Auf Updates prüfen", + "openDevTools": "Entwicklertools öffnen", + "liteModeSettings": "Einstellungen für den Leichtgewichtigen Modus", + "exit": "Beenden", + "exportDiagnostics": "Diagnoseinformationen exportieren", + "vergeVersion": "Verge-Version" + } + }, + "theme": { + "title": "Thema-Einstellungen", + "fields": { + "primaryColor": "Hauptfarbe", + "secondaryColor": "Sekundärfarbe", + "primaryText": "Haupttextfarbe", + "secondaryText": "Sekundärtextfarbe", + "infoColor": "Informationsfarbe", + "warningColor": "Warnfarbe", + "errorColor": "Fehlerfarbe", + "successColor": "Erfolgsfarbe", + "fontFamily": "Schriftfamilie", + "cssInjection": "CSS-Einbindung" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Layout-Einstellungen", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Verkehrsdiagramm", + "memoryUsage": "Kern-Speichernutzung", + "proxyGroupIcon": "Proxy-Gruppen-Symbol", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Navigationsleiste-Symbol", + "trayIcon": "Tray-Symbol", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Standard-Tray-Symbol", + "systemProxyTrayIcon": "Systemproxy-Tray-Symbol", + "tunTrayIcon": "TUN-Modus-Tray-Symbol", + "enableTrayIcon": "Tray-Symbol aktivieren", + "enableTraySpeed": "Tray-Geschwindigkeit aktivieren" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Monochromes Symbol", + "colorful": "Farbiges Symbol", + "disable": "Deaktivieren" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Port-Konfiguration", + "fields": { + "mixed": "Mischter Proxy-Port", + "socks": "SOCKS-Proxy-Port", + "http": "HTTP(S)-Proxy-Port", + "redir": "Redir-Transparenter Proxy-Port", + "tproxy": "TPROXY-Transparenter Proxy-Port" + }, + "actions": { + "random": "Zufälliger Port" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Stabile Version", + "alpha": "Alpha-Version" + } + }, + "liteMode": { + "title": "Einstellungen für den Leichtgewichtigen Modus", + "actions": { + "enterNow": "Sofort in den Leichtgewichtigen Modus wechseln" + }, + "toggles": { + "autoEnter": "Automatisch in den Leichtgewichtigen Modus wechseln" + }, + "tooltips": { + "autoEnter": "Wenn diese Option aktiviert ist, wird der Leichtgewichtige Modus automatisch aktiviert, nachdem das Fenster für eine bestimmte Zeit geschlossen wurde." + }, + "fields": { + "delay": "Verzögerung beim automatischen Wechsel in den Leichtgewichtigen Modus" + }, + "messages": { + "autoEnterHint": "Nach dem Schließen des Fensters wird der Leichtgewichtige Modus automatisch nach {{n}} Minuten aktiviert." + } + }, + "backup": { + "title": "Sicherungseinstellungen", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Sichern", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Sicherung löschen", + "restore": "Wiederherstellen", + "restoreBackup": "Sicherung wiederherstellen" + }, + "fields": { + "webdavUrl": "WebDAV-Serveradresse http(s)://", + "username": "Benutzername", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "Die WebDAV-Serveradresse darf nicht leer sein", + "invalidWebdavUrl": "Ungültiges Format für die WebDAV-Serveradresse", + "usernameRequired": "Der Benutzername darf nicht leer sein", + "passwordRequired": "Das Passwort darf nicht leer sein", + "webdavConfigSaved": "WebDAV-Konfiguration erfolgreich gespeichert", + "webdavConfigSaveFailed": "Speichern der WebDAV-Konfiguration fehlgeschlagen: {{error}}", + "backupCreated": "Sicherung erfolgreich erstellt", + "backupFailed": "Sicherung fehlgeschlagen: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Wiederherstellung erfolgreich. Die App wird in 1 Sekunde neu starten.", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Confirm to delete this backup file?", + "confirmRestore": "Confirm to restore this backup file?" + }, + "table": { + "filename": "Dateiname", + "backupTime": "Sicherungszeit", + "actions": "Aktionen", + "noBackups": "Keine Sicherungen vorhanden", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Sonstige Einstellungen", + "fields": { + "appLogLevel": "Anwendungs-Protokolliergrad", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Verbindungen automatisch schließen", + "autoCheckUpdate": "Automatisch auf Updates prüfen", + "enableBuiltinEnhanced": "Eingebaute Verbesserungen aktivieren", + "proxyLayoutColumns": "Anzahl der Spalten im Proxy-Layout", + "autoLogClean": "Protokolle automatisch bereinigen", + "autoDelayDetection": "Automatische Latenzprüfung", + "defaultLatencyTest": "Standard-Testlink", + "defaultLatencyTimeout": "Test-Timeout" + }, + "tooltips": { + "autoCloseConnections": "Wenn der ausgewählte Knoten in der Proxy-Gruppe oder der Proxy-Modus geändert wird, werden die bestehenden Verbindungen geschlossen.", + "enableBuiltinEnhanced": "Kompatibilitätsbehandlung der Konfigurationsdatei", + "autoDelayDetection": "Überprüft regelmäßig im Hintergrund die Latenz des aktuellen Knotens", + "defaultLatencyTest": "Dies wird nur für HTTP-Client-Anfragentests verwendet und hat keine Auswirkungen auf die Konfigurationsdatei." + }, + "options": { + "proxyLayoutColumns": { + "auto": "Automatische Anzahl der Spalten" + }, + "autoLogClean": { + "never": "Nie bereinigen", + "retainDays": "{{n}} Tage behalten" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Zur Veröffentlichungsseite gehen", + "update": "Aktualisieren" + }, + "messages": { + "portableError": "Die portable Version unterstützt keine In-App-Aktualisierung. Bitte laden Sie die Dateien manuell herunter und ersetzen Sie sie.", + "breakChangeError": "Dies ist eine wichtige Aktualisierung. Die In-App-Aktualisierung wird nicht unterstützt. Bitte deinstallieren Sie die Software und laden Sie die neue Version manuell herunter und installieren Sie sie." + } + }, + "sysproxy": { + "title": "Systemproxy-Einstellungen", + "fieldsets": { + "currentStatus": "Aktueller Systemproxy" + }, + "fields": { + "enableStatus": "Aktivierungsstatus: ", + "serverAddr": "Serveradresse: ", + "pacUrl": "PAC-Adresse: ", + "proxyHost": "Proxy-Host", + "usePacMode": "PAC-Modus verwenden", + "proxyGuard": "Systemproxy-Schutz", + "guardDuration": "Proxy-Schutz-Intervall", + "alwaysUseDefaultBypass": "Immer die Standard-Umgehung verwenden", + "proxyBypass": "Proxy-Umgehungseinstellungen: ", + "bypass": "Aktuelle Umgehung: ", + "pacScriptContent": "PAC-Skriptinhalt" + }, + "tooltips": { + "proxyGuard": "Aktivieren Sie diese Option, um zu verhindern, dass andere Software die Proxy-Einstellungen des Betriebssystems ändert." + }, + "messages": { + "durationTooShort": "Das Intervall des Proxy-Daemons darf nicht weniger als 1 Sekunde betragen.", + "invalidBypass": "Ungültiges Format für die Proxy-Umgehung", + "invalidProxyHost": "Ungültiges Format für den Proxy-Host" + }, + "actions": { + "editPac": "Bearbeiten PAC" + } + }, + "tun": { + "title": "Virtual Network Interface-Modus", + "fields": { + "stack": "TUN-Modus-Stack", + "device": "Device Name", + "autoRoute": "Globale Routing automatisch einstellen", + "strictRoute": "Strenges Routing", + "autoDetectInterface": "Netzwerkschnittstelle automatisch auswählen", + "dnsHijack": "DNS-Hijacking", + "mtu": "Maximale Übertragungseinheit" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Einstellungen angewendet" + } + }, + "dns": { + "dialog": { + "title": "DNS-Überschreibung", + "warning": "Wenn Sie sich nicht mit diesen Einstellungen auskennen, ändern Sie sie nicht und lassen Sie die DNS-Überschreibung aktiviert." + }, + "sections": { + "general": "DNS-Einstellungen", + "fallbackFilter": "Rückfallfilter-Einstellungen", + "hosts": "Hosts-Einstellungen" + }, + "fields": { + "enable": "DNS aktivieren", + "listen": "DNS-Lauschangabe", + "enhancedMode": "Erweiterter Modus", + "fakeIpRange": "Fake-IP-Bereich", + "fakeIpFilterMode": "Fake-IP-Filtermodus", + "ipv6": { + "label": "IPv6", + "description": "IPv6-DNS-Auflösung aktivieren" + }, + "preferH3": { + "label": "HTTP/3 bevorzugen", + "description": "DNS DOH verwendet HTTP/3-Protokoll" + }, + "respectRules": { + "label": "Routierungsregeln beachten", + "description": "DNS-Verbindungen folgen den Routierungsregeln" + }, + "useHosts": { + "label": "Hosts verwenden", + "description": "Aktivieren Sie die Auflösung von Hosts über die hosts-Datei" + }, + "useSystemHosts": { + "label": "System-Hosts verwenden", + "description": "Aktivieren Sie die Auflösung von Hosts über die System-hosts-Datei" + }, + "directPolicy": { + "label": "Direkte Namenserver folgen der Strategie", + "description": "Ob die Namenserver-Strategie befolgt werden soll" + }, + "defaultNameserver": { + "label": "Standard-Namenserver", + "description": "Standard-DNS-Server, die zum Auflösen von DNS-Servern verwendet werden" + }, + "nameserver": { + "label": "Namenserver", + "description": "Liste der DNS-Server, getrennt durch Kommas" + }, + "fallback": { + "label": "Rückfallserver", + "description": "Liste der Rückfall-DNS-Server, getrennt durch Kommas" + }, + "proxy": { + "label": "Proxy-Server-Namenserver", + "description": "Proxy-Knoten-Namenserver, nur für die Auflösung der Domains von Proxy-Knoten verwendet, getrennt durch Kommas" + }, + "directNameserver": { + "label": "Direkter Namenserver", + "description": "Direkter Ausgangs-Namenserver, unterstützt das Schlüsselwort system, getrennt durch Kommas" + }, + "fakeIpFilter": { + "label": "Fake-IP-Filter", + "description": "Domains, die die Fake-IP-Auflösung überspringen, getrennt durch Kommas" + }, + "nameserverPolicy": { + "label": "Namenserver-Strategie", + "description": "Domain-spezifischer DNS-Server, mehrere Server getrennt durch Semikolons, Format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP-Filterung", + "description": "GeoIP-Rückfallfilterung aktivieren" + }, + "geoipCode": "GeoIP-Ländercode", + "fallbackIpCidr": { + "label": "Rückfall-IP-CIDR", + "description": "IP-CIDRs, die keine Rückfallserver verwenden, getrennt durch Kommas" + }, + "fallbackDomain": { + "label": "Rückfall-Domäne", + "description": "Domains, die Rückfallserver verwenden, getrennt durch Kommas" + }, + "hosts": { + "label": "Hosts", + "description": "Benutzerdefinierte Zuordnung von Domains zu IPs oder Domains, getrennt durch Kommas" + } + }, + "messages": { + "saved": "DNS-Einstellungen wurden gespeichert", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "Link öffnen" + }, + "title": "Web-Oberfläche", + "messages": { + "supportedPlaceholders": "Unterstützt %host, %port, %secret", + "placeholderInstruction": "Verwenden Sie %host, %port, %secret für Host, Port und Zugangsschlüssel" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Globale Tastenkombinationen aktivieren" + }, + "title": "Tastenkombinationseinstellungen", + "functions": { + "rule": "Regel-Modus", + "global": "Globaler Modus", + "openOrCloseDashboard": "Dashboard öffnen/schließen", + "toggleSystemProxy": "Systemproxy ein/ausschalten", + "toggleTunMode": "TUN-Modus ein/ausschalten", + "entryLightweightMode": "Leichtgewichtigen Modus betreten", + "direct": "Direktverbindungs-Modus" + } + }, + "password": { + "prompts": { + "enterRoot": "Bitte geben Sie Ihr Root-Passwort ein." + } + }, + "networkInterface": { + "title": "Netzwerkschnittstelle", + "fields": { + "ipAddress": "IP-Adresse", + "macAddress": "MAC-Adresse" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clash-Kern wurde neu gestartet", + "versionUpdated": "Kernversion wurde aktualisiert", + "alreadyLatestVersion": "Bereits die neueste Kernversion in Verwendung", + "changeSuccess": "Kern erfolgreich gewechselt", + "changeFailed": "Kernwechsel fehlgeschlagen", + "geoDataUpdated": "Geo-Daten wurden aktualisiert" + }, + "clashService": { + "installSuccess": "Service erfolgreich installiert", + "uninstallSuccess": "Service erfolgreich deinstalliert" + }, + "updater": { + "withClashProxySuccess": "Aktualisierung mit Clash-Proxy erfolgreich", + "withClashProxyFailed": "Aktualisierung auch mit Clash-Proxy fehlgeschlagen" + } + } + }, + "statuses": { + "clash": { + "stopping": "Kern wird gestoppt...", + "restarting": "Kern wird neu gestartet..." + }, + "clashService": { + "installing": "Service wird installiert...", + "uninstalling": "Service wird deinstalliert..." + } + } +} diff --git a/src/locales/de/shared.json b/src/locales/de/shared.json new file mode 100644 index 000000000..22684cae0 --- /dev/null +++ b/src/locales/de/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Abbrechen", + "close": "Schließen", + "confirm": "Bestätigen", + "save": "Speichern", + "delete": "Löschen", + "edit": "Bearbeiten", + "new": "Neu", + "enable": "Aktivieren", + "upgrade": "Kern aktualisieren", + "restart": "Kern neustarten", + "resetToDefault": "Auf Standardwerte zurücksetzen", + "refresh": "Aktualisieren", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Listenansicht", + "tableView": "Tabellenansicht", + "pause": "Pausieren", + "resume": "Fortsetzen", + "closeAll": "Alle schließen", + "clear": "Löschen" + }, + "labels": { + "updateAt": "Aktualisiert am", + "timeout": "Timeout", + "icon": "Symbol", + "name": "Name", + "readOnly": "Schreibgeschützt", + "expireTime": "Ablaufzeit", + "updateTime": "Aktualisierungszeit", + "usedTotal": "Verwendet / Gesamt", + "from": "Von", + "password": "Passwort", + "retryAttempts": "Retry attempts", + "downloaded": "Heruntergeladen", + "uploaded": "Hochgeladen" + }, + "statuses": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert", + "saving": "Saving...", + "empty": "Leer" + }, + "units": { + "milliseconds": "Millisekunden", + "seconds": "Sekunden", + "minutes": "Minuten", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Filterbedingungen", + "matchCase": "Groß-/Kleinschreibung beachten", + "matchWholeWord": "Ganzes Wort übereinstimmen", + "useRegex": "Regulären Ausdruck verwenden" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Maximieren", + "minimize": "Minimieren" + }, + "editorModes": { + "visualization": "Visualisierung", + "advanced": "Erweitert" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Abonnement erfolgreich importiert", + "importSubscriptionSuccess": "Abonnement erfolgreich importiert", + "importWithClashProxy": "Abonnement mit Clash-Proxy importiert", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Kopieren erfolgreich", + "saveSuccess": "Zufalls-Konfiguration erfolgreich gespeichert", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Abonnement-Konfigurationsüberprüfung fehlgeschlagen. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Die Änderungen wurden rückgängig gemacht. Fehlerdetails: ", + "bootFailed": "Start-Abonnement-Konfigurationsüberprüfung fehlgeschlagen. Die Standardkonfiguration wurde verwendet, um die App zu starten. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Fehlerdetails: ", + "coreChangeFailed": "Konfigurationsüberprüfung beim Wechsel des Kerns fehlgeschlagen. Die Standardkonfiguration wurde verwendet, um die App zu starten. Bitte überprüfen Sie die Abonnement-Konfigurationsdatei. Fehlerdetails: ", + "processTerminated": "Validierungsprozess abgebrochen" + }, + "script": { + "syntaxError": "Skript-Syntaxfehler. Die Änderungen wurden rückgängig gemacht.", + "missingMain": "Skriptfehler. Die Änderungen wurden rückgängig gemacht.", + "fileNotFound": "Datei nicht gefunden. Die Änderungen wurden rückgängig gemacht.", + "fileError": "Skript-Dateifehler. Die Änderungen wurden rückgängig gemacht." + }, + "yaml": { + "syntaxError": "YAML-Syntaxfehler. Die Änderungen wurden rückgängig gemacht.", + "readError": "YAML-Lesefehler. Die Änderungen wurden rückgängig gemacht.", + "mappingError": "YAML-Mappingfehler. Die Änderungen wurden rückgängig gemacht.", + "keyError": "YAML-Schlüsselfehler. Die Änderungen wurden rückgängig gemacht.", + "generalError": "YAML-Fehler. Die Änderungen wurden rückgängig gemacht." + }, + "merge": { + "syntaxError": "Syntaxfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", + "mappingError": "Mappingfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", + "keyError": "Schlüsselfehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht.", + "generalError": "Fehler in der Überdeckungsdatei. Die Änderungen wurden rückgängig gemacht." + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/de/tests.json b/src/locales/de/tests.json new file mode 100644 index 000000000..49b92211b --- /dev/null +++ b/src/locales/de/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Alle testen" + }, + "title": "Testen" + }, + "components": { + "item": { + "actions": { + "test": "Testen" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Neuen Test erstellen", + "edit": "Test bearbeiten" + }, + "fields": { + "url": "Test-URL" + } + } + }, + "statuses": { + "test": { + "pending": "Wartend auf Prüfung", + "yes": "Unterstützt", + "no": "Nicht unterstützt", + "failed": "Test fehlgeschlagen", + "completed": "Prüfung abgeschlossen", + "disallowedIsp": "Nicht zugelassener Internetdienstanbieter", + "originalsOnly": "Nur Original", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Nicht unterstütztes Land/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Wird getestet..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "Erkennung für {{name}} fehlgeschlagen", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Entsperrungstest" + } + } +} diff --git a/src/locales/en.json b/src/locales/en.json deleted file mode 100644 index 2716d3165..000000000 --- a/src/locales/en.json +++ /dev/null @@ -1,718 +0,0 @@ -{ - "millis": "ms", - "seconds": "seconds", - "mins": "mins", - "Back": "Back", - "Close": "Close", - "Cancel": "Cancel", - "Confirm": "Confirm", - "Maximize": "Maximize", - "Minimize": "Minimize", - "Format document": "Format document", - "Empty": "Empty", - "New": "New", - "Edit": "Edit", - "Save": "Save", - "Delete": "Delete", - "Enable": "Enable", - "Disable": "Disable", - "Label-Home": "Home", - "Label-Proxies": "Proxies", - "Label-Profiles": "Profiles", - "Label-Connections": "Connections", - "Label-Rules": "Rules", - "Label-Logs": "Logs", - "Label-Unlock": "Test", - "Label-Settings": "Settings", - "Proxies": "Proxies", - "Proxy Groups": "Proxy Groups", - "Proxy Chain Mode": "Proxy Chain Mode", - "Connect": "Connect", - "Connecting...": "Connecting...", - "Disconnect": "Disconnect", - "Failed to connect to proxy chain": "Failed to connect to proxy chain", - "Proxy Provider": "Proxy Provider", - "Proxy Count": "Proxy Count", - "Update All": "Update All", - "Update At": "Update At", - "rule": "rule", - "global": "global", - "direct": "direct", - "Chain Proxy": "🔗 Chain Proxy", - "Chain Proxy Config": "Chain Proxy Config", - "Proxy Rules": "Proxy Rules", - "Select Rules": "Select Rules", - "Click nodes in order to add to proxy chain": "Click nodes in order to add to proxy chain", - "No proxy chain configured": "No proxy chain configured", - "Proxy Order": "Proxy Order", - "timeout": "Timeout", - "Clear All": "Clear All", - "script": "script", - "locate": "locate", - "Delay check": "Delay check", - "Sort by default": "Sort by default", - "Sort by delay": "Sort by delay", - "Sort by name": "Sort by name", - "Delay check URL": "Delay check URL", - "Delay check to cancel fixed": "Delay check to cancel fixed", - "Proxy basic": "Proxy basic", - "Proxy detail": "Proxy detail", - "Profiles": "Profiles", - "Update All Profiles": "Update All Profiles", - "View Runtime Config": "View Runtime Config", - "Reactivate Profiles": "Reactivate Profiles", - "Paste": "Paste", - "Profile URL": "Profile URL", - "Import": "Import", - "From": "From", - "Update Time": "Update Time", - "Used / Total": "Used / Total", - "Expire Time": "Expire Time", - "Create Profile": "Create Profile", - "Edit Profile": "Edit Profile", - "Edit Proxies": "Edit Proxies", - "Use newlines for multiple uri": "Use newlines for multiple uri(Base64 encoding supported)", - "Edit Rules": "Edit Rules", - "Rule Type": "Rule Type", - "Rule Content": "Rule Content", - "Proxy Policy": "Proxy Policy", - "No Resolve": "No Resolve", - "Prepend Rule": "Prepend Rule", - "Append Rule": "Append Rule", - "Prepend Group": "Prepend Group", - "Append Group": "Append Group", - "Prepend Proxy": "Prepend Proxy", - "Append Proxy": "Append Proxy", - "Rule Condition Required": "Rule Condition Required", - "Invalid Rule": "Invalid Rule", - "Advanced": "Advanced", - "Visualization": "Visualization", - "DOMAIN": "Matches the full domain name", - "DOMAIN-SUFFIX": "Matches the domain suffix", - "DOMAIN-KEYWORD": "Matches the domain keyword", - "DOMAIN-REGEX": "Matches the domain using regular expressions", - "GEOSITE": "Matches domains within the Geosite", - "GEOIP": "Matches the country code of the IP address", - "SRC-GEOIP": "Matches the country code of the source IP address", - "IP-ASN": "Matches the IP address's ASN", - "SRC-IP-ASN": "Matches the source IP address's ASN", - "IP-CIDR": "Matches the IP address range", - "IP-CIDR6": "Matches the IPv6 address range", - "SRC-IP-CIDR": "Matches the source IP address range", - "IP-SUFFIX": "Matches the IP address suffix range", - "SRC-IP-SUFFIX": "Matches the source IP address suffix range", - "SRC-PORT": "Matches the source port range", - "DST-PORT": "Matches the destination port range", - "IN-PORT": "Matches the inbound port", - "DSCP": "DSCP marking (only for tproxy UDP inbound)", - "PROCESS-NAME": "Matches the process name (Android package name)", - "PROCESS-PATH": "Matches the full process path", - "PROCESS-NAME-REGEX": "Matches the full process name using regular expressions (Android package name)", - "PROCESS-PATH-REGEX": "Matches the full process path using regular expressions", - "NETWORK": "Matches the transport protocol (tcp/udp)", - "UID": "Matches the Linux USER ID", - "IN-TYPE": "Matches the inbound type", - "IN-USER": "Matches the inbound username", - "IN-NAME": "Matches the inbound name", - "SUB-RULE": "Sub-rule", - "RULE-SET": "Matches the rule set", - "AND": "Logical AND", - "OR": "Logical OR", - "NOT": "Logical NOT", - "MATCH": "Matches all requests", - "DIRECT": "Data goes directly outbound", - "REJECT": "Intercepts requests", - "REJECT-DROP": "Discards requests", - "PASS": "Skips this rule when matched", - "Edit Groups": "Edit Proxy Groups", - "Group Type": "Group Type", - "select": "Select proxy manually", - "url-test": "Select proxy based on URL test delay", - "fallback": "Switch to another proxy on error", - "load-balance": "Distribute proxy based on load balancing", - "relay": "Pass through the defined proxy chain", - "Group Name": "Group Name", - "Use Proxies": "Use Proxies", - "Use Provider": "Use Provider", - "Health Check Url": "Health Check Url", - "Expected Status": "Expected Status", - "Interval": "Interval", - "Lazy": "Lazy", - "Timeout": "Timeout", - "Max Failed Times": "Max Failed Times", - "Interface Name": "Interface Name", - "Routing Mark": "Routing Mark", - "Include All": "Include All Proxies and Providers", - "Include All Providers": "Include All Providers", - "Include All Proxies": "Include All Proxies", - "Exclude Filter": "Exclude Filter", - "Exclude Type": "Exclude Type", - "Disable UDP": "Disable UDP", - "Hidden": "Hidden", - "Group Name Required": "Group Name Required", - "Group Name Already Exists": "Group Name Already Exists", - "Extend Config": "Extend Config", - "Extend Script": "Extend Script", - "Global Merge": "Global Extend Config", - "Global Script": "Global Extend Script", - "Type": "Type", - "Name": "Name", - "Descriptions": "Descriptions", - "Subscription URL": "Subscription URL", - "Update Interval": "Update Interval", - "Choose File": "Choose File", - "Use System Proxy": "Use System Proxy", - "Use Clash Proxy": "Use Clash Proxy", - "Accept Invalid Certs (Danger)": "Allows Invalid Certificates (Danger)", - "Refresh": "Refresh", - "Home": "Home", - "Select": "Select", - "Edit Info": "Edit Info", - "Edit File": "Edit File", - "Open File": "Open File", - "Update": "Update", - "Update via proxy": "Update via proxy", - "Update(Proxy)": "Update(Proxy)", - "Confirm deletion": "Confirm deletion", - "This operation is not reversible": "This operation is not reversible", - "Script Console": "Script Console", - "To Top": "To Top", - "To End": "To End", - "Connections": "Connections", - "Table View": "Table View", - "List View": "List View", - "Close All": "Close All", - "Close All Connections": "Close All Connections", - "Upload": "Upload", - "Download": "Download", - "Download Speed": "Download Speed", - "Upload Speed": "Upload Speed", - "Host": "Host", - "Downloaded": "Downloaded", - "Uploaded": "Uploaded", - "DL Speed": "DL Speed", - "UL Speed": "UL Speed", - "Active Connections": "Active Connections", - "Chains": "Chains", - "Rule": "Rule", - "Process": "Process", - "Time": "Time", - "Source": "Source", - "Destination": "Destination", - "DestinationPort": "Destination Port", - "Close Connection": "Close Connection", - "Rules": "Rules", - "Rule Provider": "Rule Provider", - "Logs": "Logs", - "Pause": "Pause", - "Resume": "Resume", - "Clear": "Clear", - "Test": "Test", - "Test All": "Test All", - "Testing...": "Testing...", - "Create Test": "Create Test", - "Edit Test": "Edit Test", - "Icon": "Icon", - "Test URL": "Test URL", - "Settings": "Settings", - "System Setting": "System Setting", - "Tun Mode": "Tun Mode", - "TUN requires Service Mode": "TUN mode requires install service", - "Install Service": "Install Service", - "Install Service failed": "Install Service failed", - "Uninstall Service": "Uninstall Service", - "Restart Core failed": "Restart Core failed", - "Reset to Default": "Reset to Default", - "Tun Mode Info": "Tun (Virtual NIC) mode: Captures all system traffic, when enabled, there is no need to enable system proxy.", - "TUN requires Service Mode or Admin Mode": "TUN requires Service Mode or Admin Mode", - "TUN Mode automatically disabled due to service unavailable": "TUN Mode automatically disabled due to service unavailable", - "Failed to disable TUN Mode automatically": "Failed to disable TUN Mode automatically", - "System Proxy Enabled": "System proxy is enabled, your applications will access the network through the proxy", - "System Proxy Disabled": "System proxy is disabled, it is recommended for most users to turn on this option", - "TUN Mode Enabled": "TUN mode is enabled, applications will access the network through the virtual network card", - "TUN Mode Disabled": "TUN mode is disabled, suitable for special applications", - "TUN Mode Service Required": "TUN mode requires service mode, please install the service first", - "TUN Mode Intercept Info": "TUN mode can take over all application traffic, suitable for special applications that do not follow the system proxy settings", - "Core communication error": "Core communication error", - "Rule Mode Description": "Routes traffic according to preset rules, provides flexible proxy strategies", - "Global Mode Description": "All traffic goes through proxy servers, suitable for scenarios requiring global internet access", - "Direct Mode Description": "All traffic doesn't go through proxy nodes, but is forwarded by Clash kernel to target servers, suitable for specific scenarios requiring kernel traffic distribution", - "Stack": "Tun Stack", - "System and Mixed Can Only be Used in Service Mode": "System and Mixed Can Only be Used in Service Mode", - "Device": "Device Name", - "Auto Route": "Auto Route", - "Strict Route": "Strict Route", - "Auto Detect Interface": "Auto Detect Interface", - "DNS Hijack": "DNS Hijack", - "MTU": "Max Transmission Unit", - "Service Mode": "Service Mode", - "Service Mode Info": "Please install the service mode before enabling TUN mode. The kernel process started by the service can obtain the permission to install the virtual network card (TUN mode)", - "Current State": "Current State", - "pending": "pending", - "installed": "installed", - "uninstall": "uninstalled", - "active": "active", - "unknown": "unknown", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "Information: Please make sure that the Clash Verge Service is installed and enabled", - "Install": "Install", - "Uninstall": "Uninstall", - "Disable Service Mode": "Disable Service Mode", - "System Proxy": "System Proxy", - "System Proxy Info": "Enable to modify the operating system's proxy settings. If enabling fails, modify the operating system's proxy settings manually", - "System Proxy Setting": "System Proxy Setting", - "Current System Proxy": "Current System Proxy", - "Enable status": "Enable Status:", - "Enabled": "Enabled", - "Disabled": "Disabled", - "Server Addr": "Server Addr: ", - "Proxy Host": "Proxy Host", - "Invalid Proxy Host Format": "Invalid Proxy Host Format", - "Not available": "Not available", - "Proxy Guard": "Proxy Guard", - "Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings", - "Guard Duration": "Guard Duration", - "Always use Default Bypass": "Always use Default Bypass", - "Use Bypass Check": "Use Bypass Check", - "Proxy Bypass": "Proxy Bypass Settings: ", - "Bypass": "Bypass: ", - "Use PAC Mode": "Use PAC Mode", - "PAC Script Content": "PAC Script Content", - "PAC URL": "PAC URL: ", - "Auto Launch": "Auto Launch", - "Administrator mode may not support auto launch": "Administrator mode may not support auto launch", - "Silent Start": "Silent Start", - "Silent Start Info": "Start the program in background mode without displaying the panel", - "Hover Jump Navigator": "Hover Jump Navigator", - "Hover Jump Navigator Info": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", - "Hover Jump Navigator Delay": "Hover Jump Navigator Delay", - "Hover Jump Navigator Delay Info": "Delay before auto scrolling when hovering, in milliseconds", - "TG Channel": "Telegram Channel", - "Manual": "Manual", - "Github Repo": "Github Repo", - "Clash Setting": "Clash Setting", - "Allow Lan": "Allow LAN", - "Network Interface": "Network Interface", - "Ip Address": "IP Address", - "Mac Address": "MAC Address", - "IPv6": "IPv6", - "Unified Delay": "Unified Delay", - "Unified Delay Info": "When unified delay is turned on, two delay tests will be performed to eliminate the delay differences between different types of nodes caused by connection handshakes, etc", - "Log Level": "Log Level", - "Log Level Info": "This parameter is valid only for kernel log files in the log directory Service folder", - "Port Config": "Port Config", - "Random Port": "Random Port", - "Mixed Port": "Mixed Port", - "Socks Port": "Socks Port", - "Http Port": "Http(s) Port", - "Redir Port": "Redir Port", - "Tproxy Port": "Tproxy Port", - "Port settings saved": "Port settings saved", - "Failed to save port settings": "Failed to save port settings", - "External": "External", - "Enable External Controller": "Enable External Controller", - "External Controller": "External Controller", - "Core Secret": "Core Secret", - "Recommended": "Recommended", - "Open URL": "Open URL", - "Replace host, port, secret with %host, %port, %secret": "Replace host, port, secret with %host, %port, %secret", - "Support %host, %port, %secret": "Support %host, %port, %secret", - "Clash Core": "Clash Core", - "Upgrade": "Upgrade", - "Restart": "Restart", - "Release Version": "Release Version", - "Alpha Version": "Alpha Version", - "Please Enable Service Mode": "Please Install and Enable Service Mode First", - "Please enter your root password": "Please enter your root password", - "Grant": "Grant", - "Open UWP tool": "Open UWP tool", - "Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction", - "Update GeoData": "Update GeoData", - "Verge Basic Setting": "Verge Basic Setting", - "Verge Advanced Setting": "Verge Advanced Setting", - "Language": "Language", - "Theme Mode": "Theme Mode", - "theme.light": "Light", - "theme.dark": "Dark", - "theme.system": "System", - "Tray Click Event": "Tray Click Event", - "Show Main Window": "Show Main Window", - "Show Tray Menu": "Show Tray Menu", - "Copy Env Type": "Copy Env Type", - "Copy Success": "Copy Success", - "Start Page": "Start Page", - "Startup Script": "Startup Script", - "Browse": "Browse", - "Theme Setting": "Theme Setting", - "Primary Color": "Primary Color", - "Secondary Color": "Secondary Color", - "Primary Text": "Primary Text", - "Secondary Text": "Secondary Text", - "Info Color": "Info Color", - "Warning Color": "Warning Color", - "Error Color": "Error Color", - "Success Color": "Success Color", - "Font Family": "Font Family", - "CSS Injection": "CSS Injection", - "Layout Setting": "Layout Setting", - "Traffic Graph": "Traffic Graph", - "Memory Usage": "Core Usage", - "Memory Cleanup": "Tap to clean up memory", - "Proxy Group Icon": "Proxy Group Icon", - "Nav Icon": "Nav Icon", - "Monochrome": "Monochrome", - "Colorful": "Colorful", - "Tray Icon": "Tray Icon", - "Common Tray Icon": "Common Tray Icon", - "System Proxy Tray Icon": "System Proxy Tray Icon", - "Tun Tray Icon": "Tun Tray Icon", - "Miscellaneous": "Miscellaneous", - "App Log Level": "App Log Level", - "Auto Close Connections": "Auto Close Connections", - "Auto Close Connections Info": "Terminate established connections when the proxy group selection or proxy mode changes", - "Auto Check Update": "Auto Check Update", - "Enable Builtin Enhanced": "Enable Builtin Enhanced", - "Enable Builtin Enhanced Info": "Compatibility handling for the configuration file", - "Proxy Layout Columns": "Proxy Layout Columns", - "Auto Columns": "Auto Columns", - "Auto Log Clean": "Auto Log Clean", - "Never Clean": "Never Clean", - "Retain _n Days": "Retain {{n}} Days", - "Auto Delay Detection": "Auto Delay Detection", - "Auto Delay Detection Info": "Periodically test the current node latency in the background", - "Default Latency Test": "Default Latency Test", - "Default Latency Test Info": "Used for HTTP client request testing only and won't make a difference to the configuration file", - "Default Latency Timeout": "Default Latency Timeout", - "Hotkey Setting": "Hotkey Setting", - "Enable Global Hotkey": "Enable Global Hotkey", - "open_or_close_dashboard": "Open/Close Dashboard", - "clash_mode_rule": "Rule Mode", - "clash_mode_global": "Global Mode", - "clash_mode_direct": "Direct Mode", - "toggle_system_proxy": "Enable/Disable System Proxy", - "toggle_tun_mode": "Enable/Disable Tun Mode", - "entry_lightweight_mode": "Entry Lightweight Mode", - "Backup Setting": "Backup Setting", - "Backup Setting Info": "Support local or WebDAV backup of configuration files", - "Runtime Config": "Runtime Config", - "Open Conf Dir": "Open Conf Dir", - "Open Conf Dir Info": "If the software runs abnormally, BACKUP and delete all files in this folder then restart the software", - "Open Core Dir": "Open Core Dir", - "Open Logs Dir": "Open Logs Dir", - "Check for Updates": "Check for Updates", - "Go to Release Page": "Go to Release Page", - "Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it", - "Break Change Update Error": "This version is a major update and does not support in-app updates. Please uninstall it and manually download and install the new version", - "Open Dev Tools": "Dev Tools", - "Export Diagnostic Info": "Export Diagnostic Info", - "Export Diagnostic Info For Issue Reporting": "Export Diagnostic Info For Issue Reporting", - "Exit": "Exit", - "Verge Version": "Verge Version", - "ReadOnly": "ReadOnly", - "ReadOnlyMessage": "Cannot edit in read-only editor", - "Filter": "Filter", - "Filter conditions": "Filter conditions", - "Match Case": "Match Case", - "Match Whole Word": "Match Whole Word", - "Use Regular Expression": "Use Regular Expression", - "Profile Imported Successfully": "Profile Imported Successfully", - "Profile Switched": "Profile Switched", - "Profile Reactivated": "Profile Reactivated", - "Profile switch interrupted by new selection": "Profile switch interrupted by new selection", - "Only YAML Files Supported": "Only YAML Files Supported", - "Settings Applied": "Settings Applied", - "Stopping Core...": "Stopping Core...", - "Restarting Core...": "Restarting Core...", - "Installing Service...": "Installing Service...", - "Uninstalling Service...": "Uninstalling Service...", - "Service Installed Successfully": "Service Installed Successfully", - "Service Uninstalled Successfully": "Service Uninstalled Successfully", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Proxy Daemon Duration Cannot be Less than 1 Second", - "Invalid Bypass Format": "Invalid Bypass Format", - "Waiting for service to be ready...": "Waiting for service to be ready...", - "Service not ready, retrying attempt {count}/{total}...": "Service not ready, retrying attempt {{count}}/{{total}}...", - "Failed to check service status, retrying attempt {count}/{total}...": "Failed to check service status, retrying attempt {{count}}/{{total}}...", - "Service did not become ready after attempts. Proceeding with core restart.": "Service did not become ready after attempts. Proceeding with core restart.", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "Service was ready, but core restart might have issues or service became unavailable. Please check.", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "Service installation or core restart encountered issues. Service might not be available. Please check system logs.", - "Attempting to restart core as a fallback...": "Attempting to restart core as a fallback...", - "Fallback core restart also failed: {message}": "Fallback core restart also failed: {{message}}", - "Service is ready and core restarted": "Service is ready and core restarted", - "Core restarted. Service is now available.": "Core restarted. Service is now available.", - "Clash Port Modified": "Clash Port Modified", - "Port Conflict": "Port Conflict", - "Restart Application to Apply Modifications": "Restart Application to Apply Modifications", - "External Controller Address Modified": "External Controller Address Modified", - "Permissions Granted Successfully for _clash Core": "Permissions Granted Successfully for {{core}} Core", - "Core Version Updated": "Core Version Updated", - "Clash Core Restarted": "Clash Core Restarted", - "GeoData Updated": "GeoData Updated", - "Currently on the Latest Version": "Currently on the Latest Version", - "Already Using Latest Core": "Already Using Latest Core", - "Import Subscription Successful": "Import subscription successful", - "WebDAV Server URL": "WebDAV Server URL", - "Username": "Username", - "Password": "Password", - "Backup": "Backup", - "Local Backup": "Local backup", - "WebDAV Backup": "WebDAV backup", - "Select Backup Target": "Select backup target", - "Filename": "Filename", - "Actions": "Actions", - "Restore": "Restore", - "Export": "Export", - "No Backups": "No backups available", - "WebDAV URL Required": "WebDAV URL cannot be empty", - "Invalid WebDAV URL": "Invalid WebDAV URL format", - "Username Required": "Username cannot be empty", - "Password Required": "Password cannot be empty", - "Failed to Fetch Backups": "Failed to fetch backup files", - "WebDAV Config Saved": "WebDAV configuration saved successfully", - "WebDAV Config Save Failed": "Failed to save WebDAV configuration: {{error}}", - "Backup Created": "Backup created successfully", - "Backup Failed": "Backup failed: {{error}}", - "Local Backup Created": "Local backup created successfully", - "Local Backup Failed": "Local backup failed", - "Local Backup Exported": "Local backup exported successfully", - "Local Backup Export Failed": "Failed to export local backup", - "Local Backup Info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups.", - "Delete Backup": "Delete Backup", - "Export Backup": "Export Backup", - "Restore Backup": "Restore Backup", - "Backup Time": "Backup Time", - "Confirm to delete this backup file?": "Confirm to delete this backup file?", - "Confirm to restore this backup file?": "Confirm to restore this backup file?", - "Restore Success, App will restart in 1s": "Restore Success, App will restart in 1s", - "Failed to fetch backup files": "Failed to fetch backup files", - "Profile": "Profile", - "Help": "Help", - "About": "About", - "Theme": "Theme", - "Main Window": "Main Window", - "Group Icon": "Group Icon", - "Menu Icon": "Menu Icon", - "PAC File": "PAC File", - "Web UI": "Web UI", - "Hotkeys": "Hotkeys", - "Verge Mixed Port": "Verge Mixed Port", - "Verge Socks Port": "Verge Socks Port", - "Verge Redir Port": "Verge Redir Port", - "Verge Tproxy Port": "Verge Tproxy Port", - "Verge Port": "Verge Port", - "Verge HTTP Enabled": "Verge HTTP Enabled", - "WebDAV URL": "WebDAV URL", - "WebDAV Username": "WebDAV Username", - "WebDAV Password": "WebDAV Password", - "Dashboard": "Dashboard", - "Restart App": "Restart App", - "Restart Clash Core": "Restart Clash Core", - "TUN Mode": "TUN Mode", - "Copy Env": "Copy Env", - "Conf Dir": "Conf Dir", - "Core Dir": "Core Dir", - "Logs Dir": "Logs Dir", - "Open Dir": "Open Dir", - "More": "More", - "Rule Mode": "Rule Mode", - "Global Mode": "Global Mode", - "Direct Mode": "Direct Mode", - "Enable Tray Speed": "Enable Tray Speed", - "Enable Tray Icon": "Enable Tray Icon", - "Show Proxy Groups Inline": "Show Proxy Groups Inline", - "LightWeight Mode": "Lightweight Mode", - "LightWeight Mode Info": "Close the GUI and keep only the kernel running", - "LightWeight Mode Settings": "LightWeight Mode Settings", - "Enter LightWeight Mode Now": "Enter LightWeight Mode Now", - "Auto Enter LightWeight Mode": "Auto Enter LightWeight Mode", - "Auto Enter LightWeight Mode Info": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time", - "Auto Enter LightWeight Mode Delay": "Auto Enter LightWeight Mode Delay", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes", - "Config Validation Failed": "Subscription configuration validation failed. Please check the subscription configuration file; modifications have been rolled back.", - "Boot Config Validation Failed": "Boot subscription configuration validation failed. Started with the default configuration; please check the subscription configuration file.", - "Core Change Config Validation Failed": "Configuration validation failed when switching the kernel. Started with the default configuration; please check the subscription configuration file.", - "Config Validation Process Terminated": "The validation process has been terminated.", - "Script Syntax Error": "Script syntax error, changes reverted", - "Script Missing Main": "Script error, changes reverted", - "File Not Found": "File missing, changes reverted", - "Script File Error": "Script file error, changes reverted", - "Core Changed Successfully": "Core changed successfully", - "Failed to Change Core": "Failed to change core", - "YAML Syntax Error": "YAML syntax error, changes reverted", - "YAML Read Error": "YAML read error, changes reverted", - "YAML Mapping Error": "YAML mapping error, changes reverted", - "YAML Key Error": "YAML key error, changes reverted", - "YAML Error": "YAML error, changes reverted", - "Merge File Syntax Error": "Merge file syntax error, changes reverted", - "Merge File Mapping Error": "Merge file mapping error, changes reverted", - "Merge File Key Error": "Merge file key error, changes reverted", - "Merge File Error": "Merge file error, changes reverted", - "Validate YAML File": "Validate YAML File", - "Validate Merge File": "Validate Merge File", - "Validation Success": "Validation Success", - "Validation Failed": "Validation Failed", - "Service Administrator Prompt": "Clash Verge requires administrator privileges to reinstall the system service", - "DNS Settings": "DNS Settings", - "DNS settings saved": "DNS settings saved", - "DNS Overwrite": "DNS Overwrite", - "DNS Settings Warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled", - "Enable DNS": "Enable DNS", - "DNS Listen": "DNS Listen", - "Enhanced Mode": "Enhanced Mode", - "Fake IP Range": "Fake IP Range", - "Fake IP Filter Mode": "Fake IP Filter Mode", - "Enable IPv6 DNS resolution": "Enable IPv6 DNS resolution", - "Prefer H3": "Prefer H3", - "DNS DOH使用HTTP/3": "DNS DOH uses HTTP/3", - "Respect Rules": "Respect Rules", - "DNS connections follow routing rules": "DNS connections follow routing rules", - "Use Hosts": "Use Hosts", - "Enable to resolve hosts through hosts file": "Enable to resolve hosts through hosts file", - "Use System Hosts": "Use System Hosts", - "Enable to resolve hosts through system hosts file": "Enable to resolve hosts through system hosts file", - "Direct Nameserver Follow Policy": "Direct Nameserver Follow Policy", - "Whether to follow nameserver policy": "Whether to follow nameserver policy", - "Default Nameserver": "Default Nameserver", - "Default DNS servers used to resolve DNS servers": "Default DNS servers used to resolve DNS servers", - "Nameserver": "Nameserver", - "List of DNS servers": "List of DNS servers, comma separated", - "Fallback": "Fallback", - "List of fallback DNS servers": "List of fallback DNS servers, comma separated", - "Proxy Server Nameserver": "Proxy Server Nameserver", - "Proxy Node Nameserver": "DNS servers for proxy node domain resolution", - "Direct Nameserver": "Direct Nameserver", - "Direct outbound Nameserver": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated", - "Fake IP Filter": "Fake IP Filter", - "Domains that skip fake IP resolution": "Domains that skip fake IP resolution, comma separated", - "Nameserver Policy": "Nameserver Policy", - "Domain-specific DNS server": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2", - "Fallback Filter Settings": "Fallback Filter Settings", - "GeoIP Filtering": "GeoIP Filtering", - "Enable GeoIP filtering for fallback": "Enable GeoIP filtering for fallback", - "GeoIP Code": "GeoIP Code", - "Fallback IP CIDR": "Fallback IP CIDR", - "IP CIDRs not using fallback servers": "IP CIDRs not using fallback servers, comma separated", - "Fallback Domain": "Fallback Domain", - "Domains using fallback servers": "Domains using fallback servers, comma separated", - "Hosts Settings": "Hosts Settings", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "Custom domain to IP or domain mapping", - "Enable Alpha Channel": "Enable Alpha Channel", - "Alpha versions may contain experimental features and bugs": "Alpha versions may contain experimental features and bugs", - "Home Settings": "Home Settings", - "Profile Card": "Profile Card", - "Current Proxy Card": "Current Proxy Card", - "Network Settings Card": "Network Settings Card", - "Proxy Mode Card": "Proxy Mode Card", - "Clash Mode Card": "Clash Mode Card", - "Traffic Stats Card": "Traffic Stats Card", - "Clash Info Cards": "Clash Info Cards", - "System Info Cards": "System Info Cards", - "Website Tests Card": "Website Tests Card", - "Traffic Stats": "Traffic Stats", - "Website Tests": "Website Tests", - "Clash Info": "Clash Info", - "Core Version": "Core Version", - "System Proxy Address": "System Proxy Address", - "Uptime": "Uptime", - "Rules Count": "Rules Count", - "System Info": "System Info", - "OS Info": "OS Info", - "Running Mode": "Running Mode", - "Sidecar Mode": "User Mode", - "Administrator Mode": "Administrator Mode", - "Administrator + Service Mode": "Admin + Service Mode", - "Last Check Update": "Last Check Update", - "Click to import subscription": "Click to import subscription", - "Last Update failed": "Last Update failed", - "Next Up": "Next Up", - "No schedule": "No schedule", - "Unknown": "Unknown", - "Auto update disabled": "Auto update disabled", - "Update subscription successfully": "Update subscription successfully", - "Update with Clash proxy successfully": "Update with Clash proxy successfully", - "Update failed even with Clash proxy": "Update failed even with Clash proxy", - "Profile creation failed, retrying with Clash proxy...": "Profile creation failed, retrying with Clash proxy...", - "Profile creation succeeded with Clash proxy": "Profile creation succeeded with Clash proxy", - "Import failed, retrying with Clash proxy...": "Import failed, retrying with Clash proxy...", - "Profile Imported with Clash proxy": "Profile Imported with Clash proxy", - "Import failed even with Clash proxy": "Import failed even with Clash proxy", - "Current Node": "Current Node", - "No active proxy node": "No active proxy node", - "Network Settings": "Network Settings", - "Proxy Mode": "Proxy Mode", - "Group": "Group", - "Proxy": "Proxy", - "IP Information Card": "IP Information Card", - "IP Information": "IP Information", - "Failed to get IP info": "Failed to get IP info", - "ISP": "ISP", - "ASN": "ASN", - "ORG": "ORG", - "Location": "Location", - "Timezone": "Timezone", - "Auto refresh": "Auto refresh", - "Unlock Test": "Unlock Test", - "Pending": "Pending", - "Yes": "Yes", - "No": "No", - "Failed": "Failed", - "Completed": "Completed", - "Disallowed ISP": "Disallowed ISP", - "Originals Only": "Originals Only", - "No (IP Banned By Disney+)": "No (IP Banned By Disney+)", - "Unsupported Country/Region": "Unsupported Country/Region", - "Failed (Network Connection)": "Failed (Network Connection)", - "DashboardToggledTitle": "Dashboard Toggled", - "DashboardToggledBody": "Dashboard visibility toggled by hotkey", - "ClashModeChangedTitle": "Clash Mode Changed", - "ClashModeChangedBody": "Switched to {mode} mode", - "SystemProxyToggledTitle": "System Proxy Toggled", - "SystemProxyToggledBody": "System proxy state toggled by hotkey", - "TunModeToggledTitle": "TUN Mode Toggled", - "TunModeToggledBody": "TUN mode toggled by hotkey", - "LightweightModeEnteredTitle": "Lightweight Mode", - "LightweightModeEnteredBody": "Entered lightweight mode by hotkey", - "AppQuitTitle": "APP Quit", - "AppQuitBody": "APP quit by hotkey", - "AppHiddenTitle": "APP Hidden", - "AppHiddenBody": "APP window hidden by hotkey", - "Invalid Profile URL": "Invalid profile URL. Please enter a URL starting with http:// or https://", - "Saved Successfully": "Saved successfully", - "External Cors": "External Cors", - "Enable one-click CORS for external API. Click to toggle CORS": "Enable one-click CORS for external API. Click to toggle CORS", - "External Cors Settings": "External Cors Settings", - "External Cors Configuration": "External Cors Configuration", - "Allow private network access": "Allow private network access", - "Allowed Origins": "Allowed Origins", - "Please enter a valid url": "Please enter a valid url", - "Add": "Add", - "Always included origins: {{urls}}": "Always included origins: {{urls}}", - "Invalid regular expression": "Invalid regular expression", - "Copy Version": "Copy Version", - "Version copied to clipboard": "Version copied to clipboard", - "Controller address cannot be empty": "Controller address cannot be empty", - "Secret cannot be empty": "Secret cannot be empty", - "Configuration saved successfully": "Configuration saved successfully", - "Failed to save configuration": "Failed to save configuration", - "Controller address copied to clipboard": "Controller address copied to clipboard", - "Secret copied to clipboard": "Secret copied to clipboard", - "Saving...": "Saving...", - "Proxy node already exists in chain": "Proxy node already exists in chain", - "Detection timeout or failed": "Detection timeout or failed", - "Batch Operations": "Batch Operations", - "Delete Selected Profiles": "Delete Selected Profiles", - "Deselect All": "Deselect All", - "Done": "Done", - "items": "items", - "Select All": "Select All", - "Selected": "Selected", - "Selected profiles deleted successfully": "Selected profiles deleted successfully", - "Prefer System Titlebar": "Prefer System Titlebar", - "App Log Max Size": "App Log Max Size", - "App Log Max Count": "App Log Max Count", - "Allow Auto Update": "Allow Auto Update", - "Menu reorder mode": "Menu reorder mode", - "Unlock menu order": "Unlock menu order", - "Lock menu order": "Lock menu order", - "Open App Log": "Open App Log", - "Open Core Log": "Open Core Log" -} diff --git a/src/locales/en/connections.json b/src/locales/en/connections.json new file mode 100644 index 000000000..4d5e53605 --- /dev/null +++ b/src/locales/en/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Connections" + }, + "components": { + "fields": { + "host": "Host", + "dlSpeed": "DL Speed", + "ulSpeed": "UL Speed", + "chains": "Chains", + "rule": "Rule", + "process": "Process", + "time": "Time", + "source": "Source", + "destination": "Destination", + "destinationPort": "Destination Port", + "type": "Type" + }, + "order": { + "default": "Default", + "uploadSpeed": "Upload Speed", + "downloadSpeed": "Download Speed" + }, + "actions": { + "closeConnection": "Close Connection" + } + } +} diff --git a/src/locales/en/home.json b/src/locales/en/home.json new file mode 100644 index 000000000..e1d9abbac --- /dev/null +++ b/src/locales/en/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Lightweight Mode", + "manual": "Manual", + "settings": "Home Settings" + }, + "cards": { + "trafficStats": "Traffic Stats", + "networkSettings": "Network Settings", + "proxyMode": "Proxy Mode" + }, + "settings": { + "cards": { + "profile": "Profile Card", + "currentProxy": "Current Proxy Card", + "network": "Network Settings Card", + "proxyMode": "Proxy Mode Card", + "traffic": "Traffic Stats Card", + "tests": "Website Tests Card", + "ip": "IP Information Card", + "clashInfo": "Clash Info Cards", + "systemInfo": "System Info Cards" + }, + "title": "Home Settings" + }, + "title": "Home" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "System Proxy Enabled", + "systemProxyDisabled": "System Proxy Disabled", + "tunModeServiceRequired": "TUN Mode Service Required", + "tunModeEnabled": "TUN Mode Enabled", + "tunModeDisabled": "TUN Mode Disabled" + }, + "tooltips": { + "systemProxy": "System Proxy Info", + "tunMode": "TUN Mode Intercept Info" + } + }, + "clashInfo": { + "title": "Clash Info", + "fields": { + "coreVersion": "Core Version", + "systemProxyAddress": "System Proxy Address", + "mixedPort": "Mixed Port", + "uptime": "Uptime", + "rulesCount": "Rules Count" + } + }, + "systemInfo": { + "title": "System Info", + "fields": { + "osInfo": "OS Info", + "autoLaunch": "Auto Launch", + "runningMode": "Running Mode", + "lastCheckUpdate": "Last Check Update", + "vergeVersion": "Verge Version" + }, + "actions": { + "settings": "Settings" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "Service Mode", + "sidecarMode": "User Mode", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP Information", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Auto refresh", + "unknown": "Unknown" + }, + "errors": { + "load": "Failed to get IP info" + } + }, + "currentProxy": { + "title": "Current Node", + "actions": { + "refreshDelay": "Delay check" + }, + "labels": { + "globalMode": "Global Mode", + "directMode": "Direct Mode", + "group": "Group", + "proxy": "Proxy", + "noActiveNode": "No active proxy node" + } + }, + "tests": { + "title": "Website Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Upload Speed", + "downloadSpeed": "Download Speed", + "activeConnections": "Active Connections", + "memoryUsage": "Core Usage" + }, + "legends": { + "upload": "Upload", + "download": "Download" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/en/index.ts b/src/locales/en/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/en/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/en/layout.json b/src/locales/en/layout.json new file mode 100644 index 000000000..7fafd7526 --- /dev/null +++ b/src/locales/en/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Home", + "proxies": "Proxies", + "profiles": "Profiles", + "connections": "Connections", + "rules": "Rules", + "logs": "Logs", + "unlock": "Test", + "settings": "Settings" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/en/logs.json b/src/locales/en/logs.json new file mode 100644 index 000000000..85afa00bb --- /dev/null +++ b/src/locales/en/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Logs" + } +} diff --git a/src/locales/en/profiles.json b/src/locales/en/profiles.json new file mode 100644 index 000000000..41bfd88cc --- /dev/null +++ b/src/locales/en/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Update All Profiles", + "viewRuntimeConfig": "View Runtime Config", + "reactivate": "Reactivate Profiles", + "import": "Import" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "Profile URL", + "actions": { + "paste": "Paste" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Only YAML Files Supported" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Profile Switched", + "profileReactivated": "Profile Reactivated", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Profiles" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Click to import subscription" + } + }, + "fileInput": { + "chooseFile": "Choose File" + }, + "menu": { + "home": "Home", + "select": "Select", + "editInfo": "Edit Info", + "editFile": "Edit File", + "editRules": "Edit Rules", + "editProxies": "Edit Proxies", + "editGroups": "Edit Proxy Groups", + "extendConfig": "Extend Config", + "extendScript": "Extend Script", + "openFile": "Open File", + "update": "Update", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Extend Config", + "script": "Global Extend Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Create Profile", + "edit": "Edit Profile" + }, + "fields": { + "type": "Type", + "description": "Descriptions", + "subscriptionUrl": "Subscription URL", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Update Interval", + "useSystemProxy": "Use System Proxy", + "useClashProxy": "Use Clash Proxy", + "acceptInvalidCerts": "Allows Invalid Certificates (Danger)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "Edit Proxies", + "placeholders": { + "multiUri": "Use newlines for multiple uri(Base64 encoding supported)" + }, + "actions": { + "prepend": "Prepend Proxy", + "append": "Append Proxy" + } + }, + "groupsEditor": { + "title": "Edit Proxy Groups", + "errors": { + "nameRequired": "Group Name Required", + "nameExists": "Group Name Already Exists" + }, + "fields": { + "type": "Group Type", + "name": "Group Name", + "icon": "Proxy Group Icon", + "proxies": "Use Proxies", + "provider": "Use Provider", + "healthCheckUrl": "Health Check Url", + "expectedStatus": "Expected Status", + "interval": "Interval", + "maxFailedTimes": "Max Failed Times", + "interfaceName": "Interface Name", + "routingMark": "Routing Mark", + "filter": "Filter", + "excludeFilter": "Exclude Filter", + "excludeType": "Exclude Type", + "includeAll": "Include All Proxies and Providers", + "includeAllProxies": "Include All Proxies", + "includeAllProviders": "Include All Providers" + }, + "toggles": { + "lazy": "Lazy", + "disableUdp": "Disable UDP", + "hidden": "Hidden" + }, + "actions": { + "prepend": "Prepend Group", + "append": "Append Group" + } + }, + "editor": { + "actions": { + "format": "Format document" + }, + "messages": { + "readOnly": "Cannot edit in read-only editor" + } + }, + "confirmDelete": { + "title": "Confirm deletion", + "message": "This operation is not reversible" + }, + "logViewer": { + "title": "Script Console" + } + } +} diff --git a/src/locales/en/proxies.json b/src/locales/en/proxies.json new file mode 100644 index 000000000..a359ee324 --- /dev/null +++ b/src/locales/en/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Chain Proxy", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Proxy Provider", + "actions": { + "updateAll": "Update All", + "update": "Update" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "Delay check to cancel fixed" + }, + "tooltips": { + "locate": "locate", + "delayCheck": "Delay check", + "sortDefault": "Sort by default", + "sortDelay": "Sort by delay", + "sortName": "Sort by name", + "delayCheckUrl": "Delay check URL", + "showBasic": "Proxy basic", + "showDetail": "Proxy detail", + "filter": "Filter" + }, + "placeholders": { + "delayCheckUrl": "Delay check URL" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Direct Mode" + }, + "title": { + "default": "Proxy Groups", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Select proxy manually", + "url-test": "Select proxy based on URL test delay", + "fallback": "Switch to another proxy on error", + "load-balance": "Distribute proxy based on load balancing", + "relay": "Pass through the defined proxy chain" + }, + "policies": { + "DIRECT": "Data goes directly outbound (DIRECT)", + "REJECT": "Intercepts requests (REJECT)", + "REJECT-DROP": "Discards requests (REJECT-DROP)", + "PASS": "Skips this rule when matched (PASS)" + } + } + } +} diff --git a/src/locales/en/rules.json b/src/locales/en/rules.json new file mode 100644 index 000000000..375314922 --- /dev/null +++ b/src/locales/en/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Rule Provider", + "dialogTitle": "Rule Providers", + "actions": { + "updateAll": "Update All", + "update": "Update" + } + }, + "title": "Rules" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Rule Type", + "content": "Rule Content", + "proxyPolicy": "Proxy Policy" + }, + "toggles": { + "noResolve": "No Resolve" + }, + "actions": { + "prependRule": "Prepend Rule", + "appendRule": "Append Rule" + }, + "validation": { + "conditionRequired": "Rule Condition Required", + "invalidRule": "Invalid Rule" + } + }, + "ruleTypes": { + "DOMAIN": "Match full domain (DOMAIN)", + "DOMAIN-SUFFIX": "Match domain suffix (DOMAIN-SUFFIX)", + "DOMAIN-KEYWORD": "Match domain keyword (DOMAIN-KEYWORD)", + "DOMAIN-REGEX": "Match domain using regex (DOMAIN-REGEX)", + "GEOSITE": "Match domains in Geosite (GEOSITE)", + "GEOIP": "Match IP country code (GEOIP)", + "SRC-GEOIP": "Match source IP country code (SRC-GEOIP)", + "IP-ASN": "Match IP ASN (IP-ASN)", + "SRC-IP-ASN": "Match source IP ASN (SRC-IP-ASN)", + "IP-CIDR": "Match IP address range (IP-CIDR)", + "IP-CIDR6": "Match IPv6 address range (IP-CIDR6)", + "SRC-IP-CIDR": "Match source IP address range (SRC-IP-CIDR)", + "IP-SUFFIX": "Match IP suffix range (IP-SUFFIX)", + "SRC-IP-SUFFIX": "Match source IP suffix range (SRC-IP-SUFFIX)", + "SRC-PORT": "Match source port range (SRC-PORT)", + "DST-PORT": "Match destination port range (DST-PORT)", + "IN-PORT": "Match inbound port (IN-PORT)", + "DSCP": "DSCP tag (TPROXY UDP inbound only) (DSCP)", + "PROCESS-NAME": "Match process name (PROCESS-NAME)", + "PROCESS-PATH": "Match full process path (PROCESS-PATH)", + "PROCESS-NAME-REGEX": "Match process name using regex (PROCESS-NAME-REGEX)", + "PROCESS-PATH-REGEX": "Match full process path using regex (PROCESS-PATH-REGEX)", + "NETWORK": "Match network protocol (TCP/UDP) (NETWORK)", + "UID": "Match Linux user ID (UID)", + "IN-TYPE": "Match inbound type (IN-TYPE)", + "IN-USER": "Match inbound username (IN-USER)", + "IN-NAME": "Match inbound name (IN-NAME)", + "SUB-RULE": "Sub-rule (SUB-RULE)", + "RULE-SET": "Match rule set (RULE-SET)", + "AND": "Logical AND (AND)", + "OR": "Logical OR (OR)", + "NOT": "Logical NOT (NOT)", + "MATCH": "Match all requests (MATCH)" + }, + "title": "Edit Rules" + } + } +} diff --git a/src/locales/en/settings.json b/src/locales/en/settings.json new file mode 100644 index 000000000..661ab2f72 --- /dev/null +++ b/src/locales/en/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Manual", + "telegram": "Telegram Channel", + "github": "Github Repo" + }, + "title": "Settings" + }, + "sections": { + "system": { + "title": "System Setting", + "toggles": { + "tunMode": "Tun Mode", + "systemProxy": "System Proxy" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "Start the program in background mode without displaying the panel" + }, + "fields": { + "autoLaunch": "Auto Launch", + "silentStart": "Silent Start" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Enable to modify the operating system's proxy settings. If enabling fails, modify the operating system's proxy settings manually", + "tunMode": "Tun (Virtual NIC) mode: Captures all system traffic, when enabled, there is no need to enable system proxy.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "Install Service", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "System Proxy", + "tunMode": "Tun Mode" + } + }, + "externalController": { + "title": "External Controller", + "fields": { + "enable": "Enable External Controller", + "address": "External Controller", + "secret": "Core Secret" + }, + "placeholders": { + "address": "Required", + "secret": "Recommended" + }, + "tooltips": { + "copy": "Copy to clipboard" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Failed to copy", + "controllerCopied": "Controller address copied to clipboard", + "secretCopied": "Secret copied to clipboard" + } + }, + "externalCors": { + "title": "External Cors Configuration", + "fields": { + "allowPrivateNetwork": "Allow private network access", + "allowedOrigins": "Allowed Origins" + }, + "placeholders": { + "origin": "Please enter a valid url" + }, + "actions": { + "add": "Add" + }, + "messages": { + "alwaysIncluded": "Always included origins: {{urls}}" + }, + "tooltips": { + "open": "External Cors Settings" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Clash Setting", + "form": { + "fields": { + "allowLan": "Allow LAN", + "dnsOverwrite": "DNS Overwrite", + "ipv6": "IPv6", + "unifiedDelay": "Unified Delay", + "logLevel": "Log Level", + "portConfig": "Port Config", + "external": "External", + "webUI": "Web UI", + "clashCore": "Clash Core", + "openUwpTool": "Open UWP tool", + "updateGeoData": "Update GeoData" + }, + "tooltips": { + "networkInterface": "Network Interface", + "unifiedDelay": "When unified delay is turned on, two delay tests will be performed to eliminate the delay differences between different types of nodes caused by connection handshakes, etc", + "logLevel": "This parameter is valid only for kernel log files in the log directory Service folder", + "openUwpTool": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge Basic Setting", + "actions": { + "browse": "Browse" + }, + "trayOptions": { + "showMainWindow": "Show Main Window", + "showTrayMenu": "Show Tray Menu", + "disable": "Disable" + }, + "fields": { + "language": "Language", + "themeMode": "Theme Mode", + "trayClickEvent": "Tray Click Event", + "copyEnvType": "Copy Env Type", + "startPage": "Start Page", + "startupScript": "Startup Script", + "themeSetting": "Theme Setting", + "layoutSetting": "Layout Setting", + "misc": "Miscellaneous", + "hotkeySetting": "Hotkey Setting" + } + }, + "advanced": { + "title": "Verge Advanced Setting", + "tooltips": { + "backupInfo": "Support local or WebDAV backup of configuration files", + "openConfDir": "If the software runs abnormally, BACKUP and delete all files in this folder then restart the software", + "liteMode": "Close the GUI and keep only the kernel running" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Currently on the Latest Version", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Backup Setting", + "runtimeConfig": "Runtime Config", + "openConfDir": "Open Conf Dir", + "openCoreDir": "Open Core Dir", + "openLogsDir": "Open Logs Dir", + "checkUpdates": "Check for Updates", + "openDevTools": "Dev Tools", + "liteModeSettings": "LightWeight Mode Settings", + "exit": "Exit", + "exportDiagnostics": "Export Diagnostic Info", + "vergeVersion": "Verge Version" + } + }, + "theme": { + "title": "Theme Setting", + "fields": { + "primaryColor": "Primary Color", + "secondaryColor": "Secondary Color", + "primaryText": "Primary Text", + "secondaryText": "Secondary Text", + "infoColor": "Info Color", + "warningColor": "Warning Color", + "errorColor": "Error Color", + "successColor": "Success Color", + "fontFamily": "Font Family", + "cssInjection": "CSS Injection" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Layout Setting", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Traffic Graph", + "memoryUsage": "Core Usage", + "proxyGroupIcon": "Proxy Group Icon", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Nav Icon", + "trayIcon": "Tray Icon", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Common Tray Icon", + "systemProxyTrayIcon": "System Proxy Tray Icon", + "tunTrayIcon": "Tun Tray Icon", + "enableTrayIcon": "Enable Tray Icon", + "enableTraySpeed": "Enable Tray Speed" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Monochrome", + "colorful": "Colorful", + "disable": "Disable" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Port Config", + "fields": { + "mixed": "Mixed Port", + "socks": "Socks Port", + "http": "Http(s) Port", + "redir": "Redir Port", + "tproxy": "Tproxy Port" + }, + "actions": { + "random": "Random Port" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Release Version", + "alpha": "Alpha Version" + } + }, + "liteMode": { + "title": "LightWeight Mode Settings", + "actions": { + "enterNow": "Enter LightWeight Mode Now" + }, + "toggles": { + "autoEnter": "Auto Enter LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time" + }, + "fields": { + "delay": "Auto Enter LightWeight Mode Delay" + }, + "messages": { + "autoEnterHint": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes" + } + }, + "backup": { + "title": "Backup Setting", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Backup", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Delete Backup", + "restore": "Restore", + "restoreBackup": "Restore Backup" + }, + "fields": { + "webdavUrl": "WebDAV Server URL", + "username": "Username", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "WebDAV URL cannot be empty", + "invalidWebdavUrl": "Invalid WebDAV URL format", + "usernameRequired": "Username cannot be empty", + "passwordRequired": "Password cannot be empty", + "webdavConfigSaved": "WebDAV configuration saved successfully", + "webdavConfigSaveFailed": "Failed to save WebDAV configuration: {{error}}", + "backupCreated": "Backup created successfully", + "backupFailed": "Backup failed: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Restore Success, App will restart in 1s", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Confirm to delete this backup file?", + "confirmRestore": "Confirm to restore this backup file?" + }, + "table": { + "filename": "Filename", + "backupTime": "Backup Time", + "actions": "Actions", + "noBackups": "No backups available", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Miscellaneous", + "fields": { + "appLogLevel": "App Log Level", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Auto Close Connections", + "autoCheckUpdate": "Auto Check Update", + "enableBuiltinEnhanced": "Enable Builtin Enhanced", + "proxyLayoutColumns": "Proxy Layout Columns", + "autoLogClean": "Auto Log Clean", + "autoDelayDetection": "Auto Delay Detection", + "defaultLatencyTest": "Default Latency Test", + "defaultLatencyTimeout": "Default Latency Timeout" + }, + "tooltips": { + "autoCloseConnections": "Terminate established connections when the proxy group selection or proxy mode changes", + "enableBuiltinEnhanced": "Compatibility handling for the configuration file", + "autoDelayDetection": "Periodically test the current node latency in the background", + "defaultLatencyTest": "Used for HTTP client request testing only and won't make a difference to the configuration file" + }, + "options": { + "proxyLayoutColumns": { + "auto": "Auto Columns" + }, + "autoLogClean": { + "never": "Never Clean", + "retainDays": "Retain {{n}} Days" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Go to Release Page", + "update": "Update" + }, + "messages": { + "portableError": "The portable version does not support in-app updates. Please manually download and replace it", + "breakChangeError": "This version is a major update and does not support in-app updates. Please uninstall it and manually download and install the new version" + } + }, + "sysproxy": { + "title": "System Proxy Setting", + "fieldsets": { + "currentStatus": "Current System Proxy" + }, + "fields": { + "enableStatus": "Enable Status:", + "serverAddr": "Server Addr: ", + "pacUrl": "PAC URL: ", + "proxyHost": "Proxy Host", + "usePacMode": "Use PAC Mode", + "proxyGuard": "Proxy Guard", + "guardDuration": "Guard Duration", + "alwaysUseDefaultBypass": "Always use Default Bypass", + "proxyBypass": "Proxy Bypass Settings: ", + "bypass": "Bypass: ", + "pacScriptContent": "PAC Script Content" + }, + "tooltips": { + "proxyGuard": "Enable to prevent other software from modifying the operating system's proxy settings" + }, + "messages": { + "durationTooShort": "Proxy Daemon Duration Cannot be Less than 1 Second", + "invalidBypass": "Invalid Bypass Format", + "invalidProxyHost": "Invalid Proxy Host Format" + }, + "actions": { + "editPac": "Edit PAC" + } + }, + "tun": { + "title": "Tun Mode", + "fields": { + "stack": "Tun Stack", + "device": "Device Name", + "autoRoute": "Auto Route", + "strictRoute": "Strict Route", + "autoDetectInterface": "Auto Detect Interface", + "dnsHijack": "DNS Hijack", + "mtu": "Max Transmission Unit" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Settings Applied" + } + }, + "dns": { + "dialog": { + "title": "DNS Overwrite", + "warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled" + }, + "sections": { + "general": "DNS Settings", + "fallbackFilter": "Fallback Filter Settings", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Enable DNS", + "listen": "DNS Listen", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Fake IP Range", + "fakeIpFilterMode": "Fake IP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Prefer H3", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Respect Rules", + "description": "DNS connections follow routing rules" + }, + "useHosts": { + "label": "Use Hosts", + "description": "Enable to resolve hosts through hosts file" + }, + "useSystemHosts": { + "label": "Use System Hosts", + "description": "Enable to resolve hosts through system hosts file" + }, + "directPolicy": { + "label": "Direct Nameserver Follow Policy", + "description": "Whether to follow nameserver policy" + }, + "defaultNameserver": { + "label": "Default Nameserver", + "description": "Default DNS servers used to resolve DNS servers" + }, + "nameserver": { + "label": "Nameserver", + "description": "List of DNS servers, comma separated" + }, + "fallback": { + "label": "Fallback", + "description": "List of fallback DNS servers, comma separated" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS servers for proxy node domain resolution" + }, + "directNameserver": { + "label": "Direct Nameserver", + "description": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated" + }, + "fakeIpFilter": { + "label": "Fake IP Filter", + "description": "Domains that skip fake IP resolution, comma separated" + }, + "nameserverPolicy": { + "label": "Nameserver Policy", + "description": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtering", + "description": "Enable GeoIP filtering for fallback" + }, + "geoipCode": "GeoIP Code", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "IP CIDRs not using fallback servers, comma separated" + }, + "fallbackDomain": { + "label": "Fallback Domain", + "description": "Domains using fallback servers, comma separated" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "Open URL" + }, + "title": "Web UI", + "messages": { + "supportedPlaceholders": "Support %host, %port, %secret", + "placeholderInstruction": "Replace host, port, secret with %host, %port, %secret" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Enable Global Hotkey" + }, + "title": "Hotkey Setting", + "functions": { + "rule": "Rule Mode", + "global": "Global Mode", + "openOrCloseDashboard": "Open/Close Dashboard", + "toggleSystemProxy": "Enable/Disable System Proxy", + "toggleTunMode": "Enable/Disable Tun Mode", + "entryLightweightMode": "Entry Lightweight Mode", + "direct": "Direct Mode" + } + }, + "password": { + "prompts": { + "enterRoot": "Please enter your root password" + } + }, + "networkInterface": { + "title": "Network Interface", + "fields": { + "ipAddress": "IP Address", + "macAddress": "MAC Address" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clash Core Restarted", + "versionUpdated": "Core Version Updated", + "alreadyLatestVersion": "Already Using Latest Core Version", + "changeSuccess": "Core changed successfully", + "changeFailed": "Failed to change core", + "geoDataUpdated": "GeoData Updated" + }, + "clashService": { + "installSuccess": "Service Installed Successfully", + "uninstallSuccess": "Service Uninstalled Successfully" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "Installing Service...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/en/shared.json b/src/locales/en/shared.json new file mode 100644 index 000000000..436164218 --- /dev/null +++ b/src/locales/en/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Cancel", + "close": "Close", + "confirm": "Confirm", + "save": "Save", + "delete": "Delete", + "edit": "Edit", + "new": "New", + "enable": "Enable", + "upgrade": "Upgrade", + "restart": "Restart", + "resetToDefault": "Reset to Default", + "refresh": "Refresh", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "List View", + "tableView": "Table View", + "pause": "Pause", + "resume": "Resume", + "closeAll": "Close All", + "clear": "Clear" + }, + "labels": { + "updateAt": "Update At", + "timeout": "Timeout", + "icon": "Icon", + "name": "Name", + "readOnly": "ReadOnly", + "expireTime": "Expire Time", + "updateTime": "Update Time", + "usedTotal": "Used / Total", + "from": "From", + "password": "Password", + "retryAttempts": "Retry attempts", + "downloaded": "Downloaded", + "uploaded": "Uploaded" + }, + "statuses": { + "enabled": "Enabled", + "disabled": "Disabled", + "saving": "Saving...", + "empty": "Empty" + }, + "units": { + "milliseconds": "ms", + "seconds": "seconds", + "minutes": "mins", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Filter conditions", + "matchCase": "Match Case", + "matchWholeWord": "Match Whole Word", + "useRegex": "Use Regular Expression" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Maximize", + "minimize": "Minimize" + }, + "editorModes": { + "visualization": "Visualization", + "advanced": "Advanced" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Profile Imported Successfully", + "importSubscriptionSuccess": "Import subscription successful", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Copy Success", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Subscription configuration validation failed. Please check the subscription configuration file; modifications have been rolled back.", + "bootFailed": "Boot subscription configuration validation failed. Started with the default configuration; please check the subscription configuration file.", + "coreChangeFailed": "Configuration validation failed when switching the kernel. Started with the default configuration; please check the subscription configuration file.", + "processTerminated": "The validation process has been terminated." + }, + "script": { + "syntaxError": "Script syntax error, changes reverted", + "missingMain": "Script error, changes reverted", + "fileNotFound": "File missing, changes reverted", + "fileError": "Script file error, changes reverted" + }, + "yaml": { + "syntaxError": "YAML syntax error, changes reverted", + "readError": "YAML read error, changes reverted", + "mappingError": "YAML mapping error, changes reverted", + "keyError": "YAML key error, changes reverted", + "generalError": "YAML error, changes reverted" + }, + "merge": { + "syntaxError": "Merge file syntax error, changes reverted", + "mappingError": "Merge file mapping error, changes reverted", + "keyError": "Merge file key error, changes reverted", + "generalError": "Merge file error, changes reverted" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/en/tests.json b/src/locales/en/tests.json new file mode 100644 index 000000000..22c585591 --- /dev/null +++ b/src/locales/en/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Test All" + }, + "title": "Test" + }, + "components": { + "item": { + "actions": { + "test": "Test" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Create Test", + "edit": "Edit Test" + }, + "fields": { + "url": "Test URL" + } + } + }, + "statuses": { + "test": { + "pending": "Pending", + "yes": "Yes", + "no": "No", + "failed": "Failed", + "completed": "Completed", + "disallowedIsp": "Disallowed ISP", + "originalsOnly": "Originals Only", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Unsupported Country/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Testing..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "Detection failed for {{name}}", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Unlock Test" + } + } +} diff --git a/src/locales/es.json b/src/locales/es.json deleted file mode 100644 index ede762259..000000000 --- a/src/locales/es.json +++ /dev/null @@ -1,563 +0,0 @@ -{ - "millis": "Milisegundos", - "seconds": "Segundos", - "mins": "Minutos", - "Back": "Volver", - "Close": "Cerrar", - "Cancel": "Cancelar", - "Confirm": "Confirmar", - "Maximize": "Maximizar", - "Minimize": "Minimizar", - "Format document": "Formatear documento", - "Empty": "Vacío", - "New": "Nuevo", - "Edit": "Editar", - "Save": "Guardar", - "Delete": "Eliminar", - "Enable": "Habilitar", - "Disable": "Deshabilitar", - "Label-Home": "Hogar", - "Label-Proxies": "Proxies", - "Label-Profiles": "Perfiles", - "Label-Connections": "Conexiones", - "Label-Rules": "Normas", - "Label-Logs": "Registros", - "Label-Unlock": "Descubrir", - "Label-Settings": "Ajustes", - "Proxy Groups": "Grupos de proxies", - "Proxy Provider": "Proveedor de proxies", - "Proxy Count": "Número de nodos", - "Update All": "Actualizar todo", - "Update At": "Actualizado el", - "rule": "Regla", - "global": "Global", - "direct": "Conexión directa", - "Chain Proxy": "🔗 Proxy en cadena", - "script": "Script", - "locate": "Nodo actual", - "Delay check": "Prueba de latencia", - "Sort by default": "Ordenación predeterminada", - "Sort by delay": "Ordenar por latencia", - "Sort by name": "Ordenar por nombre", - "Delay check URL": "URL de prueba de latencia", - "Delay check to cancel fixed": "Realizar prueba de latencia para cancelar la fijación", - "Proxy basic": "Ocultar detalles del nodo", - "Proxy detail": "Mostrar detalles del nodo", - "Profiles": "Suscripciones", - "Update All Profiles": "Actualizar todas las suscripciones", - "View Runtime Config": "Ver configuración en tiempo de ejecución", - "Reactivate Profiles": "Reactivar suscripciones", - "Paste": "Pegar", - "Profile URL": "Enlace del archivo de suscripción", - "Import": "Importar", - "From": "De", - "Update Time": "Hora de actualización", - "Used / Total": "Utilizado / Total", - "Expire Time": "Tiempo de expiración", - "Create Profile": "Crear configuración", - "Edit Profile": "Editar configuración", - "Edit Proxies": "Editar nodos", - "Use newlines for multiple uri": "Para múltiples URI, utilice saltos de línea (se admite la codificación Base64)", - "Edit Rules": "Editar reglas", - "Rule Type": "Tipo de regla", - "Rule Content": "Contenido de la regla", - "Proxy Policy": "Política de proxy", - "No Resolve": "Omitir resolución DNS", - "Prepend Rule": "Agregar regla previa", - "Append Rule": "Agregar regla posterior", - "Prepend Group": "Agregar grupo de proxy previo", - "Append Group": "Agregar grupo de proxy posterior", - "Prepend Proxy": "Agregar nodo de proxy previo", - "Append Proxy": "Agregar nodo de proxy posterior", - "Rule Condition Required": "Falta la condición de la regla", - "Invalid Rule": "Regla no válida", - "Advanced": "Avanzado", - "Visualization": "Visualización", - "DOMAIN": "Coincidir con el nombre de dominio completo", - "DOMAIN-SUFFIX": "Coincidir con el sufijo del nombre de dominio", - "DOMAIN-KEYWORD": "Coincidir con la palabra clave del nombre de dominio", - "DOMAIN-REGEX": "Coincidir con la expresión regular del nombre de dominio", - "GEOSITE": "Coincidir con los nombres de dominio en Geosite", - "GEOIP": "Coincidir con el código de país del IP", - "SRC-GEOIP": "Coincidir con el código de país del IP de origen", - "IP-ASN": "Coincidir con el ASN del IP", - "SRC-IP-ASN": "Coincidir con el ASN del IP de origen", - "IP-CIDR": "Coincidir con el rango de direcciones IP", - "IP-CIDR6": "Coincidir con el rango de direcciones IP", - "SRC-IP-CIDR": "Coincidir con el rango de direcciones IP de origen", - "IP-SUFFIX": "Coincidir con el rango de sufijos de IP", - "SRC-IP-SUFFIX": "Coincidir con el rango de sufijos de IP de origen", - "SRC-PORT": "Coincidir con el rango de puertos de origen de la solicitud", - "DST-PORT": "Coincidir con el rango de puertos de destino de la solicitud", - "IN-PORT": "Coincidir con el puerto de entrada", - "DSCP": "Etiqueta DSCP (solo para entradas UDP TPROXY)", - "PROCESS-NAME": "Coincidir con el nombre del proceso (nombre del paquete de Android)", - "PROCESS-PATH": "Coincidir con la ruta completa del proceso", - "PROCESS-NAME-REGEX": "Coincidir con el nombre completo del proceso mediante expresiones regulares (nombre del paquete de Android)", - "PROCESS-PATH-REGEX": "Coincidir con la ruta completa del proceso mediante expresiones regulares", - "NETWORK": "Coincidir con el protocolo de transporte (TCP/UDP)", - "UID": "Coincidir con el ID de usuario de Linux", - "IN-TYPE": "Coincidir con el tipo de entrada", - "IN-USER": "Coincidir con el nombre de usuario de entrada", - "IN-NAME": "Coincidir con el nombre de entrada", - "SUB-RULE": "Subregla", - "RULE-SET": "Coincidir con el conjunto de reglas", - "AND": "Y lógico", - "OR": "O lógico", - "NOT": "No lógico", - "MATCH": "Coincidir con todas las solicitudes", - "DIRECT": "Conexión directa", - "REJECT": "Rechazar solicitud", - "REJECT-DROP": "Descartar solicitud", - "PASS": "Saltar esta regla", - "Edit Groups": "Editar grupos de proxy", - "Group Type": "Tipo de grupo de proxy", - "select": "Seleccionar proxy manualmente", - "url-test": "Seleccionar proxy según la prueba de latencia de la URL", - "fallback": "Cambiar a otro proxy cuando no esté disponible", - "load-balance": "Asignar proxy según el equilibrio de carga", - "relay": "Transferir según la cadena de proxy definida", - "Group Name": "Nombre del grupo de proxy", - "Use Proxies": "Incluir proxies", - "Use Provider": "Incluir proveedor de proxies", - "Health Check Url": "URL de prueba de salud", - "Expected Status": "Código de estado esperado", - "Interval": "Intervalo de comprobación", - "Lazy": "Estado de inactividad", - "Timeout": "Tiempo de espera", - "Max Failed Times": "Número máximo de fallos", - "Interface Name": "Nombre de la interfaz de salida", - "Routing Mark": "Marca de enrutamiento", - "Include All": "Incluir todos los proxies de salida y proveedores de proxies", - "Include All Providers": "Incluir todos los proveedores de proxies", - "Include All Proxies": "Incluir todos los proxies de salida", - "Exclude Filter": "Excluir nodos", - "Exclude Type": "Tipo de nodo a excluir", - "Disable UDP": "Deshabilitar UDP", - "Hidden": "Ocultar grupo de proxy", - "Group Name Required": "El nombre del grupo de proxy no puede estar vacío", - "Group Name Already Exists": "El nombre del grupo de proxy ya existe", - "Extend Config": "Configurar sobrescritura extendida", - "Extend Script": "Script extendido", - "Type": "Tipo", - "Name": "Nombre", - "Descriptions": "Descripción", - "Subscription URL": "Enlace de suscripción", - "Update Interval": "Intervalo de actualización", - "Choose File": "Elegir archivo", - "Use System Proxy": "Usar proxy del sistema para actualizar", - "Use Clash Proxy": "Usar proxy del núcleo para actualizar", - "Refresh": "Actualizar", - "Home": "Inicio", - "Select": "Usar", - "Edit Info": "Editar información", - "Edit File": "Editar archivo", - "Open File": "Abrir archivo", - "Update": "Actualizar", - "Confirm deletion": "Confirmar eliminación", - "This operation is not reversible": "Esta operación no se puede deshacer", - "Script Console": "Salida de la consola del script", - "Connections": "Conexiones", - "Table View": "Vista de tabla", - "List View": "Vista de lista", - "Close All": "Cerrar todas", - "Upload": "Subir", - "Download": "Descargar", - "Download Speed": "Velocidad de descarga", - "Upload Speed": "Velocidad de subida", - "Host": "Host", - "Downloaded": "Descargado", - "Uploaded": "Subido", - "DL Speed": "Velocidad de descarga", - "UL Speed": "Velocidad de subida", - "Active Connections": "Conexiones activas", - "Chains": "Cadenas", - "Rule": "Regla", - "Process": "Proceso", - "Time": "Tiempo de conexión", - "Source": "Dirección de origen", - "Destination": "Dirección de destino", - "DestinationPort": "Puerto de destino", - "Close Connection": "Cerrar conexión", - "Rules": "Reglas", - "Rule Provider": "Proveedor de reglas", - "Logs": "Registros", - "Pause": "Pausar", - "Resume": "Reanudar", - "Clear": "Limpiar", - "Test": "Prueba", - "Test All": "Probar todo", - "Testing...": "Probando...", - "Create Test": "Crear prueba", - "Edit Test": "Editar prueba", - "Icon": "Icono", - "Test URL": "URL de prueba", - "Settings": "Ajustes", - "System Setting": "Ajustes del sistema", - "Tun Mode": "Modo de interfaz virtual (TUN)", - "Install Service": "Instalar servicio", - "Uninstall Service": "Desinstalar servicio", - "Reset to Default": "Restablecer a los valores predeterminados", - "Tun Mode Info": "El modo TUN (interfaz virtual) gestiona todo el tráfico del sistema. No es necesario habilitar el proxy del sistema cuando está activado.", - "TUN requires Service Mode or Admin Mode": "El modo TUN requiere el modo de servicio o el modo de administrador", - "System Proxy Enabled": "El proxy del sistema está habilitado. Sus aplicaciones accederán a Internet a través del proxy.", - "System Proxy Disabled": "El proxy del sistema está deshabilitado. Se recomienda a la mayoría de los usuarios habilitar esta opción.", - "TUN Mode Enabled": "El modo TUN está habilitado. Las aplicaciones accederán a Internet a través de la interfaz virtual.", - "TUN Mode Disabled": "El modo TUN está deshabilitado. Este modo es adecuado para aplicaciones especiales.", - "TUN Mode Service Required": "El modo TUN requiere el modo de servicio. Instale el servicio primero.", - "TUN Mode Intercept Info": "El modo TUN puede gestionar todo el tráfico de las aplicaciones. Es adecuado para aplicaciones que no siguen la configuración del proxy del sistema.", - "Stack": "Pila del modo TUN", - "Device": "Nombre de la interfaz TUN", - "Auto Route": "Configurar enrutamiento global automáticamente", - "Strict Route": "Enrutamiento estricto", - "Auto Detect Interface": "Detectar automáticamente la interfaz de salida del tráfico", - "DNS Hijack": "Secuestro de DNS", - "MTU": "Unidad máxima de transmisión", - "Service Mode": "Modo de servicio", - "active": "Activado", - "unknown": "Desconocido", - "Install": "Instalar", - "Uninstall": "Desinstalar", - "System Proxy": "Proxy del sistema", - "System Proxy Info": "Modifica la configuración del proxy del sistema operativo. Si no se puede habilitar, puede modificar manualmente la configuración del proxy del sistema operativo.", - "System Proxy Setting": "Configuración del proxy del sistema", - "Current System Proxy": "Proxy del sistema actual", - "Enable status": "Estado de habilitación: ", - "Enabled": "Habilitado", - "Disabled": "Deshabilitado", - "Server Addr": "Dirección del servidor: ", - "Proxy Host": "Host del proxy", - "Invalid Proxy Host Format": "Formato de host del proxy no válido", - "Not available": "No disponible", - "Proxy Guard": "Guardia del proxy del sistema", - "Proxy Guard Info": "Habilite esta opción para evitar que otros programas modifiquen la configuración del proxy del sistema operativo.", - "Guard Duration": "Intervalo de guardia del proxy", - "Always use Default Bypass": "Siempre usar la lista de omisión predeterminada", - "Proxy Bypass": "Configuración de omisión del proxy: ", - "Bypass": "Omisión actual: ", - "Use PAC Mode": "Usar modo PAC", - "PAC Script Content": "Contenido del script PAC", - "PAC URL": "URL del PAC: ", - "Auto Launch": "Inicio automático al arrancar el sistema", - "Administrator mode may not support auto launch": "El modo de administrador puede no admitir el inicio automático.", - "Silent Start": "Inicio silencioso", - "Silent Start Info": "El programa se ejecutará en segundo plano al iniciarse y no mostrará el panel.", - "TG Channel": "Canal de Telegram", - "Manual": "Manual de uso", - "Github Repo": "Dirección del proyecto en GitHub", - "Clash Setting": "Ajustes de Clash", - "Allow Lan": "Conexión a la red local", - "Network Interface": "Interfaz de red", - "Ip Address": "Dirección IP", - "Mac Address": "Dirección MAC", - "IPv6": "IPv6", - "Unified Delay": "Latencia unificada", - "Unified Delay Info": "Al habilitar la latencia unificada, se realizarán dos pruebas de latencia para eliminar las diferencias de latencia entre diferentes tipos de nodos causadas por el handshake de conexión, etc.", - "Log Level": "Nivel de registro", - "Log Level Info": "Solo se aplica al archivo de registro del núcleo en la carpeta Service del directorio de registros.", - "Port Config": "Configuración de puerto", - "Random Port": "Puerto aleatorio", - "Mixed Port": "Puerto de proxy mixto", - "Socks Port": "Puerto de proxy SOCKS", - "Http Port": "Puerto de proxy HTTP(S)", - "Redir Port": "Puerto de proxy transparente Redir", - "Tproxy Port": "Puerto de proxy transparente TPROXY", - "External": "Control externo", - "External Controller": "Dirección de escucha del controlador externo", - "Core Secret": "Clave de acceso a la API", - "Recommended": "Configuración recomendada", - "Open URL": "Abrir enlace", - "Replace host, port, secret with %host, %port, %secret": "Utilice %host, %port, %secret para representar el host, el puerto y la clave de acceso.", - "Support %host, %port, %secret": "Soporta %host, %port, %secret", - "Clash Core": "Núcleo de Clash", - "Upgrade": "Actualizar núcleo", - "Restart": "Reiniciar núcleo", - "Release Version": "Versión estable", - "Alpha Version": "Versión de vista previa", - "Please enter your root password": "Ingrese su contraseña de root", - "Open UWP tool": "Abrir herramienta UWP", - "Open UWP tool Info": "A partir de Windows 8, las aplicaciones UWP (como la Tienda de Microsoft) tienen restricciones para acceder directamente a los servicios de red del host local. Use esta herramienta para evitar esta restricción.", - "Update GeoData": "Actualizar GeoData", - "Verge Basic Setting": "Ajustes básicos de Verge", - "Verge Advanced Setting": "Ajustes avanzados de Verge", - "Language": "Configuración de idioma", - "Theme Mode": "Modo de tema", - "Tray Click Event": "Evento de clic en el icono de la bandeja", - "Show Main Window": "Mostrar ventana principal", - "Show Tray Menu": "Mostrar menú de la bandeja", - "Copy Env Type": "Copiar tipo de variable de entorno", - "Copy Success": "Copia exitosa", - "Start Page": "Página de inicio", - "Startup Script": "Script de inicio", - "Browse": "Examinar", - "Theme Setting": "Configuración de tema", - "Primary Color": "Color principal", - "Secondary Color": "Color secundario", - "Primary Text": "Color principal del texto", - "Secondary Text": "Color secundario del texto", - "Info Color": "Color de información", - "Warning Color": "Color de advertencia", - "Error Color": "Color de error", - "Success Color": "Color de éxito", - "Font Family": "Familia tipográfica", - "CSS Injection": "Inyección de CSS", - "Layout Setting": "Configuración de la interfaz", - "Traffic Graph": "Gráfico de tráfico", - "Memory Usage": "Uso de memoria del núcleo", - "Memory Cleanup": "Haga clic para limpiar la memoria", - "Proxy Group Icon": "Icono del grupo de proxy", - "Nav Icon": "Icono de la barra de navegación", - "Monochrome": "Icono monocromo", - "Colorful": "Icono colorido", - "Tray Icon": "Icono de la bandeja", - "Common Tray Icon": "Icono de bandeja común", - "System Proxy Tray Icon": "Icono de bandeja del proxy del sistema", - "Tun Tray Icon": "Icono de bandeja del modo TUN", - "Miscellaneous": "Ajustes varios", - "App Log Level": "Nivel de registro de la aplicación", - "Auto Close Connections": "Cerrar conexiones automáticamente", - "Auto Close Connections Info": "Cierra las conexiones establecidas cuando se cambia el nodo seleccionado en el grupo de proxy o el modo de proxy.", - "Auto Check Update": "Comprobar actualizaciones automáticamente", - "Enable Builtin Enhanced": "Habilitar funciones mejoradas integradas", - "Enable Builtin Enhanced Info": "Procesamiento de compatibilidad de archivos de configuración", - "Proxy Layout Columns": "Número de columnas en la disposición de la página de proxy", - "Auto Columns": "Número de columnas automático", - "Auto Log Clean": "Limpiar registros automáticamente", - "Never Clean": "No limpiar", - "Retain _n Days": "Retener {{n}} días", - "Auto Delay Detection": "Detección automática de latencia", - "Auto Delay Detection Info": "Prueba periódicamente la latencia del nodo actual en segundo plano", - "Default Latency Test": "Enlace de prueba de latencia predeterminado", - "Default Latency Test Info": "Solo se utiliza para pruebas de solicitudes de clientes HTTP y no afectará al archivo de configuración.", - "Default Latency Timeout": "Tiempo de espera de la prueba de latencia", - "Hotkey Setting": "Configuración de atajos de teclado", - "Enable Global Hotkey": "Habilitar atajos de teclado globales", - "open_or_close_dashboard": "Abrir/cerrar panel", - "clash_mode_rule": "Modo de reglas", - "clash_mode_global": "Modo global", - "clash_mode_direct": "Modo de conexión directa", - "toggle_system_proxy": "Activar/desactivar el proxy del sistema", - "toggle_tun_mode": "Activar/desactivar el modo TUN", - "entry_lightweight_mode": "Entrar en modo ligero", - "Backup Setting": "Configuración de copia de seguridad", - "Backup Setting Info": "Soporte para la copia de seguridad de archivos de configuración a través de WebDAV", - "Runtime Config": "Configuración actual", - "Open Conf Dir": "Directorio de configuración", - "Open Conf Dir Info": "Si el software no funciona correctamente, !realice una copia de seguridad! y elimine todos los archivos de esta carpeta, luego reinicie el software.", - "Open Core Dir": "Directorio del núcleo", - "Open Logs Dir": "Directorio de registros", - "Check for Updates": "Comprobar actualizaciones", - "Go to Release Page": "Ir a la página de lanzamiento", - "Portable Updater Error": "La versión portátil no admite la actualización desde dentro de la aplicación. Descargue e instale manualmente la actualización.", - "Break Change Update Error": "Esta es una actualización importante y no se admite la actualización desde dentro de la aplicación. Desinstale e instale manualmente la nueva versión.", - "Open Dev Tools": "Abrir herramientas de desarrollo", - "Export Diagnostic Info": "Exportar información de diagnóstico", - "Exit": "Salir", - "Verge Version": "Versión de Verge", - "ReadOnly": "Solo lectura", - "ReadOnlyMessage": "No se puede editar en modo de solo lectura", - "Filter": "Filtrar nodos", - "Filter conditions": "Condiciones de filtrado", - "Match Case": "Distinguir mayúsculas y minúsculas", - "Match Whole Word": "Coincidencia exacta de palabras", - "Use Regular Expression": "Usar expresiones regulares", - "Profile Imported Successfully": "Suscripción importada con éxito", - "Profile Switched": "Suscripción cambiada", - "Profile Reactivated": "Suscripción reactivada", - "Only YAML Files Supported": "Solo se admiten archivos YAML", - "Settings Applied": "Ajustes aplicados", - "Stopping Core...": "Deteniendo núcleo...", - "Restarting Core...": "Reiniciando núcleo...", - "Installing Service...": "Instalando servicio...", - "Uninstalling Service...": "Desinstalando servicio...", - "Service Installed Successfully": "Servicio instalado con éxito", - "Service Uninstalled Successfully": "Servicio desinstalado con éxito", - "Proxy Daemon Duration Cannot be Less than 1 Second": "El intervalo de tiempo del daemon de proxy no puede ser menor de 1 segundo", - "Invalid Bypass Format": "Formato de omisión de proxy no válido", - "Waiting for service to be ready...": "Esperando a que el servicio esté listo...", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "El servicio estaba listo, pero puede haber habido problemas al reiniciar el núcleo o el servicio se volvió inaccesible. Por favor, verifique.", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "Hubo problemas durante la instalación del servicio o al reiniciar el núcleo. El servicio podría no estar disponible. Por favor, revise los registros del sistema.", - "Service is ready and core restarted": "El servicio está listo y el núcleo se ha reiniciado", - "Core restarted. Service is now available.": "El núcleo se ha reiniciado. El servicio está disponible.", - "Core Version Updated": "Versión del núcleo actualizada", - "Clash Core Restarted": "Núcleo de Clash reiniciado", - "GeoData Updated": "GeoData actualizado", - "Currently on the Latest Version": "Actualmente está en la última versión", - "Import Subscription Successful": "Suscripción importada con éxito", - "WebDAV Server URL": "Dirección del servidor WebDAV http(s)://", - "Username": "Nombre de usuario", - "Password": "Contraseña", - "Backup": "Copia de seguridad", - "Filename": "Nombre del archivo", - "Actions": "Acciones", - "Restore": "Restaurar", - "No Backups": "No hay copias de seguridad", - "WebDAV URL Required": "La dirección del servidor WebDAV no puede estar vacía", - "Invalid WebDAV URL": "Formato de dirección del servidor WebDAV no válido", - "Username Required": "El nombre de usuario no puede estar vacío", - "Password Required": "La contraseña no puede estar vacía", - "WebDAV Config Saved": "Configuración de WebDAV guardada con éxito", - "WebDAV Config Save Failed": "Error al guardar la configuración de WebDAV: {{error}}", - "Backup Created": "Copia de seguridad creada con éxito", - "Backup Failed": "Error al crear la copia de seguridad: {{error}}", - "Delete Backup": "Eliminar copia de seguridad", - "Restore Backup": "Restaurar copia de seguridad", - "Backup Time": "Tiempo de copia de seguridad", - "Restore Success, App will restart in 1s": "Restauración exitosa. La aplicación se reiniciará en 1 segundo", - "Failed to fetch backup files": "Error al obtener las copias de seguridad", - "Profile": "Configuración", - "Web UI": "Interfaz web", - "Dashboard": "Panel de control", - "Restart App": "Reiniciar aplicación", - "Restart Clash Core": "Reiniciar el núcleo de Clash", - "TUN Mode": "Modo TUN", - "Copy Env": "Copiar variables de entorno", - "Conf Dir": "Directorio de configuración", - "Core Dir": "Directorio del núcleo", - "Logs Dir": "Directorio de registros", - "Open Dir": "Abrir directorio", - "More": "Más", - "Rule Mode": "Rule Mode", - "Global Mode": "Global Mode", - "Direct Mode": "Direct Mode", - "Enable Tray Speed": "Habilitar velocidad en la bandeja", - "Enable Tray Icon": "Habilitar icono de la bandeja", - "LightWeight Mode": "Modo ligero", - "LightWeight Mode Info": "Cierra la interfaz gráfica y solo mantiene el núcleo en ejecución", - "LightWeight Mode Settings": "Configuración del modo ligero", - "Enter LightWeight Mode Now": "Entrar en modo ligero ahora", - "Auto Enter LightWeight Mode": "Entrar automáticamente en modo ligero", - "Auto Enter LightWeight Mode Info": "Si se habilita, se activará automáticamente el modo ligero después de un tiempo de inactividad de la ventana.", - "Auto Enter LightWeight Mode Delay": "Retraso para entrar automáticamente en modo ligero", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "Después de cerrar la ventana, el modo ligero se activará automáticamente después de {{n}} minutos", - "Config Validation Failed": "Error de validación de la configuración de la suscripción. Compruebe el archivo de configuración de la suscripción. Los cambios se han deshecho. Detalles del error: ", - "Boot Config Validation Failed": "Error de validación de la configuración de la suscripción de arranque. Se ha iniciado con la configuración predeterminada. Compruebe el archivo de configuración de la suscripción. Detalles del error: ", - "Core Change Config Validation Failed": "Error de validación de la configuración al cambiar el núcleo. Se ha iniciado con la configuración predeterminada. Compruebe el archivo de configuración de la suscripción. Detalles del error: ", - "Config Validation Process Terminated": "Proceso de validación terminado", - "Script Syntax Error": "Error de sintaxis en el script. Los cambios se han deshecho", - "Script Missing Main": "Error en el script. Los cambios se han deshecho", - "File Not Found": "Archivo no encontrado. Los cambios se han deshecho", - "Script File Error": "Error en el archivo de script. Los cambios se han deshecho", - "Core Changed Successfully": "Núcleo cambiado con éxito", - "Failed to Change Core": "No se pudo cambiar el núcleo", - "YAML Syntax Error": "Error de sintaxis YAML. Los cambios se han deshecho", - "YAML Read Error": "Error al leer el archivo YAML. Los cambios se han deshecho", - "YAML Mapping Error": "Error de mapeo YAML. Los cambios se han deshecho", - "YAML Key Error": "Error de clave YAML. Los cambios se han deshecho", - "YAML Error": "Error YAML. Los cambios se han deshecho", - "Merge File Syntax Error": "Error de sintaxis en el archivo de sobrescritura. Los cambios se han deshecho", - "Merge File Mapping Error": "Error de mapeo en el archivo de sobrescritura. Los cambios se han deshecho", - "Merge File Key Error": "Error de clave en el archivo de sobrescritura. Los cambios se han deshecho", - "Merge File Error": "Error en el archivo de sobrescritura. Los cambios se han deshecho", - "Service Administrator Prompt": "Clash Verge requiere permisos de administrador para instalar el servicio del sistema", - "DNS Settings": "Configuración de DNS", - "DNS settings saved": "Configuración de DNS guardada", - "DNS Overwrite": "Sobrescritura de DNS", - "DNS Settings Warning": "Si no está seguro de cómo configurar esto, no realice cambios y mantenga habilitada la sobrescritura de DNS.", - "Enable DNS": "Habilitar DNS", - "DNS Listen": "Dirección de escucha de DNS", - "Enhanced Mode": "Modo mejorado", - "Fake IP Range": "Rango de Fake IP", - "Fake IP Filter Mode": "Modo de filtrado de Fake IP", - "Enable IPv6 DNS resolution": "Habilitar resolución DNS IPv6", - "Prefer H3": "Prefiere HTTP/3", - "DNS DOH使用HTTP/3": "DNS DOH utiliza el protocolo HTTP/3", - "Respect Rules": "Seguir las reglas de enrutamiento", - "DNS connections follow routing rules": "Las conexiones DNS siguen las reglas de enrutamiento", - "Use Hosts": "Usar archivo hosts", - "Enable to resolve hosts through hosts file": "Habilitar la resolución de nombres de host a través del archivo hosts", - "Use System Hosts": "Usar archivo hosts del sistema", - "Enable to resolve hosts through system hosts file": "Habilitar la resolución de nombres de host a través del archivo hosts del sistema", - "Direct Nameserver Follow Policy": "Los servidores DNS de conexión directa siguen la política", - "Whether to follow nameserver policy": "Si seguir la configuración de la política de servidores DNS", - "Default Nameserver": "Servidor DNS predeterminado", - "Default DNS servers used to resolve DNS servers": "Servidores DNS predeterminados utilizados para resolver servidores DNS", - "Nameserver": "Servidor DNS", - "List of DNS servers": "Lista de servidores DNS, separados por comas", - "Fallback": "Servidor de respaldo", - "List of fallback DNS servers": "Lista de servidores DNS de respaldo, separados por comas", - "Proxy Server Nameserver": "DNS del servidor proxy", - "Proxy Node Nameserver": "Servidor de resolución de nombres de dominio del nodo de proxy, separados por comas", - "Direct Nameserver": "Servidor DNS de conexión directa", - "Direct outbound Nameserver": "Servidor de resolución de nombres de dominio de salida directa, admite la palabra clave 'system', separados por comas", - "Fake IP Filter": "Filtro de Fake IP", - "Domains that skip fake IP resolution": "Dominios que omiten la resolución de Fake IP, separados por comas", - "Nameserver Policy": "Política de servidores DNS", - "Domain-specific DNS server": "Servidor DNS específico de dominio, múltiples servidores separados por punto y coma, formato: dominio=server1;server2", - "Fallback Filter Settings": "Configuración de filtrado de respaldo", - "GeoIP Filtering": "Filtrado GeoIP", - "Enable GeoIP filtering for fallback": "Habilitar el filtrado GeoIP de respaldo", - "GeoIP Code": "Código de país GeoIP", - "Fallback IP CIDR": "IP CIDR de respaldo", - "IP CIDRs not using fallback servers": "IP CIDR que no utilizan servidores de respaldo, separados por comas", - "Fallback Domain": "Dominio de respaldo", - "Domains using fallback servers": "Dominios que utilizan servidores de respaldo, separados por comas", - "Hosts Settings": "Configuración de hosts", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "Asignación personalizada de dominio a IP o dominio, separados por comas", - "Home Settings": "Configuración de la página de inicio", - "Profile Card": "Tarjeta de suscripción", - "Current Proxy Card": "Tarjeta de proxy actual", - "Network Settings Card": "Tarjeta de configuración de red", - "Proxy Mode Card": "Tarjeta de modo de proxy", - "Traffic Stats Card": "Tarjeta de estadísticas de tráfico", - "Clash Info Cards": "Tarjetas de información de Clash", - "System Info Cards": "Tarjetas de información del sistema", - "Website Tests Card": "Tarjeta de pruebas de sitios web", - "Traffic Stats": "Estadísticas de tráfico", - "Website Tests": "Pruebas de sitios web", - "Clash Info": "Información de Clash", - "Core Version": "Versión del núcleo", - "System Proxy Address": "Dirección del proxy del sistema", - "Uptime": "Tiempo de actividad", - "Rules Count": "Número de reglas", - "System Info": "Información del sistema", - "OS Info": "Información del sistema operativo", - "Running Mode": "Modo de ejecución", - "Sidecar Mode": "Modo de usuario", - "Administrator Mode": "Modo de administrador", - "Last Check Update": "Última comprobación de actualizaciones", - "Click to import subscription": "Haga clic para importar una suscripción", - "Last Update failed": "La última actualización falló", - "Next Up": "Próxima actualización", - "No schedule": "Sin programación", - "Unknown": "Desconocido", - "Auto update disabled": "La actualización automática está deshabilitada", - "Update subscription successfully": "Suscripción actualizada con éxito", - "Update with Clash proxy successfully": "Actualización con el proxy de Clash exitosa", - "Update failed even with Clash proxy": "Error al actualizar incluso con el proxy de Clash", - "Profile creation failed, retrying with Clash proxy...": "Error al crear la suscripción. Intentando con el proxy de Clash...", - "Profile creation succeeded with Clash proxy": "Creación de la suscripción con el proxy de Clash exitosa", - "Import failed, retrying with Clash proxy...": "Error al importar la suscripción. Intentando con el proxy de Clash...", - "Profile Imported with Clash proxy": "Suscripción importada con el proxy de Clash", - "Import failed even with Clash proxy": "Error al importar incluso con el proxy de Clash", - "Current Node": "Nodo actual", - "No active proxy node": "No hay nodos de proxy activos", - "Network Settings": "Configuración de red", - "Proxy Mode": "Modo de proxy", - "Group": "Grupo de proxy", - "Proxy": "Nodo", - "IP Information Card": "Tarjeta de información de IP", - "IP Information": "Información de IP", - "Failed to get IP info": "Error al obtener información de IP", - "ISP": "Proveedor de servicios de Internet", - "ASN": "Número de sistema autónomo", - "ORG": "Organización", - "Location": "Ubicación", - "Timezone": "Zona horaria", - "Auto refresh": "Actualización automática", - "Unlock Test": "Prueba de desbloqueo", - "Pending": "Pendiente de detección", - "Yes": "Soportado", - "No": "No soportado", - "Failed": "Prueba fallida", - "Completed": "Detección completada", - "Disallowed ISP": "Proveedor de servicios de Internet no permitido", - "Originals Only": "Solo originales", - "Unsupported Country/Region": "País/región no soportado", - "Configuration saved successfully": "Configuración aleatoria guardada correctamente", - "Controller address copied to clipboard": "El puerto API se copió al portapapeles", - "Secret copied to clipboard": "La clave API se copió al portapapeles", - "Copy to clipboard": "Haz clic aquí para copiar", - "Enable one-click random API port and key. Click to randomize the port and key": "Habilitar la generación de puerto y clave API aleatorios con un solo clic. Haz clic para randomizar el puerto y la clave" -} diff --git a/src/locales/es/connections.json b/src/locales/es/connections.json new file mode 100644 index 000000000..e40c6b526 --- /dev/null +++ b/src/locales/es/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Conexiones" + }, + "components": { + "fields": { + "host": "Host", + "dlSpeed": "Velocidad de descarga", + "ulSpeed": "Velocidad de subida", + "chains": "Cadenas", + "rule": "Regla", + "process": "Proceso", + "time": "Tiempo de conexión", + "source": "Dirección de origen", + "destination": "Dirección de destino", + "destinationPort": "Puerto de destino", + "type": "Tipo" + }, + "order": { + "default": "Default", + "uploadSpeed": "Velocidad de subida", + "downloadSpeed": "Velocidad de descarga" + }, + "actions": { + "closeConnection": "Cerrar conexión" + } + } +} diff --git a/src/locales/es/home.json b/src/locales/es/home.json new file mode 100644 index 000000000..1c33c5d91 --- /dev/null +++ b/src/locales/es/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Modo ligero", + "manual": "Manual de uso", + "settings": "Configuración de la página de inicio" + }, + "cards": { + "trafficStats": "Estadísticas de tráfico", + "networkSettings": "Configuración de red", + "proxyMode": "Modo de proxy" + }, + "settings": { + "cards": { + "profile": "Tarjeta de suscripción", + "currentProxy": "Tarjeta de proxy actual", + "network": "Tarjeta de configuración de red", + "proxyMode": "Tarjeta de modo de proxy", + "traffic": "Tarjeta de estadísticas de tráfico", + "tests": "Tarjeta de pruebas de sitios web", + "ip": "Tarjeta de información de IP", + "clashInfo": "Tarjetas de información de Clash", + "systemInfo": "Tarjetas de información del sistema" + }, + "title": "Configuración de la página de inicio" + }, + "title": "Hogar" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "El proxy del sistema está habilitado. Sus aplicaciones accederán a Internet a través del proxy.", + "systemProxyDisabled": "El proxy del sistema está deshabilitado. Se recomienda a la mayoría de los usuarios habilitar esta opción.", + "tunModeServiceRequired": "El modo TUN requiere el modo de servicio. Instale el servicio primero.", + "tunModeEnabled": "El modo TUN está habilitado. Las aplicaciones accederán a Internet a través de la interfaz virtual.", + "tunModeDisabled": "El modo TUN está deshabilitado. Este modo es adecuado para aplicaciones especiales." + }, + "tooltips": { + "systemProxy": "Modifica la configuración del proxy del sistema operativo. Si no se puede habilitar, puede modificar manualmente la configuración del proxy del sistema operativo.", + "tunMode": "El modo TUN puede gestionar todo el tráfico de las aplicaciones. Es adecuado para aplicaciones que no siguen la configuración del proxy del sistema." + } + }, + "clashInfo": { + "title": "Información de Clash", + "fields": { + "coreVersion": "Versión del núcleo", + "systemProxyAddress": "Dirección del proxy del sistema", + "mixedPort": "Mixed Port", + "uptime": "Tiempo de actividad", + "rulesCount": "Número de reglas" + } + }, + "systemInfo": { + "title": "Información del sistema", + "fields": { + "osInfo": "Información del sistema operativo", + "autoLaunch": "Inicio automático al arrancar el sistema", + "runningMode": "Modo de ejecución", + "lastCheckUpdate": "Última comprobación de actualizaciones", + "vergeVersion": "Versión de Verge" + }, + "actions": { + "settings": "Ajustes" + }, + "tooltips": { + "autoLaunchAdmin": "El modo de administrador puede no admitir el inicio automático." + }, + "badges": { + "adminMode": "Modo de administrador", + "serviceMode": "Modo de servicio", + "sidecarMode": "Modo de usuario", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "Información de IP", + "labels": { + "ip": "IP", + "asn": "Número de sistema autónomo", + "isp": "Proveedor de servicios de Internet", + "org": "Organización", + "location": "Ubicación", + "timezone": "Zona horaria", + "autoRefresh": "Actualización automática", + "unknown": "Desconocido" + }, + "errors": { + "load": "Error al obtener la información de IP" + } + }, + "currentProxy": { + "title": "Nodo actual", + "actions": { + "refreshDelay": "Prueba de latencia" + }, + "labels": { + "globalMode": "Global Mode", + "directMode": "Direct Mode", + "group": "Grupo de proxy", + "proxy": "Nodo", + "noActiveNode": "No hay nodos de proxy activos" + } + }, + "tests": { + "title": "Pruebas de sitios web" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Velocidad de subida", + "downloadSpeed": "Velocidad de descarga", + "activeConnections": "Conexiones activas", + "memoryUsage": "Uso de memoria del núcleo" + }, + "legends": { + "upload": "Subir", + "download": "Descargar" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Modo de reglas", + "global": "Modo global", + "direct": "Modo de conexión directa" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/es/index.ts b/src/locales/es/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/es/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/es/layout.json b/src/locales/es/layout.json new file mode 100644 index 000000000..217d6d706 --- /dev/null +++ b/src/locales/es/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Hogar", + "proxies": "Proxies", + "profiles": "Perfiles", + "connections": "Conexiones", + "rules": "Normas", + "logs": "Registros", + "unlock": "Descubrir", + "settings": "Ajustes" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/es/logs.json b/src/locales/es/logs.json new file mode 100644 index 000000000..fe479175f --- /dev/null +++ b/src/locales/es/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Registros" + } +} diff --git a/src/locales/es/profiles.json b/src/locales/es/profiles.json new file mode 100644 index 000000000..050ed8b21 --- /dev/null +++ b/src/locales/es/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Actualizar todas las suscripciones", + "viewRuntimeConfig": "Ver configuración en tiempo de ejecución", + "reactivate": "Reactivar suscripciones", + "import": "Importar" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "Enlace del archivo de suscripción", + "actions": { + "paste": "Pegar" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Solo se admiten archivos YAML" + }, + "notifications": { + "importRetry": "Error al importar la suscripción. Intentando con el proxy de Clash...", + "importFail": "Error al importar incluso con el proxy de Clash", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Suscripción cambiada", + "profileReactivated": "Suscripción reactivada", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Suscripciones" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Haga clic para importar una suscripción" + } + }, + "fileInput": { + "chooseFile": "Elegir archivo" + }, + "menu": { + "home": "Hogar", + "select": "Usar", + "editInfo": "Editar información", + "editFile": "Editar archivo", + "editRules": "Editar reglas", + "editProxies": "Editar nodos", + "editGroups": "Editar grupos de proxy", + "extendConfig": "Configurar sobrescritura extendida", + "extendScript": "Script extendido", + "openFile": "Abrir archivo", + "update": "Actualizar", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "La última actualización falló", + "nextUp": "Próxima actualización", + "noSchedule": "Sin programación", + "unknown": "Desconocido", + "autoUpdateDisabled": "La actualización automática está deshabilitada" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Crear configuración", + "edit": "Editar configuración" + }, + "fields": { + "type": "Tipo", + "description": "Descripción", + "subscriptionUrl": "Enlace de suscripción", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Intervalo de actualización", + "useSystemProxy": "Usar proxy del sistema para actualizar", + "useClashProxy": "Usar proxy del núcleo para actualizar", + "acceptInvalidCerts": "Allows Invalid Certificates (Danger)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Error al crear la suscripción. Intentando con el proxy de Clash...", + "creationSuccess": "Creación de la suscripción con el proxy de Clash exitosa" + } + } + }, + "proxiesEditor": { + "title": "Editar nodos", + "placeholders": { + "multiUri": "Para múltiples URI, utilice saltos de línea (se admite la codificación Base64)" + }, + "actions": { + "prepend": "Agregar nodo de proxy previo", + "append": "Agregar nodo de proxy posterior" + } + }, + "groupsEditor": { + "title": "Editar grupos de proxy", + "errors": { + "nameRequired": "El nombre del grupo de proxy no puede estar vacío", + "nameExists": "El nombre del grupo de proxy ya existe" + }, + "fields": { + "type": "Tipo de grupo de proxy", + "name": "Nombre del grupo de proxy", + "icon": "Icono del grupo de proxy", + "proxies": "Incluir proxies", + "provider": "Incluir proveedor de proxies", + "healthCheckUrl": "URL de prueba de salud", + "expectedStatus": "Código de estado esperado", + "interval": "Intervalo de comprobación", + "maxFailedTimes": "Número máximo de fallos", + "interfaceName": "Nombre de la interfaz de salida", + "routingMark": "Marca de enrutamiento", + "filter": "Filtrar nodos", + "excludeFilter": "Excluir nodos", + "excludeType": "Tipo de nodo a excluir", + "includeAll": "Incluir todos los proxies de salida y proveedores de proxies", + "includeAllProxies": "Incluir todos los proxies de salida", + "includeAllProviders": "Incluir todos los proveedores de proxies" + }, + "toggles": { + "lazy": "Estado de inactividad", + "disableUdp": "Deshabilitar UDP", + "hidden": "Ocultar grupo de proxy" + }, + "actions": { + "prepend": "Agregar grupo de proxy previo", + "append": "Agregar grupo de proxy posterior" + } + }, + "editor": { + "actions": { + "format": "Formatear documento" + }, + "messages": { + "readOnly": "No se puede editar en modo de solo lectura" + } + }, + "confirmDelete": { + "title": "Confirmar eliminación", + "message": "Esta operación no se puede deshacer" + }, + "logViewer": { + "title": "Salida de la consola del script" + } + } +} diff --git a/src/locales/es/proxies.json b/src/locales/es/proxies.json new file mode 100644 index 000000000..1699dd5ae --- /dev/null +++ b/src/locales/es/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Proxy en cadena", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Proveedor de proxies", + "actions": { + "updateAll": "Actualizar todo", + "update": "Actualizar" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Número de nodos", + "delayCheckReset": "Realizar prueba de latencia para cancelar la fijación" + }, + "tooltips": { + "locate": "Nodo actual", + "delayCheck": "Prueba de latencia", + "sortDefault": "Ordenación predeterminada", + "sortDelay": "Ordenar por latencia", + "sortName": "Ordenar por nombre", + "delayCheckUrl": "URL de prueba de latencia", + "showBasic": "Ocultar detalles del nodo", + "showDetail": "Mostrar detalles del nodo", + "filter": "Filtrar nodos" + }, + "placeholders": { + "delayCheckUrl": "URL de prueba de latencia" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Modo de conexión directa" + }, + "title": { + "default": "Grupos de proxies", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Seleccionar proxy manualmente", + "url-test": "Seleccionar proxy según la prueba de latencia de la URL", + "fallback": "Cambiar a otro proxy cuando no esté disponible", + "load-balance": "Asignar proxy según el equilibrio de carga", + "relay": "Transferir según la cadena de proxy definida" + }, + "policies": { + "DIRECT": "Conexión directa", + "REJECT": "Rechazar solicitud", + "REJECT-DROP": "Descartar solicitud", + "PASS": "Saltar esta regla" + } + } + } +} diff --git a/src/locales/es/rules.json b/src/locales/es/rules.json new file mode 100644 index 000000000..442fe13cd --- /dev/null +++ b/src/locales/es/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Proveedor de reglas", + "dialogTitle": "Proveedor de reglas", + "actions": { + "updateAll": "Actualizar todo", + "update": "Actualizar" + } + }, + "title": "Reglas" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Tipo de regla", + "content": "Contenido de la regla", + "proxyPolicy": "Política de proxy" + }, + "toggles": { + "noResolve": "Omitir resolución DNS" + }, + "actions": { + "prependRule": "Agregar regla previa", + "appendRule": "Agregar regla posterior" + }, + "validation": { + "conditionRequired": "Falta la condición de la regla", + "invalidRule": "Regla no válida" + } + }, + "ruleTypes": { + "DOMAIN": "Coincidir con el nombre de dominio completo", + "DOMAIN-SUFFIX": "Coincidir con el sufijo del nombre de dominio", + "DOMAIN-KEYWORD": "Coincidir con la palabra clave del nombre de dominio", + "DOMAIN-REGEX": "Coincidir con la expresión regular del nombre de dominio", + "GEOSITE": "Coincidir con los nombres de dominio en Geosite", + "GEOIP": "Coincidir con el código de país del IP", + "SRC-GEOIP": "Coincidir con el código de país del IP de origen", + "IP-ASN": "Coincidir con el ASN del IP", + "SRC-IP-ASN": "Coincidir con el ASN del IP de origen", + "IP-CIDR": "Coincidir con el rango de direcciones IP", + "IP-CIDR6": "Coincidir con el rango de direcciones IP", + "SRC-IP-CIDR": "Coincidir con el rango de direcciones IP de origen", + "IP-SUFFIX": "Coincidir con el rango de sufijos de IP", + "SRC-IP-SUFFIX": "Coincidir con el rango de sufijos de IP de origen", + "SRC-PORT": "Coincidir con el rango de puertos de origen de la solicitud", + "DST-PORT": "Coincidir con el rango de puertos de destino de la solicitud", + "IN-PORT": "Coincidir con el puerto de entrada", + "DSCP": "Etiqueta DSCP (solo para entradas UDP TPROXY)", + "PROCESS-NAME": "Coincidir con el nombre del proceso (nombre del paquete de Android)", + "PROCESS-PATH": "Coincidir con la ruta completa del proceso", + "PROCESS-NAME-REGEX": "Coincidir con el nombre completo del proceso mediante expresiones regulares (nombre del paquete de Android)", + "PROCESS-PATH-REGEX": "Coincidir con la ruta completa del proceso mediante expresiones regulares", + "NETWORK": "Coincidir con el protocolo de transporte (TCP/UDP)", + "UID": "Coincidir con el ID de usuario de Linux", + "IN-TYPE": "Coincidir con el tipo de entrada", + "IN-USER": "Coincidir con el nombre de usuario de entrada", + "IN-NAME": "Coincidir con el nombre de entrada", + "SUB-RULE": "Subregla", + "RULE-SET": "Coincidir con el conjunto de reglas", + "AND": "Y lógico", + "OR": "O lógico", + "NOT": "No lógico", + "MATCH": "Coincidir con todas las solicitudes" + }, + "title": "Editar reglas" + } + } +} diff --git a/src/locales/es/settings.json b/src/locales/es/settings.json new file mode 100644 index 000000000..cbc1d05ab --- /dev/null +++ b/src/locales/es/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Manual de uso", + "telegram": "Canal de Telegram", + "github": "Dirección del proyecto en GitHub" + }, + "title": "Ajustes" + }, + "sections": { + "system": { + "title": "Ajustes del sistema", + "toggles": { + "tunMode": "Modo de interfaz virtual (TUN)", + "systemProxy": "Proxy del sistema" + }, + "tooltips": { + "autoLaunchAdmin": "El modo de administrador puede no admitir el inicio automático.", + "silentStart": "El programa se ejecutará en segundo plano al iniciarse y no mostrará el panel." + }, + "fields": { + "autoLaunch": "Inicio automático", + "silentStart": "Inicio silencioso" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Modifica la configuración del proxy del sistema operativo. Si no se puede habilitar, puede modificar manualmente la configuración del proxy del sistema operativo.", + "tunMode": "El modo TUN (interfaz virtual) gestiona todo el tráfico del sistema. No es necesario habilitar el proxy del sistema cuando está activado.", + "tunUnavailable": "El modo TUN requiere el modo de servicio o el modo de administrador" + }, + "actions": { + "installService": "Instalar servicio", + "uninstallService": "Desinstalar servicio" + }, + "fields": { + "systemProxy": "Proxy del sistema", + "tunMode": "Modo de interfaz virtual (TUN)" + } + }, + "externalController": { + "title": "Dirección de escucha del controlador externo", + "fields": { + "enable": "Habilitar controlador externo", + "address": "Dirección de escucha del controlador externo", + "secret": "Clave de acceso a la API" + }, + "placeholders": { + "address": "Requerido", + "secret": "Configuración recomendada" + }, + "tooltips": { + "copy": "Copiar al portapapeles" + }, + "messages": { + "addressRequired": "La dirección del controlador no puede estar vacía", + "secretRequired": "La clave secreta no puede estar vacía", + "copyFailed": "Error al copiar", + "controllerCopied": "El puerto API se copió al portapapeles", + "secretCopied": "La clave API se copió al portapapeles" + } + }, + "externalCors": { + "title": "Configuración de CORS externo", + "fields": { + "allowPrivateNetwork": "Permitir acceso a red privada", + "allowedOrigins": "Orígenes permitidos" + }, + "placeholders": { + "origin": "Introduce una URL válida" + }, + "actions": { + "add": "Agregar" + }, + "messages": { + "alwaysIncluded": "Orígenes siempre incluidos: {{urls}}" + }, + "tooltips": { + "open": "Configuración de CORS externo" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Ajustes de Clash", + "form": { + "fields": { + "allowLan": "Conexión a la red local", + "dnsOverwrite": "Sobrescritura de DNS", + "ipv6": "IPv6", + "unifiedDelay": "Latencia unificada", + "logLevel": "Nivel de registro", + "portConfig": "Configuración de puerto", + "external": "Control externo", + "webUI": "Interfaz web", + "clashCore": "Núcleo de Clash", + "openUwpTool": "Abrir herramienta UWP", + "updateGeoData": "Actualizar GeoData" + }, + "tooltips": { + "networkInterface": "Interfaz de red", + "unifiedDelay": "Al habilitar la latencia unificada, se realizarán dos pruebas de latencia para eliminar las diferencias de latencia entre diferentes tipos de nodos causadas por el handshake de conexión, etc.", + "logLevel": "Solo se aplica al archivo de registro del núcleo en la carpeta Service del directorio de registros.", + "openUwpTool": "A partir de Windows 8, las aplicaciones UWP (como la Tienda de Microsoft) tienen restricciones para acceder directamente a los servicios de red del host local. Use esta herramienta para evitar esta restricción." + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Ajustes básicos de Verge", + "actions": { + "browse": "Examinar" + }, + "trayOptions": { + "showMainWindow": "Mostrar ventana principal", + "showTrayMenu": "Mostrar menú de la bandeja", + "disable": "Deshabilitar" + }, + "fields": { + "language": "Configuración de idioma", + "themeMode": "Modo de tema", + "trayClickEvent": "Evento de clic en el icono de la bandeja", + "copyEnvType": "Copiar tipo de variable de entorno", + "startPage": "Página de inicio", + "startupScript": "Script de inicio", + "themeSetting": "Configuración de tema", + "layoutSetting": "Configuración de la interfaz", + "misc": "Ajustes varios", + "hotkeySetting": "Configuración de atajos de teclado" + } + }, + "advanced": { + "title": "Ajustes avanzados de Verge", + "tooltips": { + "backupInfo": "Soporte para la copia de seguridad de archivos de configuración a través de WebDAV", + "openConfDir": "Si el software no funciona correctamente, !realice una copia de seguridad! y elimine todos los archivos de esta carpeta, luego reinicie el software.", + "liteMode": "Cierra la interfaz gráfica y solo mantiene el núcleo en ejecución" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Actualmente está en la última versión", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Configuración de copia de seguridad", + "runtimeConfig": "Configuración actual", + "openConfDir": "Directorio de configuración", + "openCoreDir": "Directorio del núcleo", + "openLogsDir": "Directorio de registros", + "checkUpdates": "Comprobar actualizaciones", + "openDevTools": "Abrir herramientas de desarrollo", + "liteModeSettings": "Configuración del modo ligero", + "exit": "Salir", + "exportDiagnostics": "Exportar información de diagnóstico", + "vergeVersion": "Versión de Verge" + } + }, + "theme": { + "title": "Configuración de tema", + "fields": { + "primaryColor": "Color principal", + "secondaryColor": "Color secundario", + "primaryText": "Color principal del texto", + "secondaryText": "Color secundario del texto", + "infoColor": "Color de información", + "warningColor": "Color de advertencia", + "errorColor": "Color de error", + "successColor": "Color de éxito", + "fontFamily": "Familia tipográfica", + "cssInjection": "Inyección de CSS" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Configuración de la interfaz", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Gráfico de tráfico", + "memoryUsage": "Uso de memoria del núcleo", + "proxyGroupIcon": "Icono del grupo de proxy", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Icono de la barra de navegación", + "trayIcon": "Icono de la bandeja", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Icono de bandeja común", + "systemProxyTrayIcon": "Icono de bandeja del proxy del sistema", + "tunTrayIcon": "Icono de bandeja del modo TUN", + "enableTrayIcon": "Habilitar icono de la bandeja", + "enableTraySpeed": "Habilitar velocidad en la bandeja" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Icono monocromo", + "colorful": "Icono colorido", + "disable": "Deshabilitar" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Configuración de puerto", + "fields": { + "mixed": "Puerto de proxy mixto", + "socks": "Puerto de proxy SOCKS", + "http": "Puerto de proxy HTTP(S)", + "redir": "Puerto de proxy transparente Redir", + "tproxy": "Puerto de proxy transparente TPROXY" + }, + "actions": { + "random": "Puerto aleatorio" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Versión estable", + "alpha": "Versión alfa" + } + }, + "liteMode": { + "title": "Configuración del modo ligero", + "actions": { + "enterNow": "Entrar en modo ligero ahora" + }, + "toggles": { + "autoEnter": "Entrar automáticamente en modo ligero" + }, + "tooltips": { + "autoEnter": "Si se habilita, se activará automáticamente el modo ligero después de un tiempo de inactividad de la ventana." + }, + "fields": { + "delay": "Retraso para entrar automáticamente en modo ligero" + }, + "messages": { + "autoEnterHint": "Después de cerrar la ventana, el modo ligero se activará automáticamente después de {{n}} minutos" + } + }, + "backup": { + "title": "Configuración de copia de seguridad", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Copia de seguridad", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Eliminar copia de seguridad", + "restore": "Restaurar", + "restoreBackup": "Restaurar copia de seguridad" + }, + "fields": { + "webdavUrl": "Dirección del servidor WebDAV http(s)://", + "username": "Nombre de usuario", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "La dirección del servidor WebDAV no puede estar vacía", + "invalidWebdavUrl": "Formato de dirección del servidor WebDAV no válido", + "usernameRequired": "El nombre de usuario no puede estar vacío", + "passwordRequired": "La contraseña no puede estar vacía", + "webdavConfigSaved": "Configuración de WebDAV guardada con éxito", + "webdavConfigSaveFailed": "Error al guardar la configuración de WebDAV: {{error}}", + "backupCreated": "Copia de seguridad creada con éxito", + "backupFailed": "Error al crear la copia de seguridad: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Restauración exitosa. La aplicación se reiniciará en 1 segundo", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Confirm to delete this backup file?", + "confirmRestore": "Confirm to restore this backup file?" + }, + "table": { + "filename": "Nombre del archivo", + "backupTime": "Tiempo de copia de seguridad", + "actions": "Acciones", + "noBackups": "No hay copias de seguridad", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Ajustes varios", + "fields": { + "appLogLevel": "Nivel de registro de la aplicación", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Cerrar conexiones automáticamente", + "autoCheckUpdate": "Comprobar actualizaciones automáticamente", + "enableBuiltinEnhanced": "Habilitar funciones mejoradas integradas", + "proxyLayoutColumns": "Número de columnas en la disposición de la página de proxy", + "autoLogClean": "Limpiar registros automáticamente", + "autoDelayDetection": "Detección automática de latencia", + "defaultLatencyTest": "Enlace de prueba de latencia predeterminado", + "defaultLatencyTimeout": "Tiempo de espera de la prueba de latencia" + }, + "tooltips": { + "autoCloseConnections": "Cierra las conexiones establecidas cuando se cambia el nodo seleccionado en el grupo de proxy o el modo de proxy.", + "enableBuiltinEnhanced": "Procesamiento de compatibilidad de archivos de configuración", + "autoDelayDetection": "Prueba periódicamente la latencia del nodo actual en segundo plano", + "defaultLatencyTest": "Solo se utiliza para pruebas de solicitudes de clientes HTTP y no afectará al archivo de configuración." + }, + "options": { + "proxyLayoutColumns": { + "auto": "Número de columnas automático" + }, + "autoLogClean": { + "never": "No limpiar", + "retainDays": "Retener {{n}} días" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Ir a la página de lanzamiento", + "update": "Actualizar" + }, + "messages": { + "portableError": "La versión portátil no admite la actualización desde dentro de la aplicación. Descargue e instale manualmente la actualización.", + "breakChangeError": "Esta es una actualización importante y no se admite la actualización desde dentro de la aplicación. Desinstale e instale manualmente la nueva versión." + } + }, + "sysproxy": { + "title": "Configuración del proxy del sistema", + "fieldsets": { + "currentStatus": "Proxy del sistema actual" + }, + "fields": { + "enableStatus": "Estado de habilitación: ", + "serverAddr": "Dirección del servidor: ", + "pacUrl": "URL del PAC: ", + "proxyHost": "Host del proxy", + "usePacMode": "Usar modo PAC", + "proxyGuard": "Guardia del proxy del sistema", + "guardDuration": "Intervalo de guardia del proxy", + "alwaysUseDefaultBypass": "Siempre usar la lista de omisión predeterminada", + "proxyBypass": "Configuración de omisión del proxy: ", + "bypass": "Omisión actual: ", + "pacScriptContent": "Contenido del script PAC" + }, + "tooltips": { + "proxyGuard": "Habilite esta opción para evitar que otros programas modifiquen la configuración del proxy del sistema operativo." + }, + "messages": { + "durationTooShort": "El intervalo de tiempo del daemon de proxy no puede ser menor de 1 segundo", + "invalidBypass": "Formato de omisión de proxy no válido", + "invalidProxyHost": "Formato de host del proxy no válido" + }, + "actions": { + "editPac": "Editar PAC" + } + }, + "tun": { + "title": "Modo de interfaz virtual (TUN)", + "fields": { + "stack": "Pila del modo TUN", + "device": "Device Name", + "autoRoute": "Configurar enrutamiento global automáticamente", + "strictRoute": "Enrutamiento estricto", + "autoDetectInterface": "Detectar automáticamente la interfaz de salida del tráfico", + "dnsHijack": "Secuestro de DNS", + "mtu": "Unidad máxima de transmisión" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Ajustes aplicados" + } + }, + "dns": { + "dialog": { + "title": "Sobrescritura de DNS", + "warning": "Si no está seguro de cómo configurar esto, no realice cambios y mantenga habilitada la sobrescritura de DNS." + }, + "sections": { + "general": "Configuración de DNS", + "fallbackFilter": "Configuración de filtrado de respaldo", + "hosts": "Configuración de hosts" + }, + "fields": { + "enable": "Habilitar DNS", + "listen": "Dirección de escucha de DNS", + "enhancedMode": "Modo mejorado", + "fakeIpRange": "Rango de Fake IP", + "fakeIpFilterMode": "Modo de filtrado de Fake IP", + "ipv6": { + "label": "IPv6", + "description": "Habilitar resolución DNS IPv6" + }, + "preferH3": { + "label": "Prefiere HTTP/3", + "description": "DNS DOH utiliza el protocolo HTTP/3" + }, + "respectRules": { + "label": "Seguir las reglas de enrutamiento", + "description": "Las conexiones DNS siguen las reglas de enrutamiento" + }, + "useHosts": { + "label": "Usar archivo hosts", + "description": "Habilitar la resolución de nombres de host a través del archivo hosts" + }, + "useSystemHosts": { + "label": "Usar archivo hosts del sistema", + "description": "Habilitar la resolución de nombres de host a través del archivo hosts del sistema" + }, + "directPolicy": { + "label": "Los servidores DNS de conexión directa siguen la política", + "description": "Si seguir la configuración de la política de servidores DNS" + }, + "defaultNameserver": { + "label": "Servidor DNS predeterminado", + "description": "Servidores DNS predeterminados utilizados para resolver servidores DNS" + }, + "nameserver": { + "label": "Servidor DNS", + "description": "Lista de servidores DNS, separados por comas" + }, + "fallback": { + "label": "Servidor de respaldo", + "description": "Lista de servidores DNS de respaldo, separados por comas" + }, + "proxy": { + "label": "DNS del servidor proxy", + "description": "Servidor de resolución de nombres de dominio del nodo de proxy, separados por comas" + }, + "directNameserver": { + "label": "Servidor DNS de conexión directa", + "description": "Servidor de resolución de nombres de dominio de salida directa, admite la palabra clave 'system', separados por comas" + }, + "fakeIpFilter": { + "label": "Filtro de Fake IP", + "description": "Dominios que omiten la resolución de Fake IP, separados por comas" + }, + "nameserverPolicy": { + "label": "Política de servidores DNS", + "description": "Servidor DNS específico de dominio, múltiples servidores separados por punto y coma, formato: dominio=server1;server2" + }, + "geoipFiltering": { + "label": "Filtrado GeoIP", + "description": "Habilitar el filtrado GeoIP de respaldo" + }, + "geoipCode": "Código de país GeoIP", + "fallbackIpCidr": { + "label": "IP CIDR de respaldo", + "description": "IP CIDR que no utilizan servidores de respaldo, separados por comas" + }, + "fallbackDomain": { + "label": "Dominio de respaldo", + "description": "Dominios que utilizan servidores de respaldo, separados por comas" + }, + "hosts": { + "label": "Hosts", + "description": "Asignación personalizada de dominio a IP o dominio, separados por comas" + } + }, + "messages": { + "saved": "Configuración de DNS guardada", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "Abrir enlace" + }, + "title": "Interfaz web", + "messages": { + "supportedPlaceholders": "Soporta %host, %port, %secret", + "placeholderInstruction": "Utilice %host, %port, %secret para representar el host, el puerto y la clave de acceso." + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Habilitar atajos de teclado globales" + }, + "title": "Configuración de atajos de teclado", + "functions": { + "rule": "Modo de reglas", + "global": "Modo global", + "openOrCloseDashboard": "Abrir/cerrar panel", + "toggleSystemProxy": "Activar/desactivar el proxy del sistema", + "toggleTunMode": "Activar/desactivar el modo TUN", + "entryLightweightMode": "Entrar en modo ligero", + "direct": "Modo de conexión directa" + } + }, + "password": { + "prompts": { + "enterRoot": "Ingrese su contraseña de root" + } + }, + "networkInterface": { + "title": "Interfaz de red", + "fields": { + "ipAddress": "Dirección IP", + "macAddress": "Dirección MAC" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Núcleo de Clash reiniciado", + "versionUpdated": "Versión del núcleo actualizada", + "alreadyLatestVersion": "Ya estás utilizando la versión más reciente del núcleo", + "changeSuccess": "Núcleo cambiado con éxito", + "changeFailed": "No se pudo cambiar el núcleo", + "geoDataUpdated": "GeoData actualizado" + }, + "clashService": { + "installSuccess": "Servicio instalado con éxito", + "uninstallSuccess": "Servicio desinstalado con éxito" + }, + "updater": { + "withClashProxySuccess": "Actualización con el proxy de Clash exitosa", + "withClashProxyFailed": "Error al actualizar incluso con el proxy de Clash" + } + } + }, + "statuses": { + "clash": { + "stopping": "Deteniendo núcleo...", + "restarting": "Reiniciando núcleo..." + }, + "clashService": { + "installing": "Instalando servicio...", + "uninstalling": "Desinstalando servicio..." + } + } +} diff --git a/src/locales/es/shared.json b/src/locales/es/shared.json new file mode 100644 index 000000000..cb06326a8 --- /dev/null +++ b/src/locales/es/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Cancelar", + "close": "Cerrar", + "confirm": "Confirmar", + "save": "Guardar", + "delete": "Eliminar", + "edit": "Editar", + "new": "Nuevo", + "enable": "Habilitar", + "upgrade": "Actualizar núcleo", + "restart": "Reiniciar núcleo", + "resetToDefault": "Restablecer a los valores predeterminados", + "refresh": "Actualizar", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Vista de lista", + "tableView": "Vista de tabla", + "pause": "Pausar", + "resume": "Reanudar", + "closeAll": "Cerrar todas", + "clear": "Limpiar" + }, + "labels": { + "updateAt": "Actualizado el", + "timeout": "Timeout", + "icon": "Icono", + "name": "Nombre", + "readOnly": "Solo lectura", + "expireTime": "Tiempo de expiración", + "updateTime": "Hora de actualización", + "usedTotal": "Utilizado / Total", + "from": "De", + "password": "Contraseña", + "retryAttempts": "Retry attempts", + "downloaded": "Descargado", + "uploaded": "Subido" + }, + "statuses": { + "enabled": "Habilitado", + "disabled": "Deshabilitado", + "saving": "Saving...", + "empty": "Vacío" + }, + "units": { + "milliseconds": "Milisegundos", + "seconds": "Segundos", + "minutes": "Minutos", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Condiciones de filtrado", + "matchCase": "Distinguir mayúsculas y minúsculas", + "matchWholeWord": "Coincidencia exacta de palabras", + "useRegex": "Usar expresiones regulares" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Maximizar", + "minimize": "Minimizar" + }, + "editorModes": { + "visualization": "Visualización", + "advanced": "Avanzado" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Suscripción importada con éxito", + "importSubscriptionSuccess": "Suscripción importada con éxito", + "importWithClashProxy": "Suscripción importada con el proxy de Clash", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Copia exitosa", + "saveSuccess": "Configuración aleatoria guardada correctamente", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Error de validación de la configuración de la suscripción. Compruebe el archivo de configuración de la suscripción. Los cambios se han deshecho. Detalles del error: ", + "bootFailed": "Error de validación de la configuración de la suscripción de arranque. Se ha iniciado con la configuración predeterminada. Compruebe el archivo de configuración de la suscripción. Detalles del error: ", + "coreChangeFailed": "Error de validación de la configuración al cambiar el núcleo. Se ha iniciado con la configuración predeterminada. Compruebe el archivo de configuración de la suscripción. Detalles del error: ", + "processTerminated": "Proceso de validación terminado" + }, + "script": { + "syntaxError": "Error de sintaxis en el script. Los cambios se han deshecho", + "missingMain": "Error en el script. Los cambios se han deshecho", + "fileNotFound": "Archivo no encontrado. Los cambios se han deshecho", + "fileError": "Error en el archivo de script. Los cambios se han deshecho" + }, + "yaml": { + "syntaxError": "Error de sintaxis YAML. Los cambios se han deshecho", + "readError": "Error al leer el archivo YAML. Los cambios se han deshecho", + "mappingError": "Error de mapeo YAML. Los cambios se han deshecho", + "keyError": "Error de clave YAML. Los cambios se han deshecho", + "generalError": "Error YAML. Los cambios se han deshecho" + }, + "merge": { + "syntaxError": "Error de sintaxis en el archivo de sobrescritura. Los cambios se han deshecho", + "mappingError": "Error de mapeo en el archivo de sobrescritura. Los cambios se han deshecho", + "keyError": "Error de clave en el archivo de sobrescritura. Los cambios se han deshecho", + "generalError": "Error en el archivo de sobrescritura. Los cambios se han deshecho" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/es/tests.json b/src/locales/es/tests.json new file mode 100644 index 000000000..43bc028b0 --- /dev/null +++ b/src/locales/es/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Probar todo" + }, + "title": "Prueba" + }, + "components": { + "item": { + "actions": { + "test": "Prueba" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Crear prueba", + "edit": "Editar prueba" + }, + "fields": { + "url": "URL de prueba" + } + } + }, + "statuses": { + "test": { + "pending": "Pendiente de detección", + "yes": "Soportado", + "no": "No soportado", + "failed": "Prueba fallida", + "completed": "Detección completada", + "disallowedIsp": "Proveedor de servicios de Internet no permitido", + "originalsOnly": "Solo originales", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "País/región no soportado", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Probando..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "Fallo en la detección para {{name}}", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Prueba de desbloqueo" + } + } +} diff --git a/src/locales/fa.json b/src/locales/fa.json deleted file mode 100644 index 346394f91..000000000 --- a/src/locales/fa.json +++ /dev/null @@ -1,460 +0,0 @@ -{ - "millis": "میلی‌ثانیه", - "seconds": "ثانیه‌ها", - "mins": "دقیقه", - "Back": "بازگشت", - "Close": "بستن", - "Cancel": "لغو", - "Confirm": "تأیید", - "Maximize": "بزرگ‌نمایی", - "Minimize": "کوچک‌نمایی", - "Format document": "فرمت‌بندی سند", - "Empty": "خالی خالی", - "New": "جدید", - "Edit": "ویرایش", - "Save": "ذخیره", - "Delete": "حذف", - "Enable": "فعال کردن", - "Disable": "غیرفعال کردن", - "Label-Proxies": "پراکسی‌ها", - "Label-Profiles": "پروفایل‌ها", - "Label-Connections": "اتصالات", - "Label-Rules": "قوانین", - "Label-Logs": "لاگ‌ها", - "Label-Settings": "تنظیمات", - "Proxies": "پراکسی‌ها", - "Proxy Groups": "گروه‌های پراکسی", - "Proxy Provider": "تأمین‌کننده پروکسی", - "Update All": "به‌روزرسانی همه", - "Update At": "به‌روزرسانی در", - "rule": "قانون", - "global": "جهانی", - "direct": "مستقیم", - "Chain Proxy": "🔗 پراکسی زنجیره‌ای", - "script": "اسکریپت", - "locate": "موقعیت", - "Delay check": "بررسی تأخیر", - "Sort by default": "مرتب‌سازی بر اساس پیش‌فرض", - "Sort by delay": "مرتب‌سازی بر اساس تأخیر", - "Sort by name": "مرتب‌سازی بر اساس نام", - "Delay check URL": "آدرس بررسی تأخیر", - "Delay check to cancel fixed": "بررسی تأخیر برای لغو ثابت", - "Proxy basic": "پراکسی پایه", - "Proxy detail": "جزئیات پراکسی", - "Profiles": "پروفایل‌ها", - "Update All Profiles": "به‌روزرسانی همه پروفایل‌ها", - "View Runtime Config": "مشاهده پیکربندی زمان اجرا", - "Reactivate Profiles": "فعال‌سازی مجدد پروفایل‌ها", - "Paste": "چسباندن", - "Profile URL": "آدرس پروفایل", - "Import": "وارد کردن", - "From": "از", - "Update Time": "زمان به‌روزرسانی", - "Used / Total": "استفاده‌شده / کل", - "Expire Time": "زمان انقضا", - "Create Profile": "ایجاد پروفایل", - "Edit Profile": "ویرایش پروفایل", - "Edit Proxies": "ویرایش پروکسی‌ها", - "Use newlines for multiple uri": "استفاده از خطوط جدید برای چندین آدرس (پشتیبانی از رمزگذاری Base64)", - "Edit Rules": "ویرایش قوانین", - "Rule Type": "نوع قانون", - "Rule Content": "محتوای قانون", - "Proxy Policy": "سیاست پروکسی", - "No Resolve": "بدون حل", - "Prepend Rule": "اضافه کردن قانون به ابتدا", - "Append Rule": "اضافه کردن قانون به انتها", - "Prepend Group": "اضافه کردن گروه به ابتدا", - "Append Group": "اضافه کردن گروه به انتها", - "Prepend Proxy": "پیش‌افزودن پراکسی", - "Append Proxy": "پس‌افزودن پراکسی", - "Rule Condition Required": "شرط قانون الزامی است", - "Invalid Rule": "قانون نامعتبر", - "Advanced": "پیشرفته", - "Visualization": "تجسم", - "DOMAIN": "مطابقت با نام کامل دامنه", - "DOMAIN-SUFFIX": "مطابقت با پسوند دامنه", - "DOMAIN-KEYWORD": "مطابقت با کلمه کلیدی دامنه", - "DOMAIN-REGEX": "مطابقت با دامنه با استفاده از عبارات منظم", - "GEOSITE": "مطابقت با دامنه‌های درون Geosite", - "GEOIP": "مطابقت با کد کشور IP", - "SRC-GEOIP": "مطابقت با کد کشور IP مبدا", - "IP-ASN": "مطابقت با ASN آدرس IP", - "SRC-IP-ASN": "مطابقت با ASN آدرس IP مبدا", - "IP-CIDR": "مطابقت با محدوده آدرس IP", - "IP-CIDR6": "مطابقت با محدوده آدرس IPv6", - "SRC-IP-CIDR": "مطابقت با محدوده آدرس IP مبدا", - "IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP", - "SRC-IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP مبدا", - "SRC-PORT": "مطابقت با محدوده پورت مبدا", - "DST-PORT": "مطابقت با محدوده پورت مقصد", - "IN-PORT": "مطابقت با پورت ورودی", - "DSCP": "علامت‌گذاری DSCP (فقط برای tproxy UDP ورودی)", - "PROCESS-NAME": "مطابقت با نام فرآیند (نام بسته Android)", - "PROCESS-PATH": "مطابقت با مسیر کامل فرآیند", - "PROCESS-NAME-REGEX": "مطابقت با نام فرآیند با استفاده از عبارات منظم (نام بسته Android)", - "PROCESS-PATH-REGEX": "مطابقت با مسیر کامل فرآیند با استفاده از عبارات منظم", - "NETWORK": "مطابقت با پروتکل انتقال (tcp/udp)", - "UID": "مطابقت با شناسه کاربری Linux", - "IN-TYPE": "مطابقت با نوع ورودی", - "IN-USER": "مطابقت با نام کاربری ورودی", - "IN-NAME": "مطابقت با نام ورودی", - "SUB-RULE": "قانون فرعی", - "RULE-SET": "مطابقت با مجموعه قوانین", - "AND": "منطق AND", - "OR": "منطق OR", - "NOT": "منطق NOT", - "MATCH": "مطابقت با تمام درخواست‌ها", - "DIRECT": "داده‌ها به صورت مستقیم خروجی می‌شوند", - "REJECT": "درخواست‌ها را متوقف می‌کند", - "REJECT-DROP": "درخواست‌ها را نادیده می‌گیرد", - "PASS": "این قانون را در صورت تطابق نادیده می‌گیرد", - "Edit Groups": "ویرایش گروه‌های پروکسی", - "Group Type": "نوع گروه", - "select": "انتخاب پروکسی به صورت دستی", - "url-test": "انتخاب پروکسی بر اساس تأخیر آزمایش URL", - "fallback": "تعویض به پروکسی دیگر در صورت بروز خطا", - "load-balance": "توزیع پراکسی بر اساس توازن بار", - "relay": "عبور از زنجیره پروکسی تعریف شده", - "Group Name": "نام گروه", - "Use Proxies": "استفاده از پروکسی‌ها", - "Use Provider": "استفاده از ارائه‌دهنده", - "Health Check Url": "آدرس بررسی سلامت", - "Expected Status": "وضعیت مورد انتظار", - "Interval": "فاصله زمانی", - "Lazy": "تنبل", - "Timeout": "زمان قطع", - "Max Failed Times": "حداکثر تعداد شکست‌ها", - "Interface Name": "نام رابط", - "Routing Mark": "علامت مسیریابی", - "Include All": "شامل همه پروکسی‌ها و ارائه‌دهنده‌ها", - "Include All Providers": "شامل همه ارائه‌دهنده‌ها", - "Include All Proxies": "شامل همه پروکسی‌ها", - "Exclude Filter": "فیلتر استثناء", - "Exclude Type": "نوع استثناء", - "Disable UDP": "غیرفعال کردن UDP", - "Hidden": "مخفی", - "Group Name Required": "نام گروه مورد نیاز است", - "Group Name Already Exists": "نام گروه قبلا وجود دارد", - "Extend Config": "توسعه پیکربندی", - "Extend Script": "ادغام اسکریپت", - "Global Merge": "تنظیمات گسترده‌ی سراسری", - "Global Script": "اسکریپت گسترش سراسری", - "Type": "نوع", - "Name": "نام", - "Descriptions": "توضیحات", - "Subscription URL": "آدرس اشتراک", - "Update Interval": "فاصله زمانی به‌روزرسانی", - "Choose File": "انتخاب فایل", - "Use System Proxy": "استفاده از پراکسی سیستم", - "Use Clash Proxy": "استفاده از پراکسی Clash", - "Accept Invalid Certs (Danger)": "پذیرش گواهی‌نامه‌های نامعتبر (خطرناک)", - "Refresh": "بازنشانی", - "Home": "خانه", - "Select": "انتخاب", - "Edit Info": "ویرایش اطلاعات", - "Edit File": "ویرایش فایل", - "Open File": "باز کردن فایل", - "Update": "به‌روزرسانی", - "Update(Proxy)": "به‌روزرسانی (پراکسی)", - "Confirm deletion": "تأیید حذف", - "This operation is not reversible": "این عملیات قابل برگشت نیست", - "Script Console": "کنسول اسکریپت", - "To Top": "به بالا", - "To End": "به پایان", - "Connections": "اتصالات", - "Table View": "نمای جدولی", - "List View": "نمای لیستی", - "Close All": "بستن همه", - "Download Speed": "سرعت دانلود", - "Upload Speed": "سرعت بارگذاری", - "Host": "میزبان", - "Downloaded": "دانلود شده", - "Uploaded": "بارگذاری شده", - "DL Speed": "سرعت دانلود", - "UL Speed": "سرعت بارگذاری", - "Chains": "زنجیره‌ها", - "Rule": "قانون", - "Process": "فرآیند", - "Time": "زمان", - "Source": "منبع", - "Destination": "آدرس IP مقصد", - "DestinationPort": "بندر هدف", - "Close Connection": "بستن اتصال", - "Rules": "قوانین", - "Rule Provider": "تأمین‌کننده قانون", - "Logs": "لاگ‌ها", - "Pause": "توقف", - "Resume": "از سرگیری", - "Clear": "پاک کردن", - "Test": "آزمون", - "Test All": "آزمون همه", - "Create Test": "ایجاد آزمون", - "Edit Test": "ویرایش آزمون", - "Icon": "آیکون", - "Test URL": "آدرس آزمون", - "Settings": "تنظیمات", - "System Setting": "تنظیمات سیستم", - "Tun Mode": "Tun (کارت شبکه مجازی)", - "TUN requires Service Mode": "حالت تونل‌زنی نیاز به سرویس دارد", - "Install Service": "نصب سرویس", - "Reset to Default": "بازنشانی به پیش‌فرض", - "Tun Mode Info": "حالت Tun (NIC مجازی): تمام ترافیک سیستم را ضبط می کند، وقتی فعال باشد، نیازی به فعال کردن پروکسی سیستم نیست.", - "Stack": "انباشته Tun", - "System and Mixed Can Only be Used in Service Mode": "سیستم و ترکیبی تنها می‌توانند در حالت سرویس استفاده شوند", - "Device": "نام دستگاه", - "Auto Route": "مسیر خودکار", - "Strict Route": "مسیر دقیق", - "Auto Detect Interface": "تشخیص خودکار رابط", - "DNS Hijack": "ربایش DNS", - "MTU": "واحد حداکثر انتقال", - "Service Mode": "حالت سرویس", - "Service Mode Info": "لطفاً قبل از فعال کردن حالت TUN، حالت سرویس را نصب کنید.", - "Current State": "وضعیت فعلی", - "pending": "در انتظار", - "installed": "نصب شده", - "uninstall": "حذف شده", - "active": "فعال", - "unknown": "ناشناخته", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "اطلاعات: لطفاً مطمئن شوید که سرویس Clash Verge نصب و فعال شده است", - "Install": "نصب", - "Uninstall": "حذف نصب", - "Disable Service Mode": "غیرفعال کردن حالت سرویس", - "System Proxy": "پراکسی سیستم", - "System Proxy Info": "به امکانات تنظیم پروکسی سیستم عامل دسترسی پیدا کنید. اگر فعال‌سازی ناموفق بود، پروکسی سیستم عامل را به‌صورت دستی تغییر دهید", - "System Proxy Setting": "تنظیمات پراکسی سیستم", - "Current System Proxy": "پراکسی سیستم فعلی", - "Enable status": "وضعیت فعال", - "Enabled": "توانایی فعال شد", - "Disabled": "غیرفعال شد", - "Server Addr": "آدرس سرور: ", - "Proxy Host": "میزبان پراکسی", - "Invalid Proxy Host Format": "فرمت میزبان پراکسی نامعتبر است", - "Not available": "غیر فعال شد", - "Proxy Guard": "محافظ پراکسی", - "Proxy Guard Info": "امکان جلوگیری از نرم‌افزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید", - "Guard Duration": "مدت محافظت", - "Always use Default Bypass": "همیشه از دور زدن پیش‌فرض استفاده کنید", - "Use Bypass Check": "استخدم التحقق من التحايل", - "Proxy Bypass": "دور زدن پراکسی: ", - "Bypass": "دور زدن: ", - "Use PAC Mode": "استفاده از حالت PAC", - "PAC Script Content": "محتوای اسکریپت PAC", - "PAC URL": "PAC URL: ", - "Auto Launch": "راه‌اندازی خودکار", - "Silent Start": "شروع بی‌صدا", - "Silent Start Info": "برنامه را در حالت پس‌زمینه بدون نمایش پانل اجرا کنید", - "TG Channel": "کانال تلگرام", - "Manual": "راهنما", - "Github Repo": "مخزن GitHub", - "Clash Setting": "تنظیمات Clash", - "Allow Lan": "اجازه LAN", - "Network Interface": "رابط شبکه", - "Ip Address": "آدرس IP", - "Mac Address": "آدرس MAC", - "IPv6": "IPv6", - "Unified Delay": "معادلDELAY", - "Unified Delay Info": "معادلDELAY را فعال کنید تا ترافیک شبکه به سرعت رسید", - "Log Level": "سطح لاگ", - "Log Level Info": "این فقط روی فایل‌های لاگ هسته تحت فایل سرویس در فهرست ورود اثر می‌گذارد.", - "Port Config": "پیکربندی پورت", - "Random Port": "پورت تصادفی", - "Mixed Port": "پورت پروکسی ترکیبی", - "Socks Port": "پورت پروکسی Socks", - "Http Port": "پورت پروکسی Http(s)", - "Redir Port": "پورت پروکسی شفاف Redir", - "Tproxy Port": "پورت پروکسی شفاف Tproxy", - "External": "خارجی", - "External Controller": "کنترل‌کننده خارجی", - "Core Secret": "رمز اصلی", - "Recommended": "توصیه شده", - "Open URL": "باز کردن آدرس اینترنتی", - "Replace host, port, secret with %host, %port, %secret": "جایگزین کردن میزبان، پورت و رمز با %host، %port، %secret", - "Support %host, %port, %secret": "پشتیبانی از %host، %port و %secret", - "Clash Core": "هسته Clash", - "Upgrade": "ارتقاء", - "Restart": "راه‌اندازی مجدد", - "Release Version": "نسخه نهایی", - "Alpha Version": "نسخه آلفا", - "Please enter your root password": "لطفاً رمز ریشه خود را وارد کنید", - "Grant": "اعطا", - "Open UWP tool": "باز کردن ابزار UWP", - "Open UWP tool Info": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود", - "Update GeoData": "به‌روزرسانی GeoData", - "Verge Basic Setting": "تنظیمات پایه Verge", - "Verge Advanced Setting": "تنظیمات پیشرفته Verge", - "Language": "زبان", - "Theme Mode": "حالت تم", - "theme.light": "روشن", - "theme.dark": "تاریک", - "theme.system": "سیستم", - "Tray Click Event": "رویداد کلیک در سینی سیستم", - "Show Main Window": "نمایش پنجره اصلی", - "Copy Env Type": "کپی نوع محیط", - "Copy Success": "کپی با موفقیت انجام شد", - "Start Page": "صفحه شروع", - "Startup Script": "اسکریپت راه‌اندازی", - "Browse": "مرور کردن", - "Theme Setting": "تنظیمات تم", - "Primary Color": "رنگ اصلی", - "Secondary Color": "رنگ ثانویه", - "Primary Text": "متن اصلی", - "Secondary Text": "متن ثانویه", - "Info Color": "رنگ اطلاعات", - "Warning Color": "رنگ هشدار", - "Error Color": "رنگ خطا", - "Success Color": "رنگ موفقیت", - "Font Family": "خانواده فونت", - "CSS Injection": "تزریق CSS", - "Layout Setting": "تنظیمات چیدمان", - "Traffic Graph": "نمودار ترافیک", - "Memory Usage": "استفاده از حافظه", - "Memory Cleanup": "برای پاکسازی حافظه ضربه بزنید", - "Proxy Group Icon": "آیکون گروه پراکسی", - "Nav Icon": "آیکون ناوبری", - "Monochrome": "تک رنگ", - "Colorful": "رنگارنگ", - "Tray Icon": "آیکون سینی سیستم", - "Common Tray Icon": "آیکون مشترک سینی سیستم", - "System Proxy Tray Icon": "آیکون سینی پراکسی سیستم", - "Tun Tray Icon": "آیکون سینی Tun", - "Miscellaneous": "متفرقه", - "App Log Level": "سطح لاگ برنامه", - "Auto Close Connections": "بستن خودکار اتصالات", - "Auto Close Connections Info": "اتصالات برقرار شده را هنگام تغییر انتخاب گروه پروکسی یا حالت پروکسی خاتمه دهید", - "Auto Check Update": "بررسی خودکار به‌روزرسانی", - "Enable Builtin Enhanced": "فعال کردن تقویت داخلی", - "Enable Builtin Enhanced Info": "مدیریت سازگاری برای فایل پیکربندی", - "Proxy Layout Columns": "ستون چیدمان پراکسی", - "Auto Columns": "ستون‌های خودکار", - "Auto Log Clean": "پاکسازی خودکار لاگ", - "Never Clean": "هرگز پاک نکن", - "Retain _n Days": "نگهداری به مدت {{n}} روز", - "Auto Delay Detection": "تشخیص تأخیر خودکار", - "Auto Delay Detection Info": "به‌صورت دوره‌ای تأخیر گره فعلی را در پس‌زمینه آزمایش می‌کند", - "Default Latency Test": "آزمون تأخیر پیش‌فرض", - "Default Latency Test Info": "فقط برای تست درخواست‌های کلاینت HTTP استفاده می‌شود و بر فایل پیکربندی تأثیری نخواهد داشت", - "Default Latency Timeout": "زمان انتظار تأخیر پیش‌فرض", - "Hotkey Setting": "تنظیمات کلیدهای میانبر", - "Enable Global Hotkey": "فعال کردن کلید میانبر سراسری", - "open_or_close_dashboard": "باز/بستن داشبورد", - "clash_mode_rule": "حالت قانون", - "clash_mode_global": "حالت جهانی", - "clash_mode_direct": "حالت مستقیم", - "toggle_system_proxy": "فعال/غیرفعال کردن پراکسی سیستم", - "toggle_tun_mode": "فعال/غیرفعال کردن حالت Tun", - "Backup Setting": "تنظیمات پشتیبان گیری", - "Backup Setting Info": "از فایل های پیکربندی پشتیبان WebDAV پشتیبانی می کند", - "Runtime Config": "پیکربندی زمان اجرا", - "Open Conf Dir": "باز کردن پوشه برنامه", - "Open Conf Dir Info": "اگر نرم‌افزار به‌طور غیرعادی اجرا می‌شود، از تمام فایل‌های موجود در این پوشه نسخه پشتیبان تهیه و پاک کنید تا نرم‌افزار را مجدداً راه‌اندازی کنید", - "Open Core Dir": "باز کردن پوشه هسته", - "Open Logs Dir": "باز کردن پوشه لاگ‌ها", - "Check for Updates": "بررسی برای به‌روزرسانی‌ها", - "Go to Release Page": "رفتن به صفحه انتشار", - "Portable Updater Error": "نسخه پرتابل از به‌روزرسانی درون برنامه‌ای پشتیبانی نمی‌کند. لطفاً به صورت دستی دانلود و جایگزین کنید", - "Break Change Update Error": "این نسخه یک به‌روزرسانی اساسی است و پشتیبانی از به‌روزرسانی درون برنامه را پشتیبانی نمی‌کند. لطفاً پس از حذف، دستی دانلود و نصب کنید.", - "Open Dev Tools": "باز کردن ابزارهای توسعه‌دهنده", - "Exit": "خروج", - "Verge Version": "نسخه Verge", - "ReadOnly": "فقط خواندنی", - "ReadOnlyMessage": "نمی‌توان در ویرایشگر فقط خواندنی ویرایش کرد", - "Filter": "فیلتر", - "Filter conditions": "شرایط فیلتر", - "Match Case": "تطبیق حروف کوچک و بزرگ", - "Match Whole Word": "تطبیق کل کلمه", - "Use Regular Expression": "استفاده از عبارت منظم", - "Profile Imported Successfully": "پروفایل با موفقیت وارد شد", - "Profile Switched": "پروفایل تغییر یافت", - "Profile Reactivated": "پروفایل مجدداً فعال شد", - "Only YAML Files Supported": "فقط فایل‌های YAML پشتیبانی می‌شوند", - "Settings Applied": "تنظیمات اعمال شد", - "Installing Service...": "در حال نصب سرویس...", - "Service Installed Successfully": "سرویس با موفقیت نصب شد", - "Service Uninstalled Successfully": "سرویس با موفقیت حذف نصب شد", - "Proxy Daemon Duration Cannot be Less than 1 Second": "مدت زمان دیمن پراکسی نمی‌تواند کمتر از 1 ثانیه باشد", - "Invalid Bypass Format": "فرمت عبور نامعتبر است", - "Clash Port Modified": "پورت Clash تغییر یافت", - "Port Conflict": "تعارض پورت", - "Restart Application to Apply Modifications": "راه‌اندازی مجدد برنامه برای اعمال تغییرات", - "External Controller Address Modified": "آدرس کنترل‌کننده خارجی تغییر یافت", - "Permissions Granted Successfully for _clash Core": "مجوزها با موفقیت برای هسته {{core}} اعطا شد", - "Core Version Updated": "نسخه هسته به‌روزرسانی شد", - "Clash Core Restarted": "هسته Clash مجدداً راه‌اندازی شد", - "GeoData Updated": "GeoData به‌روزرسانی شد", - "Currently on the Latest Version": "در حال حاضر در آخرین نسخه", - "Import Subscription Successful": "وارد کردن اشتراک با موفقیت انجام شد", - "WebDAV Server URL": "http(s):// URL سرور WebDAV", - "Username": "نام کاربری", - "Password": "رمز عبور", - "Backup": "پشتیبان‌گیری", - "Filename": "نام فایل", - "Actions": "عملیات", - "Restore": "بازیابی", - "No Backups": "هیچ پشتیبانی موجود نیست", - "WebDAV URL Required": "آدرس WebDAV نمی‌تواند خالی باشد", - "Invalid WebDAV URL": "فرمت آدرس WebDAV نامعتبر است", - "Username Required": "نام کاربری نمی‌تواند خالی باشد", - "Password Required": "رمز عبور نمی‌تواند خالی باشد", - "Failed to Fetch Backups": "دریافت فایل‌های پشتیبان ناموفق بود", - "WebDAV Config Saved": "پیکربندی WebDAV با موفقیت ذخیره شد", - "WebDAV Config Save Failed": "خطا در ذخیره تنظیمات WebDAV: {{error}}", - "Backup Created": "پشتیبان‌گیری با موفقیت ایجاد شد", - "Backup Failed": "خطا در پشتیبان‌گیری: {{error}}", - "Delete Backup": "حذف پشتیبان", - "Restore Backup": "بازیابی پشتیبان", - "Backup Time": "زمان پشتیبان‌گیری", - "Confirm to delete this backup file?": "آیا از حذف این فایل پشتیبان اطمینان دارید؟", - "Confirm to restore this backup file?": "آیا از بازیابی این فایل پشتیبان اطمینان دارید؟", - "Restore Success, App will restart in 1s": "بازیابی با موفقیت انجام شد، برنامه در 1 ثانیه راه‌اندازی مجدد می‌شود", - "Failed to fetch backup files": "دریافت فایل‌های پشتیبان ناموفق بود", - "Profile": "پروفایل", - "Help": "راهنما", - "About": "درباره", - "Theme": "پوسته", - "Main Window": "پنجره اصلی", - "Group Icon": "آیکون گروه", - "Menu Icon": "آیکون منو", - "PAC File": "فایل PAC", - "Web UI": "رابط وب", - "Hotkeys": "کلیدهای میانبر", - "Verge Mixed Port": "پورت ترکیبی Verge", - "Verge Socks Port": "پورت Socks Verge", - "Verge Redir Port": "پورت تغییر مسیر Verge", - "Verge Tproxy Port": "پورت Tproxy Verge", - "Verge Port": "پورت Verge", - "Verge HTTP Enabled": "HTTP Verge فعال", - "WebDAV URL": "آدرس WebDAV", - "WebDAV Username": "نام کاربری WebDAV", - "WebDAV Password": "رمز عبور WebDAV", - "Dashboard": "داشبورد", - "Restart App": "راه‌اندازی مجدد برنامه", - "Restart Clash Core": "راه‌اندازی مجدد هسته Clash", - "TUN Mode": "حالت TUN", - "Copy Env": "کپی متغیرهای محیطی", - "Conf Dir": "پوشه پیکربندی", - "Core Dir": "پوشه هسته", - "Logs Dir": "پوشه لاگ‌ها", - "Open Dir": "باز کردن پوشه", - "More": "بیشتر", - "Rule Mode": "حالت قوانین", - "Global Mode": "حالت جهانی", - "Direct Mode": "حالت مستقیم", - "Enable Tray Speed": "فعال کردن سرعت ترای", - "LightWeight Mode": "در فارسی", - "LightWeight Mode Info": "رابط کاربری گرافیکی را ببندید و فقط هسته را در حال اجرا نگه دارید", - "Config Validation Failed": "اعتبارسنجی پیکربندی اشتراک ناموفق بود، فایل پیکربندی را بررسی کنید، تغییرات برگشت داده شد، جزئیات خطا:", - "Boot Config Validation Failed": "اعتبارسنجی پیکربندی هنگام راه‌اندازی ناموفق بود، پیکربندی پیش‌فرض استفاده شد، فایل پیکربندی را بررسی کنید، جزئیات خطا:", - "Core Change Config Validation Failed": "اعتبارسنجی پیکربندی هنگام تغییر هسته ناموفق بود، پیکربندی پیش‌فرض استفاده شد، فایل پیکربندی را بررسی کنید، جزئیات خطا:", - "Config Validation Process Terminated": "فرآیند اعتبارسنجی متوقف شد", - "Script Syntax Error": "خطای نحوی اسکریپت، تغییرات برگشت داده شد", - "Script Missing Main": "خطای اسکریپت، تغییرات برگشت داده شد", - "File Not Found": "فایل یافت نشد، تغییرات برگشت داده شد", - "Script File Error": "خطای فایل اسکریپت، تغییرات برگشت داده شد", - "Core Changed Successfully": "هسته با موفقیت تغییر کرد", - "Failed to Change Core": "تغییر هسته ناموفق بود", - "Service Administrator Prompt": "Clash Verge برای نصب مجدد سرویس سیستم به امتیازات مدیر نیاز دارد", - "Default": "پیش‌فرض", - "Label-Test": "آزمون", - "Please Install and Enable Service Mode First": "لطفاً ابتدا حالت سرویس را نصب و فعال کنید", - "Verge Setting": "تنظیمات Verge" -} diff --git a/src/locales/fa/connections.json b/src/locales/fa/connections.json new file mode 100644 index 000000000..dfd891c2a --- /dev/null +++ b/src/locales/fa/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "اتصالات" + }, + "components": { + "fields": { + "host": "میزبان", + "dlSpeed": "سرعت دانلود", + "ulSpeed": "سرعت بارگذاری", + "chains": "زنجیره‌ها", + "rule": "قانون", + "process": "فرآیند", + "time": "زمان", + "source": "منبع", + "destination": "آدرس IP مقصد", + "destinationPort": "بندر هدف", + "type": "نوع" + }, + "order": { + "default": "Default", + "uploadSpeed": "سرعت بارگذاری", + "downloadSpeed": "سرعت دانلود" + }, + "actions": { + "closeConnection": "بستن اتصال" + } + } +} diff --git a/src/locales/fa/home.json b/src/locales/fa/home.json new file mode 100644 index 000000000..786dbc893 --- /dev/null +++ b/src/locales/fa/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "در فارسی", + "manual": "راهنما", + "settings": "Home Settings" + }, + "cards": { + "trafficStats": "Traffic Stats", + "networkSettings": "Network Settings", + "proxyMode": "Proxy Mode" + }, + "settings": { + "cards": { + "profile": "Profile Card", + "currentProxy": "Current Proxy Card", + "network": "Network Settings Card", + "proxyMode": "Proxy Mode Card", + "traffic": "Traffic Stats Card", + "tests": "Website Tests Card", + "ip": "IP Information Card", + "clashInfo": "Clash Info Cards", + "systemInfo": "System Info Cards" + }, + "title": "Home Settings" + }, + "title": "Home" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "System proxy is enabled, your applications will access the network through the proxy", + "systemProxyDisabled": "System proxy is disabled, it is recommended for most users to turn on this option", + "tunModeServiceRequired": "TUN mode requires service mode, please install the service first", + "tunModeEnabled": "TUN mode is enabled, applications will access the network through the virtual network card", + "tunModeDisabled": "TUN mode is disabled, suitable for special applications" + }, + "tooltips": { + "systemProxy": "به امکانات تنظیم پروکسی سیستم عامل دسترسی پیدا کنید. اگر فعال‌سازی ناموفق بود، پروکسی سیستم عامل را به‌صورت دستی تغییر دهید", + "tunMode": "TUN mode can take over all application traffic, suitable for special applications that do not follow the system proxy settings" + } + }, + "clashInfo": { + "title": "Clash Info", + "fields": { + "coreVersion": "Core Version", + "systemProxyAddress": "System Proxy Address", + "mixedPort": "Mixed Port", + "uptime": "Uptime", + "rulesCount": "Rules Count" + } + }, + "systemInfo": { + "title": "System Info", + "fields": { + "osInfo": "OS Info", + "autoLaunch": "راه‌اندازی خودکار", + "runningMode": "Running Mode", + "lastCheckUpdate": "Last Check Update", + "vergeVersion": "نسخه Verge" + }, + "actions": { + "settings": "تنظیمات" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "حالت سرویس", + "sidecarMode": "User Mode", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP Information", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Auto refresh", + "unknown": "Unknown" + }, + "errors": { + "load": "دریافت اطلاعات IP با خطا مواجه شد" + } + }, + "currentProxy": { + "title": "Current Node", + "actions": { + "refreshDelay": "بررسی تأخیر" + }, + "labels": { + "globalMode": "حالت جهانی", + "directMode": "حالت مستقیم", + "group": "Group", + "proxy": "Proxy", + "noActiveNode": "No active proxy node" + } + }, + "tests": { + "title": "Website Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "سرعت بارگذاری", + "downloadSpeed": "سرعت دانلود", + "activeConnections": "Active Connections", + "memoryUsage": "استفاده از حافظه" + }, + "legends": { + "upload": "Upload", + "download": "Download" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "حالت قانون", + "global": "حالت جهانی", + "direct": "حالت مستقیم" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/fa/index.ts b/src/locales/fa/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/fa/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/fa/layout.json b/src/locales/fa/layout.json new file mode 100644 index 000000000..5a7239845 --- /dev/null +++ b/src/locales/fa/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Home", + "proxies": "پراکسی‌ها", + "profiles": "پروفایل‌ها", + "connections": "اتصالات", + "rules": "قوانین", + "logs": "لاگ‌ها", + "unlock": "Test", + "settings": "تنظیمات" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/fa/logs.json b/src/locales/fa/logs.json new file mode 100644 index 000000000..18d2842d1 --- /dev/null +++ b/src/locales/fa/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "لاگ‌ها" + } +} diff --git a/src/locales/fa/profiles.json b/src/locales/fa/profiles.json new file mode 100644 index 000000000..0bd044d10 --- /dev/null +++ b/src/locales/fa/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "به‌روزرسانی همه پروفایل‌ها", + "viewRuntimeConfig": "مشاهده پیکربندی زمان اجرا", + "reactivate": "فعال‌سازی مجدد پروفایل‌ها", + "import": "وارد کردن" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "آدرس پروفایل", + "actions": { + "paste": "چسباندن" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "فقط فایل‌های YAML پشتیبانی می‌شوند" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "پروفایل تغییر یافت", + "profileReactivated": "پروفایل مجدداً فعال شد", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "پروفایل‌ها" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Click to import subscription" + } + }, + "fileInput": { + "chooseFile": "انتخاب فایل" + }, + "menu": { + "home": "Home", + "select": "انتخاب", + "editInfo": "ویرایش اطلاعات", + "editFile": "ویرایش فایل", + "editRules": "ویرایش قوانین", + "editProxies": "ویرایش پروکسی‌ها", + "editGroups": "ویرایش گروه‌های پروکسی", + "extendConfig": "توسعه پیکربندی", + "extendScript": "ادغام اسکریپت", + "openFile": "باز کردن فایل", + "update": "به‌روزرسانی", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "ایجاد پروفایل", + "edit": "ویرایش پروفایل" + }, + "fields": { + "type": "نوع", + "description": "توضیحات", + "subscriptionUrl": "آدرس اشتراک", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "فاصله زمانی به‌روزرسانی", + "useSystemProxy": "استفاده از پراکسی سیستم", + "useClashProxy": "استفاده از پراکسی Clash", + "acceptInvalidCerts": "پذیرش گواهی‌نامه‌های نامعتبر (خطرناک)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "ویرایش پروکسی‌ها", + "placeholders": { + "multiUri": "استفاده از خطوط جدید برای چندین آدرس (پشتیبانی از رمزگذاری Base64)" + }, + "actions": { + "prepend": "پیش‌افزودن پراکسی", + "append": "پس‌افزودن پراکسی" + } + }, + "groupsEditor": { + "title": "ویرایش گروه‌های پروکسی", + "errors": { + "nameRequired": "نام گروه مورد نیاز است", + "nameExists": "نام گروه قبلا وجود دارد" + }, + "fields": { + "type": "نوع گروه", + "name": "نام گروه", + "icon": "آیکون گروه پراکسی", + "proxies": "استفاده از پروکسی‌ها", + "provider": "استفاده از ارائه‌دهنده", + "healthCheckUrl": "آدرس بررسی سلامت", + "expectedStatus": "وضعیت مورد انتظار", + "interval": "فاصله زمانی", + "maxFailedTimes": "حداکثر تعداد شکست‌ها", + "interfaceName": "نام رابط", + "routingMark": "علامت مسیریابی", + "filter": "فیلتر", + "excludeFilter": "فیلتر استثناء", + "excludeType": "نوع استثناء", + "includeAll": "شامل همه پروکسی‌ها و ارائه‌دهنده‌ها", + "includeAllProxies": "شامل همه پروکسی‌ها", + "includeAllProviders": "شامل همه ارائه‌دهنده‌ها" + }, + "toggles": { + "lazy": "تنبل", + "disableUdp": "غیرفعال کردن UDP", + "hidden": "مخفی" + }, + "actions": { + "prepend": "اضافه کردن گروه به ابتدا", + "append": "اضافه کردن گروه به انتها" + } + }, + "editor": { + "actions": { + "format": "فرمت‌بندی سند" + }, + "messages": { + "readOnly": "نمی‌توان در ویرایشگر فقط خواندنی ویرایش کرد" + } + }, + "confirmDelete": { + "title": "تأیید حذف", + "message": "این عملیات قابل برگشت نیست" + }, + "logViewer": { + "title": "کنسول اسکریپت" + } + } +} diff --git a/src/locales/fa/proxies.json b/src/locales/fa/proxies.json new file mode 100644 index 000000000..20bebdfa8 --- /dev/null +++ b/src/locales/fa/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 پراکسی زنجیره‌ای", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "تأمین‌کننده پروکسی", + "actions": { + "updateAll": "به‌روزرسانی همه", + "update": "به‌روزرسانی" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "بررسی تأخیر برای لغو ثابت" + }, + "tooltips": { + "locate": "موقعیت", + "delayCheck": "بررسی تأخیر", + "sortDefault": "مرتب‌سازی بر اساس پیش‌فرض", + "sortDelay": "مرتب‌سازی بر اساس تأخیر", + "sortName": "مرتب‌سازی بر اساس نام", + "delayCheckUrl": "آدرس بررسی تأخیر", + "showBasic": "پراکسی پایه", + "showDetail": "جزئیات پراکسی", + "filter": "فیلتر" + }, + "placeholders": { + "delayCheckUrl": "آدرس بررسی تأخیر" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "حالت مستقیم" + }, + "title": { + "default": "گروه‌های پراکسی", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "انتخاب پروکسی به صورت دستی", + "url-test": "انتخاب پروکسی بر اساس تأخیر آزمایش URL", + "fallback": "تعویض به پروکسی دیگر در صورت بروز خطا", + "load-balance": "توزیع پراکسی بر اساس توازن بار", + "relay": "عبور از زنجیره پروکسی تعریف شده" + }, + "policies": { + "DIRECT": "داده‌ها به صورت مستقیم خروجی می‌شوند", + "REJECT": "درخواست‌ها را متوقف می‌کند", + "REJECT-DROP": "درخواست‌ها را نادیده می‌گیرد", + "PASS": "این قانون را در صورت تطابق نادیده می‌گیرد" + } + } + } +} diff --git a/src/locales/fa/rules.json b/src/locales/fa/rules.json new file mode 100644 index 000000000..9aa7c7426 --- /dev/null +++ b/src/locales/fa/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "تأمین‌کننده قانون", + "dialogTitle": "تأمین‌کننده قانون", + "actions": { + "updateAll": "به‌روزرسانی همه", + "update": "به‌روزرسانی" + } + }, + "title": "قوانین" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "نوع قانون", + "content": "محتوای قانون", + "proxyPolicy": "سیاست پروکسی" + }, + "toggles": { + "noResolve": "بدون حل" + }, + "actions": { + "prependRule": "اضافه کردن قانون به ابتدا", + "appendRule": "اضافه کردن قانون به انتها" + }, + "validation": { + "conditionRequired": "شرط قانون الزامی است", + "invalidRule": "قانون نامعتبر" + } + }, + "ruleTypes": { + "DOMAIN": "مطابقت با نام کامل دامنه", + "DOMAIN-SUFFIX": "مطابقت با پسوند دامنه", + "DOMAIN-KEYWORD": "مطابقت با کلمه کلیدی دامنه", + "DOMAIN-REGEX": "مطابقت با دامنه با استفاده از عبارات منظم", + "GEOSITE": "مطابقت با دامنه‌های درون Geosite", + "GEOIP": "مطابقت با کد کشور IP", + "SRC-GEOIP": "مطابقت با کد کشور IP مبدا", + "IP-ASN": "مطابقت با ASN آدرس IP", + "SRC-IP-ASN": "مطابقت با ASN آدرس IP مبدا", + "IP-CIDR": "مطابقت با محدوده آدرس IP", + "IP-CIDR6": "مطابقت با محدوده آدرس IPv6", + "SRC-IP-CIDR": "مطابقت با محدوده آدرس IP مبدا", + "IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP", + "SRC-IP-SUFFIX": "مطابقت با محدوده پسوند آدرس IP مبدا", + "SRC-PORT": "مطابقت با محدوده پورت مبدا", + "DST-PORT": "مطابقت با محدوده پورت مقصد", + "IN-PORT": "مطابقت با پورت ورودی", + "DSCP": "علامت‌گذاری DSCP (فقط برای tproxy UDP ورودی)", + "PROCESS-NAME": "مطابقت با نام فرآیند (نام بسته Android)", + "PROCESS-PATH": "مطابقت با مسیر کامل فرآیند", + "PROCESS-NAME-REGEX": "مطابقت با نام فرآیند با استفاده از عبارات منظم (نام بسته Android)", + "PROCESS-PATH-REGEX": "مطابقت با مسیر کامل فرآیند با استفاده از عبارات منظم", + "NETWORK": "مطابقت با پروتکل انتقال (tcp/udp)", + "UID": "مطابقت با شناسه کاربری Linux", + "IN-TYPE": "مطابقت با نوع ورودی", + "IN-USER": "مطابقت با نام کاربری ورودی", + "IN-NAME": "مطابقت با نام ورودی", + "SUB-RULE": "قانون فرعی", + "RULE-SET": "مطابقت با مجموعه قوانین", + "AND": "منطق AND", + "OR": "منطق OR", + "NOT": "منطق NOT", + "MATCH": "مطابقت با تمام درخواست‌ها" + }, + "title": "ویرایش قوانین" + } + } +} diff --git a/src/locales/fa/settings.json b/src/locales/fa/settings.json new file mode 100644 index 000000000..36a41769d --- /dev/null +++ b/src/locales/fa/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "راهنما", + "telegram": "کانال تلگرام", + "github": "مخزن GitHub" + }, + "title": "تنظیمات" + }, + "sections": { + "system": { + "title": "تنظیمات سیستم", + "toggles": { + "tunMode": "Tun (کارت شبکه مجازی)", + "systemProxy": "پراکسی سیستم" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "برنامه را در حالت پس‌زمینه بدون نمایش پانل اجرا کنید" + }, + "fields": { + "autoLaunch": "اجرای خودکار", + "silentStart": "اجرای بی‌صدا" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "به امکانات تنظیم پروکسی سیستم عامل دسترسی پیدا کنید. اگر فعال‌سازی ناموفق بود، پروکسی سیستم عامل را به‌صورت دستی تغییر دهید", + "tunMode": "حالت Tun (NIC مجازی): تمام ترافیک سیستم را ضبط می کند، وقتی فعال باشد، نیازی به فعال کردن پروکسی سیستم نیست.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "نصب سرویس", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "پراکسی سیستم", + "tunMode": "Tun (کارت شبکه مجازی)" + } + }, + "externalController": { + "title": "کنترل‌کننده خارجی", + "fields": { + "enable": "Enable External Controller", + "address": "کنترل‌کننده خارجی", + "secret": "رمز اصلی" + }, + "placeholders": { + "address": "Required", + "secret": "توصیه شده" + }, + "tooltips": { + "copy": "Copy to clipboard" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Failed to copy", + "controllerCopied": "Controller address copied to clipboard", + "secretCopied": "Secret copied to clipboard" + } + }, + "externalCors": { + "title": "External Cors Configuration", + "fields": { + "allowPrivateNetwork": "Allow private network access", + "allowedOrigins": "Allowed Origins" + }, + "placeholders": { + "origin": "Please enter a valid url" + }, + "actions": { + "add": "Add" + }, + "messages": { + "alwaysIncluded": "Always included origins: {{urls}}" + }, + "tooltips": { + "open": "External Cors Settings" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "تنظیمات Clash", + "form": { + "fields": { + "allowLan": "اجازه LAN", + "dnsOverwrite": "DNS Overwrite", + "ipv6": "IPv6", + "unifiedDelay": "معادلDELAY", + "logLevel": "سطح لاگ", + "portConfig": "پیکربندی پورت", + "external": "خارجی", + "webUI": "رابط وب", + "clashCore": "هسته Clash", + "openUwpTool": "باز کردن ابزار UWP", + "updateGeoData": "به‌روزرسانی GeoData" + }, + "tooltips": { + "networkInterface": "رابط شبکه", + "unifiedDelay": "معادلDELAY را فعال کنید تا ترافیک شبکه به سرعت رسید", + "logLevel": "این فقط روی فایل‌های لاگ هسته تحت فایل سرویس در فهرست ورود اثر می‌گذارد.", + "openUwpTool": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "تنظیمات پایه Verge", + "actions": { + "browse": "مرور کردن" + }, + "trayOptions": { + "showMainWindow": "نمایش پنجره اصلی", + "showTrayMenu": "Show Tray Menu", + "disable": "غیرفعال کردن" + }, + "fields": { + "language": "زبان", + "themeMode": "حالت تم", + "trayClickEvent": "رویداد کلیک در سینی سیستم", + "copyEnvType": "کپی نوع محیط", + "startPage": "صفحه شروع", + "startupScript": "اسکریپت راه‌اندازی", + "themeSetting": "تنظیمات تم", + "layoutSetting": "تنظیمات چیدمان", + "misc": "متفرقه", + "hotkeySetting": "تنظیمات کلیدهای میانبر" + } + }, + "advanced": { + "title": "تنظیمات پیشرفته Verge", + "tooltips": { + "backupInfo": "از فایل های پیکربندی پشتیبان WebDAV پشتیبانی می کند", + "openConfDir": "اگر نرم‌افزار به‌طور غیرعادی اجرا می‌شود، از تمام فایل‌های موجود در این پوشه نسخه پشتیبان تهیه و پاک کنید تا نرم‌افزار را مجدداً راه‌اندازی کنید", + "liteMode": "رابط کاربری گرافیکی را ببندید و فقط هسته را در حال اجرا نگه دارید" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "در حال حاضر در آخرین نسخه", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "تنظیمات پشتیبان گیری", + "runtimeConfig": "پیکربندی زمان اجرا", + "openConfDir": "باز کردن پوشه برنامه", + "openCoreDir": "باز کردن پوشه هسته", + "openLogsDir": "باز کردن پوشه لاگ‌ها", + "checkUpdates": "بررسی برای به‌روزرسانی‌ها", + "openDevTools": "باز کردن ابزارهای توسعه‌دهنده", + "liteModeSettings": "LightWeight Mode Settings", + "exit": "خروج", + "exportDiagnostics": "Export Diagnostic Info", + "vergeVersion": "نسخه Verge" + } + }, + "theme": { + "title": "تنظیمات تم", + "fields": { + "primaryColor": "رنگ اصلی", + "secondaryColor": "رنگ ثانویه", + "primaryText": "متن اصلی", + "secondaryText": "متن ثانویه", + "infoColor": "رنگ اطلاعات", + "warningColor": "رنگ هشدار", + "errorColor": "رنگ خطا", + "successColor": "رنگ موفقیت", + "fontFamily": "خانواده فونت", + "cssInjection": "تزریق CSS" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "تنظیمات چیدمان", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "نمودار ترافیک", + "memoryUsage": "استفاده از حافظه", + "proxyGroupIcon": "آیکون گروه پراکسی", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "آیکون ناوبری", + "trayIcon": "آیکون سینی سیستم", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "آیکون مشترک سینی سیستم", + "systemProxyTrayIcon": "آیکون سینی پراکسی سیستم", + "tunTrayIcon": "آیکون سینی Tun", + "enableTrayIcon": "Enable Tray Icon", + "enableTraySpeed": "فعال کردن سرعت ترای" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "تک رنگ", + "colorful": "رنگارنگ", + "disable": "غیرفعال کردن" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "پیکربندی پورت", + "fields": { + "mixed": "پورت پروکسی ترکیبی", + "socks": "پورت پروکسی Socks", + "http": "پورت پروکسی Http(s)", + "redir": "پورت پروکسی شفاف Redir", + "tproxy": "پورت پروکسی شفاف Tproxy" + }, + "actions": { + "random": "پورت تصادفی" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "نسخه نهایی", + "alpha": "نسخه آلفا" + } + }, + "liteMode": { + "title": "LightWeight Mode Settings", + "actions": { + "enterNow": "Enter LightWeight Mode Now" + }, + "toggles": { + "autoEnter": "Auto Enter LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time" + }, + "fields": { + "delay": "Auto Enter LightWeight Mode Delay" + }, + "messages": { + "autoEnterHint": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes" + } + }, + "backup": { + "title": "تنظیمات پشتیبان گیری", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "پشتیبان‌گیری", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "حذف پشتیبان", + "restore": "بازیابی", + "restoreBackup": "بازیابی پشتیبان" + }, + "fields": { + "webdavUrl": "http(s):// URL سرور WebDAV", + "username": "نام کاربری", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "آدرس WebDAV نمی‌تواند خالی باشد", + "invalidWebdavUrl": "فرمت آدرس WebDAV نامعتبر است", + "usernameRequired": "نام کاربری نمی‌تواند خالی باشد", + "passwordRequired": "رمز عبور نمی‌تواند خالی باشد", + "webdavConfigSaved": "پیکربندی WebDAV با موفقیت ذخیره شد", + "webdavConfigSaveFailed": "خطا در ذخیره تنظیمات WebDAV: {{error}}", + "backupCreated": "پشتیبان‌گیری با موفقیت ایجاد شد", + "backupFailed": "خطا در پشتیبان‌گیری: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "بازیابی با موفقیت انجام شد، برنامه در 1 ثانیه راه‌اندازی مجدد می‌شود", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "آیا از حذف این فایل پشتیبان اطمینان دارید؟", + "confirmRestore": "آیا از بازیابی این فایل پشتیبان اطمینان دارید؟" + }, + "table": { + "filename": "نام فایل", + "backupTime": "زمان پشتیبان‌گیری", + "actions": "عملیات", + "noBackups": "هیچ پشتیبانی موجود نیست", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "متفرقه", + "fields": { + "appLogLevel": "سطح لاگ برنامه", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "بستن خودکار اتصالات", + "autoCheckUpdate": "بررسی خودکار به‌روزرسانی", + "enableBuiltinEnhanced": "فعال کردن تقویت داخلی", + "proxyLayoutColumns": "ستون چیدمان پراکسی", + "autoLogClean": "پاکسازی خودکار لاگ", + "autoDelayDetection": "تشخیص تأخیر خودکار", + "defaultLatencyTest": "آزمون تأخیر پیش‌فرض", + "defaultLatencyTimeout": "زمان انتظار تأخیر پیش‌فرض" + }, + "tooltips": { + "autoCloseConnections": "اتصالات برقرار شده را هنگام تغییر انتخاب گروه پروکسی یا حالت پروکسی خاتمه دهید", + "enableBuiltinEnhanced": "مدیریت سازگاری برای فایل پیکربندی", + "autoDelayDetection": "به‌صورت دوره‌ای تأخیر گره فعلی را در پس‌زمینه آزمایش می‌کند", + "defaultLatencyTest": "فقط برای تست درخواست‌های کلاینت HTTP استفاده می‌شود و بر فایل پیکربندی تأثیری نخواهد داشت" + }, + "options": { + "proxyLayoutColumns": { + "auto": "ستون‌های خودکار" + }, + "autoLogClean": { + "never": "هرگز پاک نکن", + "retainDays": "نگهداری به مدت {{n}} روز" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "رفتن به صفحه انتشار", + "update": "به‌روزرسانی" + }, + "messages": { + "portableError": "نسخه پرتابل از به‌روزرسانی درون برنامه‌ای پشتیبانی نمی‌کند. لطفاً به صورت دستی دانلود و جایگزین کنید", + "breakChangeError": "این نسخه یک به‌روزرسانی اساسی است و پشتیبانی از به‌روزرسانی درون برنامه را پشتیبانی نمی‌کند. لطفاً پس از حذف، دستی دانلود و نصب کنید." + } + }, + "sysproxy": { + "title": "تنظیمات پراکسی سیستم", + "fieldsets": { + "currentStatus": "پراکسی سیستم فعلی" + }, + "fields": { + "enableStatus": "وضعیت فعال", + "serverAddr": "آدرس سرور: ", + "pacUrl": "PAC URL: ", + "proxyHost": "میزبان پراکسی", + "usePacMode": "استفاده از حالت PAC", + "proxyGuard": "محافظ پراکسی", + "guardDuration": "مدت محافظت", + "alwaysUseDefaultBypass": "همیشه از دور زدن پیش‌فرض استفاده کنید", + "proxyBypass": "دور زدن پراکسی: ", + "bypass": "دور زدن: ", + "pacScriptContent": "محتوای اسکریپت PAC" + }, + "tooltips": { + "proxyGuard": "امکان جلوگیری از نرم‌افزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید" + }, + "messages": { + "durationTooShort": "مدت زمان دیمن پراکسی نمی‌تواند کمتر از 1 ثانیه باشد", + "invalidBypass": "فرمت عبور نامعتبر است", + "invalidProxyHost": "فرمت میزبان پراکسی نامعتبر است" + }, + "actions": { + "editPac": "ویرایش PAC" + } + }, + "tun": { + "title": "Tun (کارت شبکه مجازی)", + "fields": { + "stack": "انباشته Tun", + "device": "Device Name", + "autoRoute": "مسیر خودکار", + "strictRoute": "مسیر دقیق", + "autoDetectInterface": "تشخیص خودکار رابط", + "dnsHijack": "ربایش DNS", + "mtu": "واحد حداکثر انتقال" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "تنظیمات اعمال شد" + } + }, + "dns": { + "dialog": { + "title": "DNS Overwrite", + "warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled" + }, + "sections": { + "general": "DNS Settings", + "fallbackFilter": "Fallback Filter Settings", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Enable DNS", + "listen": "DNS Listen", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Fake IP Range", + "fakeIpFilterMode": "Fake IP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Prefer H3", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Respect Rules", + "description": "DNS connections follow routing rules" + }, + "useHosts": { + "label": "Use Hosts", + "description": "Enable to resolve hosts through hosts file" + }, + "useSystemHosts": { + "label": "Use System Hosts", + "description": "Enable to resolve hosts through system hosts file" + }, + "directPolicy": { + "label": "Direct Nameserver Follow Policy", + "description": "Whether to follow nameserver policy" + }, + "defaultNameserver": { + "label": "Default Nameserver", + "description": "Default DNS servers used to resolve DNS servers" + }, + "nameserver": { + "label": "Nameserver", + "description": "List of DNS servers, comma separated" + }, + "fallback": { + "label": "Fallback", + "description": "List of fallback DNS servers, comma separated" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS servers for proxy node domain resolution" + }, + "directNameserver": { + "label": "Direct Nameserver", + "description": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated" + }, + "fakeIpFilter": { + "label": "Fake IP Filter", + "description": "Domains that skip fake IP resolution, comma separated" + }, + "nameserverPolicy": { + "label": "Nameserver Policy", + "description": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtering", + "description": "Enable GeoIP filtering for fallback" + }, + "geoipCode": "GeoIP Code", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "IP CIDRs not using fallback servers, comma separated" + }, + "fallbackDomain": { + "label": "Fallback Domain", + "description": "Domains using fallback servers, comma separated" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "باز کردن آدرس اینترنتی" + }, + "title": "رابط وب", + "messages": { + "supportedPlaceholders": "پشتیبانی از %host، %port و %secret", + "placeholderInstruction": "جایگزین کردن میزبان، پورت و رمز با %host، %port، %secret" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "فعال کردن کلید میانبر سراسری" + }, + "title": "تنظیمات کلیدهای میانبر", + "functions": { + "rule": "حالت قانون", + "global": "حالت جهانی", + "openOrCloseDashboard": "باز/بستن داشبورد", + "toggleSystemProxy": "فعال/غیرفعال کردن پراکسی سیستم", + "toggleTunMode": "فعال/غیرفعال کردن حالت Tun", + "entryLightweightMode": "Entry Lightweight Mode", + "direct": "حالت مستقیم" + } + }, + "password": { + "prompts": { + "enterRoot": "لطفاً رمز ریشه خود را وارد کنید" + } + }, + "networkInterface": { + "title": "رابط شبکه", + "fields": { + "ipAddress": "آدرس IP", + "macAddress": "آدرس MAC" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "هسته Clash مجدداً راه‌اندازی شد", + "versionUpdated": "نسخه هسته به‌روزرسانی شد", + "alreadyLatestVersion": "در حال حاضر از آخرین نسخه هسته استفاده می‌کنید", + "changeSuccess": "هسته با موفقیت تغییر کرد", + "changeFailed": "تغییر هسته ناموفق بود", + "geoDataUpdated": "GeoData به‌روزرسانی شد" + }, + "clashService": { + "installSuccess": "سرویس با موفقیت نصب شد", + "uninstallSuccess": "سرویس با موفقیت حذف نصب شد" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "در حال نصب سرویس...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/fa/shared.json b/src/locales/fa/shared.json new file mode 100644 index 000000000..374707ac0 --- /dev/null +++ b/src/locales/fa/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "لغو", + "close": "بستن", + "confirm": "تأیید", + "save": "ذخیره", + "delete": "حذف", + "edit": "ویرایش", + "new": "جدید", + "enable": "فعال کردن", + "upgrade": "ارتقاء", + "restart": "راه‌اندازی مجدد", + "resetToDefault": "بازنشانی به پیش‌فرض", + "refresh": "بازنشانی", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "نمای لیستی", + "tableView": "نمای جدولی", + "pause": "توقف", + "resume": "از سرگیری", + "closeAll": "بستن همه", + "clear": "پاک کردن" + }, + "labels": { + "updateAt": "به‌روزرسانی در", + "timeout": "Timeout", + "icon": "آیکون", + "name": "نام", + "readOnly": "فقط خواندنی", + "expireTime": "زمان انقضا", + "updateTime": "زمان به‌روزرسانی", + "usedTotal": "استفاده‌شده / کل", + "from": "از", + "password": "رمز عبور", + "retryAttempts": "Retry attempts", + "downloaded": "دانلود شده", + "uploaded": "بارگذاری شده" + }, + "statuses": { + "enabled": "توانایی فعال شد", + "disabled": "غیرفعال شد", + "saving": "Saving...", + "empty": "خالی خالی" + }, + "units": { + "milliseconds": "میلی‌ثانیه", + "seconds": "ثانیه‌ها", + "minutes": "دقیقه", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "شرایط فیلتر", + "matchCase": "تطبیق حروف کوچک و بزرگ", + "matchWholeWord": "تطبیق کل کلمه", + "useRegex": "استفاده از عبارت منظم" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "بزرگ‌نمایی", + "minimize": "کوچک‌نمایی" + }, + "editorModes": { + "visualization": "تجسم", + "advanced": "پیشرفته" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "پروفایل با موفقیت وارد شد", + "importSubscriptionSuccess": "وارد کردن اشتراک با موفقیت انجام شد", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "کپی با موفقیت انجام شد", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "اعتبارسنجی پیکربندی اشتراک ناموفق بود، فایل پیکربندی را بررسی کنید، تغییرات برگشت داده شد، جزئیات خطا:", + "bootFailed": "اعتبارسنجی پیکربندی هنگام راه‌اندازی ناموفق بود، پیکربندی پیش‌فرض استفاده شد، فایل پیکربندی را بررسی کنید، جزئیات خطا:", + "coreChangeFailed": "اعتبارسنجی پیکربندی هنگام تغییر هسته ناموفق بود، پیکربندی پیش‌فرض استفاده شد، فایل پیکربندی را بررسی کنید، جزئیات خطا:", + "processTerminated": "فرآیند اعتبارسنجی متوقف شد" + }, + "script": { + "syntaxError": "خطای نحوی اسکریپت، تغییرات برگشت داده شد", + "missingMain": "خطای اسکریپت، تغییرات برگشت داده شد", + "fileNotFound": "فایل یافت نشد، تغییرات برگشت داده شد", + "fileError": "خطای فایل اسکریپت، تغییرات برگشت داده شد" + }, + "yaml": { + "syntaxError": "YAML syntax error, changes reverted", + "readError": "YAML read error, changes reverted", + "mappingError": "YAML mapping error, changes reverted", + "keyError": "YAML key error, changes reverted", + "generalError": "YAML error, changes reverted" + }, + "merge": { + "syntaxError": "Merge file syntax error, changes reverted", + "mappingError": "Merge file mapping error, changes reverted", + "keyError": "Merge file key error, changes reverted", + "generalError": "Merge file error, changes reverted" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/fa/tests.json b/src/locales/fa/tests.json new file mode 100644 index 000000000..9068ea338 --- /dev/null +++ b/src/locales/fa/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "آزمون همه" + }, + "title": "آزمون" + }, + "components": { + "item": { + "actions": { + "test": "آزمون" + } + } + }, + "modals": { + "test": { + "title": { + "create": "ایجاد آزمون", + "edit": "ویرایش آزمون" + }, + "fields": { + "url": "آدرس آزمون" + } + } + }, + "statuses": { + "test": { + "pending": "Pending", + "yes": "Yes", + "no": "No", + "failed": "Failed", + "completed": "Completed", + "disallowedIsp": "Disallowed ISP", + "originalsOnly": "Originals Only", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Unsupported Country/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Testing..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "تشخیص برای {{name}} ناموفق بود", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Unlock Test" + } + } +} diff --git a/src/locales/id.json b/src/locales/id.json deleted file mode 100644 index 7d15a6016..000000000 --- a/src/locales/id.json +++ /dev/null @@ -1,459 +0,0 @@ -{ - "millis": "milidetik", - "seconds": "detik", - "mins": "menit", - "Back": "Kembali", - "Close": "Tutup", - "Cancel": "Batal", - "Confirm": "Konfirmasi", - "Maximize": "Maksimalkan", - "Minimize": "Minimalkan", - "Format document": "Format dokumen", - "Empty": "Kosong", - "New": "Baru", - "Edit": "Ubah", - "Save": "Simpan", - "Delete": "Hapus", - "Enable": "Aktifkan", - "Disable": "Nonaktifkan", - "Label-Proxies": "Proksi", - "Label-Profiles": "Profil", - "Label-Connections": "Koneksi", - "Label-Rules": "Aturan", - "Label-Logs": "Log", - "Label-Settings": "Pengaturan", - "Proxies": "Proksi", - "Proxy Groups": "Grup Proksi", - "Proxy Provider": "Penyedia Proksi", - "Update All": "Perbarui Semua", - "Update At": "Diperbarui Pada", - "rule": "aturan", - "global": "global", - "direct": "langsung", - "Chain Proxy": "🔗 Proxy Rantai", - "script": "skrip", - "locate": "Lokasi", - "Delay check": "Periksa Keterlambatan", - "Sort by default": "Urutkan secara default", - "Sort by delay": "Urutkan berdasarkan keterlambatan", - "Sort by name": "Urutkan berdasarkan nama", - "Delay check URL": "URL Periksa Keterlambatan", - "Delay check to cancel fixed": "Periksa keterlambatan untuk membatalkan tetap", - "Proxy basic": "Dasar Proksi", - "Proxy detail": "Detail Proksi", - "Profiles": "Profil", - "Update All Profiles": "Perbarui Semua Profil", - "View Runtime Config": "Lihat Konfigurasi Runtime", - "Reactivate Profiles": "Reaktivasi Profil", - "Paste": "Tempel", - "Profile URL": "URL Profil", - "Import": "Impor", - "From": "Dari", - "Update Time": "Waktu Pembaruan", - "Used / Total": "Digunakan / Total", - "Expire Time": "Waktu Kedaluwarsa", - "Create Profile": "Buat Profil", - "Edit Profile": "Ubah Profil", - "Edit Proxies": "Ubah Proksi", - "Use newlines for multiple uri": "Gunakan baris baru untuk beberapa URI (mendukung pengkodean Base64)", - "Edit Rules": "Ubah Aturan", - "Rule Type": "Jenis Aturan", - "Rule Content": "Konten Aturan", - "Proxy Policy": "Kebijakan Proksi", - "No Resolve": "Tidak Menyelesaikan", - "Prepend Rule": "Tambahkan Aturan di Awal", - "Append Rule": "Tambahkan Aturan di Akhir", - "Prepend Group": "Tambahkan Grup di Awal", - "Append Group": "Tambahkan Grup di Akhir", - "Prepend Proxy": "Tambahkan Proksi di Awal", - "Append Proxy": "Tambahkan Proksi di Akhir", - "Rule Condition Required": "Kondisi Aturan Diperlukan", - "Invalid Rule": "Aturan Tidak Valid", - "Advanced": "Lanjutan", - "Visualization": "Visualisasi", - "DOMAIN": "Cocok dengan nama domain lengkap", - "DOMAIN-SUFFIX": "Cocok dengan sufiks domain", - "DOMAIN-KEYWORD": "Cocok dengan kata kunci domain", - "DOMAIN-REGEX": "Cocok dengan domain menggunakan ekspresi reguler", - "GEOSITE": "Cocok dengan domain dalam Geosite", - "GEOIP": "Cocok dengan kode negara alamat IP", - "SRC-GEOIP": "Cocok dengan kode negara alamat IP sumber", - "IP-ASN": "Cocok dengan ASN alamat IP", - "SRC-IP-ASN": "Cocok dengan ASN alamat IP sumber", - "IP-CIDR": "Cocok dengan rentang alamat IP", - "IP-CIDR6": "Cocok dengan rentang alamat IPv6", - "SRC-IP-CIDR": "Cocok dengan rentang alamat IP sumber", - "IP-SUFFIX": "Cocok dengan rentang sufiks alamat IP", - "SRC-IP-SUFFIX": "Cocok dengan rentang sufiks alamat IP sumber", - "SRC-PORT": "Cocok dengan rentang port sumber", - "DST-PORT": "Cocok dengan rentang port tujuan", - "IN-PORT": "Cocok dengan port masuk", - "DSCP": "Penandaan DSCP (hanya untuk tproxy UDP masuk)", - "PROCESS-NAME": "Cocok dengan nama proses (nama paket Android)", - "PROCESS-PATH": "Cocok dengan jalur proses lengkap", - "PROCESS-NAME-REGEX": "Cocok dengan nama proses lengkap menggunakan ekspresi reguler (nama paket Android)", - "PROCESS-PATH-REGEX": "Cocok dengan jalur proses lengkap menggunakan ekspresi reguler", - "NETWORK": "Cocok dengan protokol transportasi (tcp/udp)", - "UID": "Cocok dengan ID PENGGUNA Linux", - "IN-TYPE": "Cocok dengan jenis masuk", - "IN-USER": "Cocok dengan nama pengguna masuk", - "IN-NAME": "Cocok dengan nama masuk", - "SUB-RULE": "Sub-aturan", - "RULE-SET": "Cocok dengan set aturan", - "AND": "Logika DAN", - "OR": "Logika ATAU", - "NOT": "Logika TIDAK", - "MATCH": "Cocok dengan semua permintaan", - "DIRECT": "Data langsung keluar", - "REJECT": "Mencegat permintaan", - "REJECT-DROP": "Membuang permintaan", - "PASS": "Lewati aturan ini saat cocok", - "Edit Groups": "Ubah Grup Proksi", - "Group Type": "Jenis Grup", - "select": "Pilih proksi secara manual", - "url-test": "Pilih proksi berdasarkan keterlambatan tes URL", - "fallback": "Beralih ke proksi lain saat terjadi kesalahan", - "load-balance": "Distribusikan proksi berdasarkan penyeimbangan beban", - "relay": "Lewatkan melalui rantai proksi yang ditentukan", - "Group Name": "Nama Grup", - "Use Proxies": "Gunakan Proksi", - "Use Provider": "Gunakan Penyedia", - "Health Check Url": "URL Pemeriksaan Kesehatan", - "Expected Status": "Status yang Diharapkan", - "Interval": "Interval", - "Lazy": "Malas", - "Timeout": "Waktu Habis", - "Max Failed Times": "Jumlah Gagal Maksimal", - "Interface Name": "Nama Antarmuka", - "Routing Mark": "Tanda Routing", - "Include All": "Sertakan Semua Proksi dan Penyedia", - "Include All Providers": "Sertakan Semua Penyedia", - "Include All Proxies": "Sertakan Semua Proksi", - "Exclude Filter": "Kecualikan Filter", - "Exclude Type": "Kecualikan Jenis", - "Disable UDP": "Nonaktifkan UDP", - "Hidden": "Tersembunyi", - "Group Name Required": "Nama Grup Diperlukan", - "Group Name Already Exists": "Nama Grup Sudah Ada", - "Extend Config": "Perluas Konfigurasi", - "Extend Script": "Perluas Skrip", - "Global Merge": "Perluas Konfigurasi Global", - "Global Script": "Perluas Skrip Global", - "Type": "Jenis", - "Name": "Nama", - "Descriptions": "Deskripsi", - "Subscription URL": "URL Langganan", - "Update Interval": "Interval Pembaruan", - "Choose File": "Pilih Berkas", - "Use System Proxy": "Gunakan Proksi Sistem", - "Use Clash Proxy": "Gunakan Proksi Clash", - "Accept Invalid Certs (Danger)": "Terima Sertifikat Tidak Valid (Bahaya)", - "Refresh": "Segarkan", - "Home": "Beranda", - "Select": "Pilih", - "Edit Info": "Ubah Info", - "Edit File": "Ubah Berkas", - "Open File": "Buka Berkas", - "Update": "Perbarui", - "Update(Proxy)": "Perbarui (Proksi)", - "Confirm deletion": "Konfirmasi penghapusan", - "This operation is not reversible": "Operasi ini tidak dapat dibatalkan", - "Script Console": "Konsol Skrip", - "To Top": "Ke Atas", - "To End": "Ke Bawah", - "Connections": "Koneksi", - "Table View": "Tampilan Tabel", - "List View": "Tampilan Daftar", - "Close All": "Tutup Semua", - "Download Speed": "Kecepatan Unduh", - "Upload Speed": "Kecepatan Unggah", - "Host": "Host", - "Downloaded": "Diunduh", - "Uploaded": "Diunggah", - "DL Speed": "Kecepatan Unduh", - "UL Speed": "Kecepatan Unggah", - "Chains": "Rantai", - "Rule": "Aturan", - "Process": "Proses", - "Time": "Waktu", - "Source": "Sumber", - "Destination": "IP Tujuan", - "DestinationPort": "Port Tujuan", - "Close Connection": "Tutup Koneksi", - "Rules": "Aturan", - "Rule Provider": "Penyedia Aturan", - "Logs": "Log", - "Pause": "Jeda", - "Resume": "Lanjut", - "Clear": "Bersihkan", - "Test": "Tes", - "Test All": "Tes Semua", - "Create Test": "Buat Tes", - "Edit Test": "Ubah Tes", - "Icon": "Ikon", - "Test URL": "URL Tes", - "Settings": "Pengaturan", - "System Setting": "Pengaturan Sistem", - "Tun Mode": "Mode Tun (NIC Virtual)", - "TUN requires Service Mode": "Mode TUN memerlukan layanan", - "Install Service": "Instal Layanan", - "Reset to Default": "Setel Ulang ke Default", - "Tun Mode Info": "Mode Tun (NIC Virtual): Menangkap semua lalu lintas sistem, saat diaktifkan, tidak perlu mengaktifkan proksi sistem.", - "Stack": "Tumpukan Tun", - "System and Mixed Can Only be Used in Service Mode": "Sistem dan Campuran Hanya Dapat Digunakan dalam Mode Layanan", - "Device": "Nama Perangkat", - "Auto Route": "Rute Otomatis", - "Strict Route": "Rute Ketat", - "Auto Detect Interface": "Deteksi Antarmuka Otomatis", - "DNS Hijack": "Pembajakan DNS", - "MTU": "Unit Transmisi Maksimum", - "Service Mode": "Mode Layanan", - "Service Mode Info": "Harap instal mode layanan sebelum mengaktifkan mode TUN. Proses kernel yang dimulai oleh layanan dapat memperoleh izin untuk menginstal kartu jaringan virtual (mode TUN)", - "Current State": "Status Saat Ini", - "pending": "tertunda", - "installed": "terinstal", - "uninstall": "dicopot", - "active": "aktif", - "unknown": "tidak diketahui", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "Informasi: Harap pastikan bahwa Layanan Clash Verge terinstal dan diaktifkan", - "Install": "Instal", - "Uninstall": "Copot", - "Disable Service Mode": "Nonaktifkan Mode Layanan", - "System Proxy": "Proksi Sistem", - "System Proxy Info": "Aktifkan untuk mengubah pengaturan proksi sistem operasi. Jika pengaktifan gagal, ubah pengaturan proksi sistem operasi secara manual", - "System Proxy Setting": "Pengaturan Proksi Sistem", - "Current System Proxy": "Proksi Sistem Saat Ini", - "Enable status": "Status Pengaktifan:", - "Enabled": "Diaktifkan", - "Disabled": "Dinonaktifkan", - "Server Addr": "Alamat Server: ", - "Proxy Host": "Host Proksi", - "Invalid Proxy Host Format": "Format Host Proksi Tidak Valid", - "Not available": "Tidak tersedia", - "Proxy Guard": "Penjaga Proksi", - "Proxy Guard Info": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi", - "Guard Duration": "Durasi Penjagaan", - "Always use Default Bypass": "Selalu gunakan Bypass Default", - "Proxy Bypass": "Pengaturan Bypass Proksi: ", - "Bypass": "Bypass: ", - "Use PAC Mode": "Gunakan Mode PAC", - "PAC Script Content": "Konten Skrip PAC", - "PAC URL": "URL PAC: ", - "Auto Launch": "Peluncuran Otomatis", - "Silent Start": "Mulai Senyap", - "Silent Start Info": "Mulai program dalam mode latar belakang tanpa menampilkan panel", - "TG Channel": "Saluran Telegram", - "Manual": "Manual", - "Github Repo": "Repositori Github", - "Clash Setting": "Pengaturan Clash", - "Allow Lan": "Izinkan LAN", - "Network Interface": "Antarmuka Jaringan", - "Ip Address": "Alamat IP", - "Mac Address": "Alamat MAC", - "IPv6": "IPv6", - "Unified Delay": "Keterlambatan Terpadu", - "Unified Delay Info": "Saat keterlambatan terpadu diaktifkan, dua tes keterlambatan akan dilakukan untuk menghilangkan perbedaan keterlambatan antara berbagai jenis node yang disebabkan oleh jabat tangan koneksi, dll.", - "Log Level": "Tingkat Log", - "Log Level Info": "Ini hanya berlaku untuk file log kernel di folder layanan di direktori log.", - "Port Config": "Konfigurasi Port", - "Random Port": "Port Acak", - "Mixed Port": "Port Campuran", - "Socks Port": "Port Socks", - "Http Port": "Port Http(s)", - "Redir Port": "Port Redir", - "Tproxy Port": "Port Tproxy", - "External": "Eksternal", - "External Controller": "Alamat Pengendali Eksternal", - "Core Secret": "Rahasia Inti", - "Recommended": "Direkomendasikan", - "Open URL": "Buka URL", - "Replace host, port, secret with %host, %port, %secret": "Ganti host, port, rahasia dengan %host, %port, %secret", - "Support %host, %port, %secret": "Dukung %host, %port, %secret", - "Clash Core": "Inti Clash", - "Upgrade": "Tingkatkan", - "Restart": "Mulai Ulang", - "Release Version": "Versi Rilis", - "Alpha Version": "Versi Alpha", - "Please Enable Service Mode": "Harap Instal dan Aktifkan Mode Layanan Terlebih Dahulu", - "Please enter your root password": "Harap masukkan kata sandi root Anda", - "Grant": "Izinkan", - "Open UWP tool": "Buka alat UWP", - "Open UWP tool Info": "Sejak Windows 8, aplikasi UWP (seperti Microsoft Store) dibatasi dari mengakses layanan jaringan host lokal secara langsung, dan alat ini dapat digunakan untuk melewati pembatasan ini", - "Update GeoData": "Perbarui GeoData", - "Verge Basic Setting": "Pengaturan Dasar Verge", - "Verge Advanced Setting": "Pengaturan Lanjutan Verge", - "Language": "Bahasa", - "Theme Mode": "Mode Tema", - "theme.light": "Terang", - "theme.dark": "Gelap", - "theme.system": "Sistem", - "Tray Click Event": "Acara Klik Tray", - "Show Main Window": "Tampilkan Jendela Utama", - "Copy Env Type": "Salin Jenis Env", - "Copy Success": "Salin Berhasil", - "Start Page": "Halaman Mulai", - "Startup Script": "Skrip Startup", - "Browse": "Jelajahi", - "Theme Setting": "Pengaturan Tema", - "Primary Color": "Warna Utama", - "Secondary Color": "Warna Sekunder", - "Primary Text": "Teks Utama", - "Secondary Text": "Teks Sekunder", - "Info Color": "Warna Info", - "Warning Color": "Warna Peringatan", - "Error Color": "Warna Kesalahan", - "Success Color": "Warna Keberhasilan", - "Font Family": "Keluarga Font", - "CSS Injection": "Injeksi CSS", - "Layout Setting": "Pengaturan Tata Letak", - "Traffic Graph": "Grafik Lalu Lintas", - "Memory Usage": "Penggunaan Memori", - "Memory Cleanup": "Ketuk untuk membersihkan memori", - "Proxy Group Icon": "Ikon Grup Proksi", - "Nav Icon": "Ikon Navigasi", - "Monochrome": "Monokrom", - "Colorful": "Berwarna", - "Tray Icon": "Ikon Tray", - "Common Tray Icon": "Ikon Tray Umum", - "System Proxy Tray Icon": "Ikon Tray Proksi Sistem", - "Tun Tray Icon": "Ikon Tray Tun", - "Miscellaneous": "Lain-lain", - "App Log Level": "Tingkat Log Aplikasi", - "Auto Close Connections": "Tutup Koneksi Otomatis", - "Auto Close Connections Info": "Hentikan koneksi yang sudah ada saat pemilihan grup proksi atau mode proksi berubah", - "Auto Check Update": "Periksa Pembaruan Otomatis", - "Enable Builtin Enhanced": "Aktifkan Peningkatan Bawaan", - "Enable Builtin Enhanced Info": "Penanganan kompatibilitas untuk file konfigurasi", - "Proxy Layout Columns": "Kolom Tata Letak Proksi", - "Auto Columns": "Kolom Otomatis", - "Auto Log Clean": "Pembersihan Log Otomatis", - "Never Clean": "Jangan Pernah Bersihkan", - "Retain _n Days": "Simpan {{n}} Hari", - "Auto Delay Detection": "Deteksi Latensi Otomatis", - "Auto Delay Detection Info": "Secara berkala menguji latensi node saat ini di latar belakang", - "Default Latency Test": "Tes Latensi Default", - "Default Latency Test Info": "Digunakan hanya untuk pengujian permintaan klien HTTP dan tidak akan mempengaruhi file konfigurasi", - "Default Latency Timeout": "Waktu Habis Latensi Default", - "Hotkey Setting": "Pengaturan Pintasan", - "Enable Global Hotkey": "Aktifkan Hotkey Global", - "open_or_close_dashboard": "Buka/Tutup Dasbor", - "clash_mode_rule": "Mode Aturan", - "clash_mode_global": "Mode Global", - "clash_mode_direct": "Mode Langsung", - "toggle_system_proxy": "Aktifkan/Nonaktifkan Proksi Sistem", - "toggle_tun_mode": "Aktifkan/Nonaktifkan Mode Tun", - "Backup Setting": "Pengaturan Cadangan", - "Backup Setting Info": "Mendukung file konfigurasi cadangan WebDAV", - "Runtime Config": "Konfigurasi Runtime", - "Open Conf Dir": "Buka Direktori Konfigurasi", - "Open Conf Dir Info": "Jika perangkat lunak berjalan tidak normal, CADANGKAN dan hapus semua file di folder ini lalu mulai ulang perangkat lunak", - "Open Core Dir": "Buka Direktori Core", - "Open Logs Dir": "Buka Direktori Log", - "Check for Updates": "Periksa Pembaruan", - "Go to Release Page": "Pergi ke Halaman Rilis", - "Portable Updater Error": "Versi portabel tidak mendukung pembaruan dalam aplikasi. Harap unduh dan ganti secara manual", - "Break Change Update Error": "Versi ini adalah pembaruan besar dan tidak mendukung pembaruan dalam aplikasi. Harap hapus instalasi dan unduh serta instal versi baru secara manual", - "Open Dev Tools": "Buka Alat Pengembang", - "Exit": "Keluar", - "Verge Version": "Versi Verge", - "ReadOnly": "Hanya Baca", - "ReadOnlyMessage": "Tidak dapat mengedit di editor hanya baca", - "Filter": "Filter", - "Filter conditions": "Kondisi Filter", - "Match Case": "Cocokkan Kasus", - "Match Whole Word": "Cocokkan Kata Utuh", - "Use Regular Expression": "Gunakan Ekspresi Reguler", - "Profile Imported Successfully": "Profil Berhasil Diimpor", - "Profile Switched": "Profil Beralih", - "Profile Reactivated": "Profil Diaktifkan Kembali", - "Only YAML Files Supported": "Hanya File YAML yang Didukung", - "Settings Applied": "Pengaturan Diterapkan", - "Installing Service...": "Memasang Layanan...", - "Service Installed Successfully": "Layanan Berhasil Diinstal", - "Service Uninstalled Successfully": "Layanan Berhasil Dicopot", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Durasi Daemon Proksi Tidak Boleh Kurang dari 1 Detik", - "Invalid Bypass Format": "Format Bypass Tidak Valid", - "Clash Port Modified": "Port Clash Diubah", - "Port Conflict": "Konflik Port", - "Restart Application to Apply Modifications": "Mulai Ulang Aplikasi untuk Menerapkan Modifikasi", - "External Controller Address Modified": "Alamat Pengendali Eksternal Diubah", - "Permissions Granted Successfully for _clash Core": "Izin Berhasil Diberikan untuk Core {{core}}", - "Core Version Updated": "Versi Core Diperbarui", - "Clash Core Restarted": "Core Clash Dimulai Ulang", - "GeoData Updated": "GeoData Diperbarui", - "Currently on the Latest Version": "Saat ini pada Versi Terbaru", - "Import Subscription Successful": "Berlangganan Berhasil Diimpor", - "WebDAV Server URL": "URL Server WebDAV", - "Username": "Nama Pengguna", - "Password": "Kata Sandi", - "Backup": "Cadangan", - "Filename": "Nama Berkas", - "Actions": "Tindakan", - "Restore": "Pulihkan", - "No Backups": "Tidak ada cadangan yang tersedia", - "WebDAV URL Required": "URL WebDAV tidak boleh kosong", - "Invalid WebDAV URL": "Format URL WebDAV tidak valid", - "Username Required": "Nama pengguna tidak boleh kosong", - "Password Required": "Kata sandi tidak boleh kosong", - "Failed to Fetch Backups": "Gagal mengambil file cadangan", - "WebDAV Config Saved": "Konfigurasi WebDAV berhasil disimpan", - "WebDAV Config Save Failed": "Gagal menyimpan konfigurasi WebDAV: {{error}}", - "Backup Created": "Cadangan berhasil dibuat", - "Backup Failed": "Cadangan gagal: {{error}}", - "Delete Backup": "Hapus Cadangan", - "Restore Backup": "Pulihkan Cadangan", - "Backup Time": "Waktu Cadangan", - "Confirm to delete this backup file?": "Konfirmasi untuk menghapus file cadangan ini?", - "Confirm to restore this backup file?": "Konfirmasi untuk memulihkan file cadangan ini?", - "Restore Success, App will restart in 1s": "Pemulihan Berhasil, Aplikasi akan dimulai ulang dalam 1 detik", - "Failed to fetch backup files": "Gagal mengambil file cadangan", - "Profile": "Profil", - "Help": "Bantuan", - "About": "Tentang", - "Theme": "Tema", - "Main Window": "Jendela Utama", - "Group Icon": "Ikon Grup", - "Menu Icon": "Ikon Menu", - "PAC File": "Berkas PAC", - "Web UI": "Antarmuka Web", - "Hotkeys": "Pintasan", - "Verge Mixed Port": "Port Campuran Verge", - "Verge Socks Port": "Port Socks Verge", - "Verge Redir Port": "Port Pengalihan Verge", - "Verge Tproxy Port": "Port Tproxy Verge", - "Verge Port": "Port Verge", - "Verge HTTP Enabled": "HTTP Verge Diaktifkan", - "WebDAV URL": "URL WebDAV", - "WebDAV Username": "Nama Pengguna WebDAV", - "WebDAV Password": "Kata Sandi WebDAV", - "Dashboard": "Dasbor", - "Restart App": "Mulai Ulang Aplikasi", - "Restart Clash Core": "Mulai Ulang Core Clash", - "TUN Mode": "Mode TUN", - "Copy Env": "Salin Env", - "Conf Dir": "Direktori Konfigurasi", - "Core Dir": "Direktori Core", - "Logs Dir": "Direktori Log", - "Open Dir": "Buka Direktori", - "More": "Lainnya", - "Rule Mode": "Mode Aturan", - "Global Mode": "Mode Global", - "Direct Mode": "Mode Langsung", - "Enable Tray Speed": "Aktifkan Tray Speed", - "LightWeight Mode": "Mode Ringan", - "LightWeight Mode Info": "Tutup GUI dan biarkan hanya kernel yang berjalan", - "Config Validation Failed": "Validasi konfigurasi langganan gagal, periksa file konfigurasi, perubahan dibatalkan, detail kesalahan:", - "Boot Config Validation Failed": "Validasi konfigurasi saat boot gagal, menggunakan konfigurasi default, periksa file konfigurasi, detail kesalahan:", - "Core Change Config Validation Failed": "Validasi konfigurasi saat ganti inti gagal, menggunakan konfigurasi default, periksa file konfigurasi, detail kesalahan:", - "Config Validation Process Terminated": "Proses validasi dihentikan", - "Script Syntax Error": "Kesalahan sintaks skrip, perubahan dibatalkan", - "Script Missing Main": "Kesalahan skrip, perubahan dibatalkan", - "File Not Found": "File tidak ditemukan, perubahan dibatalkan", - "Script File Error": "Kesalahan file skrip, perubahan dibatalkan", - "Core Changed Successfully": "Inti berhasil diubah", - "Failed to Change Core": "Gagal mengubah inti", - "Service Administrator Prompt": "Clash Verge memerlukan hak administrator untuk menginstal ulang layanan sistem", - "Default": "Default", - "Label-Test": "Tes", - "Verge Setting": "Pengaturan Verge" -} diff --git a/src/locales/id/connections.json b/src/locales/id/connections.json new file mode 100644 index 000000000..1616eeeb0 --- /dev/null +++ b/src/locales/id/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Koneksi" + }, + "components": { + "fields": { + "host": "Host", + "dlSpeed": "Kecepatan Unduh", + "ulSpeed": "Kecepatan Unggah", + "chains": "Rantai", + "rule": "Aturan", + "process": "Proses", + "time": "Waktu", + "source": "Sumber", + "destination": "IP Tujuan", + "destinationPort": "Port Tujuan", + "type": "Jenis" + }, + "order": { + "default": "Default", + "uploadSpeed": "Kecepatan Unggah", + "downloadSpeed": "Kecepatan Unduh" + }, + "actions": { + "closeConnection": "Tutup Koneksi" + } + } +} diff --git a/src/locales/id/home.json b/src/locales/id/home.json new file mode 100644 index 000000000..89d28169e --- /dev/null +++ b/src/locales/id/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Mode Ringan", + "manual": "Manual", + "settings": "Home Settings" + }, + "cards": { + "trafficStats": "Traffic Stats", + "networkSettings": "Network Settings", + "proxyMode": "Proxy Mode" + }, + "settings": { + "cards": { + "profile": "Profile Card", + "currentProxy": "Current Proxy Card", + "network": "Network Settings Card", + "proxyMode": "Proxy Mode Card", + "traffic": "Traffic Stats Card", + "tests": "Website Tests Card", + "ip": "IP Information Card", + "clashInfo": "Clash Info Cards", + "systemInfo": "System Info Cards" + }, + "title": "Home Settings" + }, + "title": "Home" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "System proxy is enabled, your applications will access the network through the proxy", + "systemProxyDisabled": "System proxy is disabled, it is recommended for most users to turn on this option", + "tunModeServiceRequired": "TUN mode requires service mode, please install the service first", + "tunModeEnabled": "TUN mode is enabled, applications will access the network through the virtual network card", + "tunModeDisabled": "TUN mode is disabled, suitable for special applications" + }, + "tooltips": { + "systemProxy": "Aktifkan untuk mengubah pengaturan proksi sistem operasi. Jika pengaktifan gagal, ubah pengaturan proksi sistem operasi secara manual", + "tunMode": "TUN mode can take over all application traffic, suitable for special applications that do not follow the system proxy settings" + } + }, + "clashInfo": { + "title": "Clash Info", + "fields": { + "coreVersion": "Core Version", + "systemProxyAddress": "System Proxy Address", + "mixedPort": "Mixed Port", + "uptime": "Uptime", + "rulesCount": "Rules Count" + } + }, + "systemInfo": { + "title": "System Info", + "fields": { + "osInfo": "OS Info", + "autoLaunch": "Peluncuran Otomatis", + "runningMode": "Running Mode", + "lastCheckUpdate": "Last Check Update", + "vergeVersion": "Versi Verge" + }, + "actions": { + "settings": "Pengaturan" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "Mode Layanan", + "sidecarMode": "User Mode", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP Information", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Auto refresh", + "unknown": "Unknown" + }, + "errors": { + "load": "Gagal mendapatkan informasi IP" + } + }, + "currentProxy": { + "title": "Current Node", + "actions": { + "refreshDelay": "Periksa Keterlambatan" + }, + "labels": { + "globalMode": "Mode Global", + "directMode": "Mode Langsung", + "group": "Group", + "proxy": "Proxy", + "noActiveNode": "No active proxy node" + } + }, + "tests": { + "title": "Website Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Kecepatan Unggah", + "downloadSpeed": "Kecepatan Unduh", + "activeConnections": "Active Connections", + "memoryUsage": "Penggunaan Memori" + }, + "legends": { + "upload": "Upload", + "download": "Download" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Mode Aturan", + "global": "Mode Global", + "direct": "Mode Langsung" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/id/index.ts b/src/locales/id/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/id/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/id/layout.json b/src/locales/id/layout.json new file mode 100644 index 000000000..8840853ca --- /dev/null +++ b/src/locales/id/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Home", + "proxies": "Proksi", + "profiles": "Profil", + "connections": "Koneksi", + "rules": "Aturan", + "logs": "Log", + "unlock": "Test", + "settings": "Pengaturan" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/id/logs.json b/src/locales/id/logs.json new file mode 100644 index 000000000..b41b2a76b --- /dev/null +++ b/src/locales/id/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Log" + } +} diff --git a/src/locales/id/profiles.json b/src/locales/id/profiles.json new file mode 100644 index 000000000..e88b19012 --- /dev/null +++ b/src/locales/id/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Perbarui Semua Profil", + "viewRuntimeConfig": "Lihat Konfigurasi Runtime", + "reactivate": "Reaktivasi Profil", + "import": "Impor" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "URL Profil", + "actions": { + "paste": "Tempel" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Hanya File YAML yang Didukung" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Profil Beralih", + "profileReactivated": "Profil Diaktifkan Kembali", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Profil" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Click to import subscription" + } + }, + "fileInput": { + "chooseFile": "Pilih Berkas" + }, + "menu": { + "home": "Home", + "select": "Pilih", + "editInfo": "Ubah Info", + "editFile": "Ubah Berkas", + "editRules": "Ubah Aturan", + "editProxies": "Ubah Proksi", + "editGroups": "Ubah Grup Proksi", + "extendConfig": "Perluas Konfigurasi", + "extendScript": "Perluas Skrip", + "openFile": "Buka Berkas", + "update": "Perbarui", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Buat Profil", + "edit": "Ubah Profil" + }, + "fields": { + "type": "Jenis", + "description": "Deskripsi", + "subscriptionUrl": "URL Langganan", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Interval Pembaruan", + "useSystemProxy": "Gunakan Proksi Sistem", + "useClashProxy": "Gunakan Proksi Clash", + "acceptInvalidCerts": "Terima Sertifikat Tidak Valid (Bahaya)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "Ubah Proksi", + "placeholders": { + "multiUri": "Gunakan baris baru untuk beberapa URI (mendukung pengkodean Base64)" + }, + "actions": { + "prepend": "Tambahkan Proksi di Awal", + "append": "Tambahkan Proksi di Akhir" + } + }, + "groupsEditor": { + "title": "Ubah Grup Proksi", + "errors": { + "nameRequired": "Nama Grup Diperlukan", + "nameExists": "Nama Grup Sudah Ada" + }, + "fields": { + "type": "Jenis Grup", + "name": "Nama Grup", + "icon": "Ikon Grup Proksi", + "proxies": "Gunakan Proksi", + "provider": "Gunakan Penyedia", + "healthCheckUrl": "URL Pemeriksaan Kesehatan", + "expectedStatus": "Status yang Diharapkan", + "interval": "Interval", + "maxFailedTimes": "Jumlah Gagal Maksimal", + "interfaceName": "Nama Antarmuka", + "routingMark": "Tanda Routing", + "filter": "Filter", + "excludeFilter": "Kecualikan Filter", + "excludeType": "Kecualikan Jenis", + "includeAll": "Sertakan Semua Proksi dan Penyedia", + "includeAllProxies": "Sertakan Semua Proksi", + "includeAllProviders": "Sertakan Semua Penyedia" + }, + "toggles": { + "lazy": "Malas", + "disableUdp": "Nonaktifkan UDP", + "hidden": "Tersembunyi" + }, + "actions": { + "prepend": "Tambahkan Grup di Awal", + "append": "Tambahkan Grup di Akhir" + } + }, + "editor": { + "actions": { + "format": "Format dokumen" + }, + "messages": { + "readOnly": "Tidak dapat mengedit di editor hanya baca" + } + }, + "confirmDelete": { + "title": "Konfirmasi penghapusan", + "message": "Operasi ini tidak dapat dibatalkan" + }, + "logViewer": { + "title": "Konsol Skrip" + } + } +} diff --git a/src/locales/id/proxies.json b/src/locales/id/proxies.json new file mode 100644 index 000000000..cc1d01776 --- /dev/null +++ b/src/locales/id/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Proxy Rantai", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Penyedia Proksi", + "actions": { + "updateAll": "Perbarui Semua", + "update": "Perbarui" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "Periksa keterlambatan untuk membatalkan tetap" + }, + "tooltips": { + "locate": "Lokasi", + "delayCheck": "Periksa Keterlambatan", + "sortDefault": "Urutkan secara default", + "sortDelay": "Urutkan berdasarkan keterlambatan", + "sortName": "Urutkan berdasarkan nama", + "delayCheckUrl": "URL Periksa Keterlambatan", + "showBasic": "Dasar Proksi", + "showDetail": "Detail Proksi", + "filter": "Filter" + }, + "placeholders": { + "delayCheckUrl": "URL Periksa Keterlambatan" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Mode Langsung" + }, + "title": { + "default": "Grup Proksi", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Pilih proksi secara manual", + "url-test": "Pilih proksi berdasarkan keterlambatan tes URL", + "fallback": "Beralih ke proksi lain saat terjadi kesalahan", + "load-balance": "Distribusikan proksi berdasarkan penyeimbangan beban", + "relay": "Lewatkan melalui rantai proksi yang ditentukan" + }, + "policies": { + "DIRECT": "Data langsung keluar", + "REJECT": "Mencegat permintaan", + "REJECT-DROP": "Membuang permintaan", + "PASS": "Lewati aturan ini saat cocok" + } + } + } +} diff --git a/src/locales/id/rules.json b/src/locales/id/rules.json new file mode 100644 index 000000000..1006ba936 --- /dev/null +++ b/src/locales/id/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Penyedia Aturan", + "dialogTitle": "Penyedia Aturan", + "actions": { + "updateAll": "Perbarui Semua", + "update": "Perbarui" + } + }, + "title": "Aturan" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Jenis Aturan", + "content": "Konten Aturan", + "proxyPolicy": "Kebijakan Proksi" + }, + "toggles": { + "noResolve": "Tidak Menyelesaikan" + }, + "actions": { + "prependRule": "Tambahkan Aturan di Awal", + "appendRule": "Tambahkan Aturan di Akhir" + }, + "validation": { + "conditionRequired": "Kondisi Aturan Diperlukan", + "invalidRule": "Aturan Tidak Valid" + } + }, + "ruleTypes": { + "DOMAIN": "Cocok dengan nama domain lengkap", + "DOMAIN-SUFFIX": "Cocok dengan sufiks domain", + "DOMAIN-KEYWORD": "Cocok dengan kata kunci domain", + "DOMAIN-REGEX": "Cocok dengan domain menggunakan ekspresi reguler", + "GEOSITE": "Cocok dengan domain dalam Geosite", + "GEOIP": "Cocok dengan kode negara alamat IP", + "SRC-GEOIP": "Cocok dengan kode negara alamat IP sumber", + "IP-ASN": "Cocok dengan ASN alamat IP", + "SRC-IP-ASN": "Cocok dengan ASN alamat IP sumber", + "IP-CIDR": "Cocok dengan rentang alamat IP", + "IP-CIDR6": "Cocok dengan rentang alamat IPv6", + "SRC-IP-CIDR": "Cocok dengan rentang alamat IP sumber", + "IP-SUFFIX": "Cocok dengan rentang sufiks alamat IP", + "SRC-IP-SUFFIX": "Cocok dengan rentang sufiks alamat IP sumber", + "SRC-PORT": "Cocok dengan rentang port sumber", + "DST-PORT": "Cocok dengan rentang port tujuan", + "IN-PORT": "Cocok dengan port masuk", + "DSCP": "Penandaan DSCP (hanya untuk tproxy UDP masuk)", + "PROCESS-NAME": "Cocok dengan nama proses (nama paket Android)", + "PROCESS-PATH": "Cocok dengan jalur proses lengkap", + "PROCESS-NAME-REGEX": "Cocok dengan nama proses lengkap menggunakan ekspresi reguler (nama paket Android)", + "PROCESS-PATH-REGEX": "Cocok dengan jalur proses lengkap menggunakan ekspresi reguler", + "NETWORK": "Cocok dengan protokol transportasi (tcp/udp)", + "UID": "Cocok dengan ID PENGGUNA Linux", + "IN-TYPE": "Cocok dengan jenis masuk", + "IN-USER": "Cocok dengan nama pengguna masuk", + "IN-NAME": "Cocok dengan nama masuk", + "SUB-RULE": "Sub-aturan", + "RULE-SET": "Cocok dengan set aturan", + "AND": "Logika DAN", + "OR": "Logika ATAU", + "NOT": "Logika TIDAK", + "MATCH": "Cocok dengan semua permintaan" + }, + "title": "Ubah Aturan" + } + } +} diff --git a/src/locales/id/settings.json b/src/locales/id/settings.json new file mode 100644 index 000000000..4196f7fa4 --- /dev/null +++ b/src/locales/id/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Manual", + "telegram": "Saluran Telegram", + "github": "Repositori Github" + }, + "title": "Pengaturan" + }, + "sections": { + "system": { + "title": "Pengaturan Sistem", + "toggles": { + "tunMode": "Mode Tun (NIC Virtual)", + "systemProxy": "Proksi Sistem" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "Mulai program dalam mode latar belakang tanpa menampilkan panel" + }, + "fields": { + "autoLaunch": "Mulai otomatis", + "silentStart": "Mulai senyap" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Aktifkan untuk mengubah pengaturan proksi sistem operasi. Jika pengaktifan gagal, ubah pengaturan proksi sistem operasi secara manual", + "tunMode": "Mode Tun (NIC Virtual): Menangkap semua lalu lintas sistem, saat diaktifkan, tidak perlu mengaktifkan proksi sistem.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "Instal Layanan", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "Proksi Sistem", + "tunMode": "Mode Tun (NIC Virtual)" + } + }, + "externalController": { + "title": "Alamat Pengendali Eksternal", + "fields": { + "enable": "Enable External Controller", + "address": "Alamat Pengendali Eksternal", + "secret": "Rahasia Inti" + }, + "placeholders": { + "address": "Required", + "secret": "Direkomendasikan" + }, + "tooltips": { + "copy": "Copy to clipboard" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Failed to copy", + "controllerCopied": "Controller address copied to clipboard", + "secretCopied": "Secret copied to clipboard" + } + }, + "externalCors": { + "title": "External Cors Configuration", + "fields": { + "allowPrivateNetwork": "Allow private network access", + "allowedOrigins": "Allowed Origins" + }, + "placeholders": { + "origin": "Please enter a valid url" + }, + "actions": { + "add": "Add" + }, + "messages": { + "alwaysIncluded": "Always included origins: {{urls}}" + }, + "tooltips": { + "open": "External Cors Settings" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Pengaturan Clash", + "form": { + "fields": { + "allowLan": "Izinkan LAN", + "dnsOverwrite": "DNS Overwrite", + "ipv6": "IPv6", + "unifiedDelay": "Keterlambatan Terpadu", + "logLevel": "Tingkat Log", + "portConfig": "Konfigurasi Port", + "external": "Eksternal", + "webUI": "Antarmuka Web", + "clashCore": "Inti Clash", + "openUwpTool": "Buka alat UWP", + "updateGeoData": "Perbarui GeoData" + }, + "tooltips": { + "networkInterface": "Antarmuka Jaringan", + "unifiedDelay": "Saat keterlambatan terpadu diaktifkan, dua tes keterlambatan akan dilakukan untuk menghilangkan perbedaan keterlambatan antara berbagai jenis node yang disebabkan oleh jabat tangan koneksi, dll.", + "logLevel": "Ini hanya berlaku untuk file log kernel di folder layanan di direktori log.", + "openUwpTool": "Sejak Windows 8, aplikasi UWP (seperti Microsoft Store) dibatasi dari mengakses layanan jaringan host lokal secara langsung, dan alat ini dapat digunakan untuk melewati pembatasan ini" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Pengaturan Dasar Verge", + "actions": { + "browse": "Jelajahi" + }, + "trayOptions": { + "showMainWindow": "Tampilkan Jendela Utama", + "showTrayMenu": "Show Tray Menu", + "disable": "Nonaktifkan" + }, + "fields": { + "language": "Bahasa", + "themeMode": "Mode Tema", + "trayClickEvent": "Acara Klik Tray", + "copyEnvType": "Salin Jenis Env", + "startPage": "Halaman Mulai", + "startupScript": "Skrip Startup", + "themeSetting": "Pengaturan Tema", + "layoutSetting": "Pengaturan Tata Letak", + "misc": "Lain-lain", + "hotkeySetting": "Pengaturan Pintasan" + } + }, + "advanced": { + "title": "Pengaturan Lanjutan Verge", + "tooltips": { + "backupInfo": "Mendukung file konfigurasi cadangan WebDAV", + "openConfDir": "Jika perangkat lunak berjalan tidak normal, CADANGKAN dan hapus semua file di folder ini lalu mulai ulang perangkat lunak", + "liteMode": "Tutup GUI dan biarkan hanya kernel yang berjalan" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Saat ini pada Versi Terbaru", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Pengaturan Cadangan", + "runtimeConfig": "Konfigurasi Runtime", + "openConfDir": "Buka Direktori Konfigurasi", + "openCoreDir": "Buka Direktori Core", + "openLogsDir": "Buka Direktori Log", + "checkUpdates": "Periksa Pembaruan", + "openDevTools": "Buka Alat Pengembang", + "liteModeSettings": "LightWeight Mode Settings", + "exit": "Keluar", + "exportDiagnostics": "Export Diagnostic Info", + "vergeVersion": "Versi Verge" + } + }, + "theme": { + "title": "Pengaturan Tema", + "fields": { + "primaryColor": "Warna Utama", + "secondaryColor": "Warna Sekunder", + "primaryText": "Teks Utama", + "secondaryText": "Teks Sekunder", + "infoColor": "Warna Info", + "warningColor": "Warna Peringatan", + "errorColor": "Warna Kesalahan", + "successColor": "Warna Keberhasilan", + "fontFamily": "Keluarga Font", + "cssInjection": "Injeksi CSS" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Pengaturan Tata Letak", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Grafik Lalu Lintas", + "memoryUsage": "Penggunaan Memori", + "proxyGroupIcon": "Ikon Grup Proksi", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Ikon Navigasi", + "trayIcon": "Ikon Tray", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Ikon Tray Umum", + "systemProxyTrayIcon": "Ikon Tray Proksi Sistem", + "tunTrayIcon": "Ikon Tray Tun", + "enableTrayIcon": "Enable Tray Icon", + "enableTraySpeed": "Aktifkan Tray Speed" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Monokrom", + "colorful": "Berwarna", + "disable": "Nonaktifkan" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Konfigurasi Port", + "fields": { + "mixed": "Port Campuran", + "socks": "Port Socks", + "http": "Port Http(s)", + "redir": "Port Redir", + "tproxy": "Port Tproxy" + }, + "actions": { + "random": "Port Acak" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Versi Rilis", + "alpha": "Versi Alpha" + } + }, + "liteMode": { + "title": "LightWeight Mode Settings", + "actions": { + "enterNow": "Enter LightWeight Mode Now" + }, + "toggles": { + "autoEnter": "Auto Enter LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time" + }, + "fields": { + "delay": "Auto Enter LightWeight Mode Delay" + }, + "messages": { + "autoEnterHint": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes" + } + }, + "backup": { + "title": "Pengaturan Cadangan", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Cadangan", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Hapus Cadangan", + "restore": "Pulihkan", + "restoreBackup": "Pulihkan Cadangan" + }, + "fields": { + "webdavUrl": "URL Server WebDAV", + "username": "Nama Pengguna", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "URL WebDAV tidak boleh kosong", + "invalidWebdavUrl": "Format URL WebDAV tidak valid", + "usernameRequired": "Nama pengguna tidak boleh kosong", + "passwordRequired": "Kata sandi tidak boleh kosong", + "webdavConfigSaved": "Konfigurasi WebDAV berhasil disimpan", + "webdavConfigSaveFailed": "Gagal menyimpan konfigurasi WebDAV: {{error}}", + "backupCreated": "Cadangan berhasil dibuat", + "backupFailed": "Cadangan gagal: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Pemulihan Berhasil, Aplikasi akan dimulai ulang dalam 1 detik", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Konfirmasi untuk menghapus file cadangan ini?", + "confirmRestore": "Konfirmasi untuk memulihkan file cadangan ini?" + }, + "table": { + "filename": "Nama Berkas", + "backupTime": "Waktu Cadangan", + "actions": "Tindakan", + "noBackups": "Tidak ada cadangan yang tersedia", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Lain-lain", + "fields": { + "appLogLevel": "Tingkat Log Aplikasi", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Tutup Koneksi Otomatis", + "autoCheckUpdate": "Periksa Pembaruan Otomatis", + "enableBuiltinEnhanced": "Aktifkan Peningkatan Bawaan", + "proxyLayoutColumns": "Kolom Tata Letak Proksi", + "autoLogClean": "Pembersihan Log Otomatis", + "autoDelayDetection": "Deteksi Latensi Otomatis", + "defaultLatencyTest": "Tes Latensi Default", + "defaultLatencyTimeout": "Waktu Habis Latensi Default" + }, + "tooltips": { + "autoCloseConnections": "Hentikan koneksi yang sudah ada saat pemilihan grup proksi atau mode proksi berubah", + "enableBuiltinEnhanced": "Penanganan kompatibilitas untuk file konfigurasi", + "autoDelayDetection": "Secara berkala menguji latensi node saat ini di latar belakang", + "defaultLatencyTest": "Digunakan hanya untuk pengujian permintaan klien HTTP dan tidak akan mempengaruhi file konfigurasi" + }, + "options": { + "proxyLayoutColumns": { + "auto": "Kolom Otomatis" + }, + "autoLogClean": { + "never": "Jangan Pernah Bersihkan", + "retainDays": "Simpan {{n}} Hari" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Pergi ke Halaman Rilis", + "update": "Perbarui" + }, + "messages": { + "portableError": "Versi portabel tidak mendukung pembaruan dalam aplikasi. Harap unduh dan ganti secara manual", + "breakChangeError": "Versi ini adalah pembaruan besar dan tidak mendukung pembaruan dalam aplikasi. Harap hapus instalasi dan unduh serta instal versi baru secara manual" + } + }, + "sysproxy": { + "title": "Pengaturan Proksi Sistem", + "fieldsets": { + "currentStatus": "Proksi Sistem Saat Ini" + }, + "fields": { + "enableStatus": "Status Pengaktifan:", + "serverAddr": "Alamat Server: ", + "pacUrl": "URL PAC: ", + "proxyHost": "Host Proksi", + "usePacMode": "Gunakan Mode PAC", + "proxyGuard": "Penjaga Proksi", + "guardDuration": "Durasi Penjagaan", + "alwaysUseDefaultBypass": "Selalu gunakan Bypass Default", + "proxyBypass": "Pengaturan Bypass Proksi: ", + "bypass": "Bypass: ", + "pacScriptContent": "Konten Skrip PAC" + }, + "tooltips": { + "proxyGuard": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi" + }, + "messages": { + "durationTooShort": "Durasi Daemon Proksi Tidak Boleh Kurang dari 1 Detik", + "invalidBypass": "Format Bypass Tidak Valid", + "invalidProxyHost": "Format Host Proksi Tidak Valid" + }, + "actions": { + "editPac": "Ubah PAC" + } + }, + "tun": { + "title": "Mode Tun (NIC Virtual)", + "fields": { + "stack": "Tumpukan Tun", + "device": "Device Name", + "autoRoute": "Rute Otomatis", + "strictRoute": "Rute Ketat", + "autoDetectInterface": "Deteksi Antarmuka Otomatis", + "dnsHijack": "Pembajakan DNS", + "mtu": "Unit Transmisi Maksimum" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Pengaturan Diterapkan" + } + }, + "dns": { + "dialog": { + "title": "DNS Overwrite", + "warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled" + }, + "sections": { + "general": "DNS Settings", + "fallbackFilter": "Fallback Filter Settings", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Enable DNS", + "listen": "DNS Listen", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Fake IP Range", + "fakeIpFilterMode": "Fake IP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Prefer H3", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Respect Rules", + "description": "DNS connections follow routing rules" + }, + "useHosts": { + "label": "Use Hosts", + "description": "Enable to resolve hosts through hosts file" + }, + "useSystemHosts": { + "label": "Use System Hosts", + "description": "Enable to resolve hosts through system hosts file" + }, + "directPolicy": { + "label": "Direct Nameserver Follow Policy", + "description": "Whether to follow nameserver policy" + }, + "defaultNameserver": { + "label": "Default Nameserver", + "description": "Default DNS servers used to resolve DNS servers" + }, + "nameserver": { + "label": "Nameserver", + "description": "List of DNS servers, comma separated" + }, + "fallback": { + "label": "Fallback", + "description": "List of fallback DNS servers, comma separated" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS servers for proxy node domain resolution" + }, + "directNameserver": { + "label": "Direct Nameserver", + "description": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated" + }, + "fakeIpFilter": { + "label": "Fake IP Filter", + "description": "Domains that skip fake IP resolution, comma separated" + }, + "nameserverPolicy": { + "label": "Nameserver Policy", + "description": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtering", + "description": "Enable GeoIP filtering for fallback" + }, + "geoipCode": "GeoIP Code", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "IP CIDRs not using fallback servers, comma separated" + }, + "fallbackDomain": { + "label": "Fallback Domain", + "description": "Domains using fallback servers, comma separated" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "Buka URL" + }, + "title": "Antarmuka Web", + "messages": { + "supportedPlaceholders": "Dukung %host, %port, %secret", + "placeholderInstruction": "Ganti host, port, rahasia dengan %host, %port, %secret" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Aktifkan Hotkey Global" + }, + "title": "Pengaturan Pintasan", + "functions": { + "rule": "Mode Aturan", + "global": "Mode Global", + "openOrCloseDashboard": "Buka/Tutup Dasbor", + "toggleSystemProxy": "Aktifkan/Nonaktifkan Proksi Sistem", + "toggleTunMode": "Aktifkan/Nonaktifkan Mode Tun", + "entryLightweightMode": "Entry Lightweight Mode", + "direct": "Mode Langsung" + } + }, + "password": { + "prompts": { + "enterRoot": "Harap masukkan kata sandi root Anda" + } + }, + "networkInterface": { + "title": "Antarmuka Jaringan", + "fields": { + "ipAddress": "Alamat IP", + "macAddress": "Alamat MAC" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Core Clash Dimulai Ulang", + "versionUpdated": "Versi Core Diperbarui", + "alreadyLatestVersion": "Sudah menggunakan versi inti terbaru", + "changeSuccess": "Inti berhasil diubah", + "changeFailed": "Gagal mengubah inti", + "geoDataUpdated": "GeoData Diperbarui" + }, + "clashService": { + "installSuccess": "Layanan Berhasil Diinstal", + "uninstallSuccess": "Layanan Berhasil Dicopot" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "Memasang Layanan...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/id/shared.json b/src/locales/id/shared.json new file mode 100644 index 000000000..14eeec27a --- /dev/null +++ b/src/locales/id/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Batal", + "close": "Tutup", + "confirm": "Konfirmasi", + "save": "Simpan", + "delete": "Hapus", + "edit": "Ubah", + "new": "Baru", + "enable": "Aktifkan", + "upgrade": "Tingkatkan", + "restart": "Mulai Ulang", + "resetToDefault": "Setel Ulang ke Default", + "refresh": "Segarkan", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Tampilan Daftar", + "tableView": "Tampilan Tabel", + "pause": "Jeda", + "resume": "Lanjut", + "closeAll": "Tutup Semua", + "clear": "Bersihkan" + }, + "labels": { + "updateAt": "Diperbarui Pada", + "timeout": "Timeout", + "icon": "Ikon", + "name": "Nama", + "readOnly": "Hanya Baca", + "expireTime": "Waktu Kedaluwarsa", + "updateTime": "Waktu Pembaruan", + "usedTotal": "Digunakan / Total", + "from": "Dari", + "password": "Kata Sandi", + "retryAttempts": "Retry attempts", + "downloaded": "Diunduh", + "uploaded": "Diunggah" + }, + "statuses": { + "enabled": "Diaktifkan", + "disabled": "Dinonaktifkan", + "saving": "Saving...", + "empty": "Kosong" + }, + "units": { + "milliseconds": "milidetik", + "seconds": "detik", + "minutes": "menit", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Kondisi Filter", + "matchCase": "Cocokkan Kasus", + "matchWholeWord": "Cocokkan Kata Utuh", + "useRegex": "Gunakan Ekspresi Reguler" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Maksimalkan", + "minimize": "Minimalkan" + }, + "editorModes": { + "visualization": "Visualisasi", + "advanced": "Lanjutan" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Profil Berhasil Diimpor", + "importSubscriptionSuccess": "Berlangganan Berhasil Diimpor", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Salin Berhasil", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Validasi konfigurasi langganan gagal, periksa file konfigurasi, perubahan dibatalkan, detail kesalahan:", + "bootFailed": "Validasi konfigurasi saat boot gagal, menggunakan konfigurasi default, periksa file konfigurasi, detail kesalahan:", + "coreChangeFailed": "Validasi konfigurasi saat ganti inti gagal, menggunakan konfigurasi default, periksa file konfigurasi, detail kesalahan:", + "processTerminated": "Proses validasi dihentikan" + }, + "script": { + "syntaxError": "Kesalahan sintaks skrip, perubahan dibatalkan", + "missingMain": "Kesalahan skrip, perubahan dibatalkan", + "fileNotFound": "File tidak ditemukan, perubahan dibatalkan", + "fileError": "Kesalahan file skrip, perubahan dibatalkan" + }, + "yaml": { + "syntaxError": "YAML syntax error, changes reverted", + "readError": "YAML read error, changes reverted", + "mappingError": "YAML mapping error, changes reverted", + "keyError": "YAML key error, changes reverted", + "generalError": "YAML error, changes reverted" + }, + "merge": { + "syntaxError": "Merge file syntax error, changes reverted", + "mappingError": "Merge file mapping error, changes reverted", + "keyError": "Merge file key error, changes reverted", + "generalError": "Merge file error, changes reverted" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/id/tests.json b/src/locales/id/tests.json new file mode 100644 index 000000000..95cfa598d --- /dev/null +++ b/src/locales/id/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Tes Semua" + }, + "title": "Tes" + }, + "components": { + "item": { + "actions": { + "test": "Tes" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Buat Tes", + "edit": "Ubah Tes" + }, + "fields": { + "url": "URL Tes" + } + } + }, + "statuses": { + "test": { + "pending": "Pending", + "yes": "Yes", + "no": "No", + "failed": "Failed", + "completed": "Completed", + "disallowedIsp": "Disallowed ISP", + "originalsOnly": "Originals Only", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Unsupported Country/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Testing..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "Deteksi gagal untuk {{name}}", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Unlock Test" + } + } +} diff --git a/src/locales/jp.json b/src/locales/jp.json deleted file mode 100644 index 618e4fbd9..000000000 --- a/src/locales/jp.json +++ /dev/null @@ -1,574 +0,0 @@ -{ - "millis": "ミリ秒", - "seconds": "秒", - "mins": "分", - "Back": "戻る", - "Close": "閉じる", - "Cancel": "キャンセル", - "Confirm": "確認", - "Maximize": "最大化", - "Minimize": "最小化", - "Format document": "文書を整形する", - "Empty": "空っぽ", - "New": "新規作成", - "Edit": "編集", - "Save": "保存", - "Delete": "削除", - "Enable": "有効にする", - "Disable": "無効にする", - "Label-Home": "ホーム", - "Label-Proxies": "プロキシ", - "Label-Profiles": "プロファイル", - "Label-Connections": "接続", - "Label-Rules": "ルール", - "Label-Logs": "ログ", - "Label-Unlock": "テスト", - "Label-Settings": "設定", - "Proxy Groups": "プロキシグループ", - "Proxy Provider": "プロキシプロバイダー", - "Proxy Count": "ノード数", - "Update All": "すべて更新", - "Update At": "更新日時", - "rule": "ルール", - "global": "グローバル", - "direct": "直接接続", - "Chain Proxy": "🔗 チェーンプロキシ", - "script": "スクリプト", - "locate": "現在のノード", - "Delay check": "遅延テスト", - "Sort by default": "デフォルトでソート", - "Sort by delay": "遅延でソート", - "Sort by name": "名前でソート", - "Delay check URL": "遅延テストURL", - "Delay check to cancel fixed": "遅延テストを実行して固定を解除する", - "Proxy basic": "ノードの詳細を隠す", - "Proxy detail": "ノードの詳細を表示する", - "Profiles": "プロファイル", - "Update All Profiles": "すべてのプロファイルを更新", - "View Runtime Config": "実行時のプロファイルを表示", - "Reactivate Profiles": "プロファイルを再アクティブ化", - "Paste": "貼り付け", - "Profile URL": "プロファイルファイルのURL", - "Import": "インポート", - "From": "から", - "Update Time": "更新時間", - "Used / Total": "使用済み / 合計", - "Expire Time": "有効期限", - "Create Profile": "新規プロファイルを作成", - "Edit Profile": "プロファイルを編集", - "Edit Proxies": "ノードを編集", - "Use newlines for multiple uri": "複数のURIは改行で区切ってください(Base64エンコードに対応)", - "Edit Rules": "ルールを編集", - "Rule Type": "ルールタイプ", - "Rule Content": "ルール内容", - "Proxy Policy": "プロキシポリシー", - "No Resolve": "DNS解決をスキップ", - "Prepend Rule": "前置ルールを追加", - "Append Rule": "後置ルールを追加", - "Prepend Group": "前置プロキシグループを追加", - "Append Group": "後置プロキシグループを追加", - "Prepend Proxy": "前置プロキシノードを追加", - "Append Proxy": "後置プロキシノードを追加", - "Rule Condition Required": "ルール条件が必要です", - "Invalid Rule": "無効なルール", - "Advanced": "詳細設定", - "Visualization": "可視化", - "DOMAIN": "完全なドメイン名を一致させる", - "DOMAIN-SUFFIX": "ドメインサフィックスを一致させる", - "DOMAIN-KEYWORD": "ドメインキーワードを一致させる", - "DOMAIN-REGEX": "ドメイン正規表現を一致させる", - "GEOSITE": "Geosite内のドメインを一致させる", - "GEOIP": "IPの所属国コードを一致させる", - "SRC-GEOIP": "送信元IPの所属国コードを一致させる", - "IP-ASN": "IPの所属ASNを一致させる", - "SRC-IP-ASN": "送信元IPの所属ASNを一致させる", - "IP-CIDR": "IPアドレス範囲を一致させる", - "IP-CIDR6": "IPアドレス範囲を一致させる", - "SRC-IP-CIDR": "送信元IPアドレス範囲を一致させる", - "IP-SUFFIX": "IPサフィックス範囲を一致させる", - "SRC-IP-SUFFIX": "送信元IPサフィックス範囲を一致させる", - "SRC-PORT": "送信元ポート範囲を一致させる", - "DST-PORT": "宛先ポート範囲を一致させる", - "IN-PORT": "入力ポートを一致させる", - "DSCP": "DSCPマーク(TPROXY UDP入力のみ)", - "PROCESS-NAME": "プロセス名を一致させる(Androidパッケージ名)", - "PROCESS-PATH": "完全なプロセスパスを一致させる", - "PROCESS-NAME-REGEX": "完全なプロセス名を正規表現で一致させる(Androidパッケージ名)", - "PROCESS-PATH-REGEX": "完全なプロセスパスを正規表現で一致させる", - "NETWORK": "トランスポートプロトコルを一致させる (TCP/UDP)", - "UID": "LinuxユーザーIDを一致させる", - "IN-TYPE": "入力タイプを一致させる", - "IN-USER": "入力ユーザー名を一致させる", - "IN-NAME": "入力名を一致させる", - "SUB-RULE": "サブルール", - "RULE-SET": "ルールセットを一致させる", - "AND": "論理積", - "OR": "論理和", - "NOT": "論理否定", - "MATCH": "すべてのリクエストを一致させる", - "DIRECT": "直接接続", - "REJECT": "リクエストを拒否", - "REJECT-DROP": "リクエストを破棄", - "PASS": "このルールをスキップ", - "Edit Groups": "プロキシグループを編集", - "Group Type": "プロキシグループタイプ", - "select": "手動でプロキシを選択", - "url-test": "URLテストによる遅延でプロキシを選択", - "fallback": "利用不可の場合は別のプロキシに切り替える", - "load-balance": "負荷分散によりプロキシを割り当てる", - "relay": "定義されたプロキシチェーンに沿って転送する", - "Group Name": "プロキシグループ名", - "Use Proxies": "プロキシを導入", - "Use Provider": "プロキシプロバイダーを導入", - "Health Check Url": "ヘルスチェックURL", - "Expected Status": "期待するステータスコード", - "Interval": "チェック間隔", - "Lazy": "遅延モード", - "Timeout": "タイムアウト時間", - "Max Failed Times": "最大失敗回数", - "Interface Name": "出力インターフェース", - "Routing Mark": "ルーティングマーク", - "Include All": "すべての出力プロキシ、プロキシプロバイダーを導入", - "Include All Providers": "すべてのプロキシプロバイダーを導入", - "Include All Proxies": "すべての出力プロキシを導入", - "Exclude Filter": "除外ノード", - "Exclude Type": "除外ノードタイプ", - "Disable UDP": "UDPを無効にする", - "Hidden": "プロキシグループを隠す", - "Group Name Required": "プロキシグループ名は必須です", - "Group Name Already Exists": "プロキシグループ名はすでに存在します", - "Extend Config": "拡張上書き設定", - "Extend Script": "拡張スクリプト", - "Type": "タイプ", - "Name": "名前", - "Descriptions": "説明", - "Subscription URL": "サブスクリプションURL", - "Update Interval": "更新間隔", - "Choose File": "ファイルを選択", - "Use System Proxy": "システムプロキシを使用して更新", - "Use Clash Proxy": "クラッシュプロキシを使用して更新", - "Refresh": "更新", - "Home": "ホーム", - "Select": "使用する", - "Edit Info": "情報を編集", - "Edit File": "ファイルを編集", - "Open File": "ファイルを開く", - "Update": "更新", - "Confirm deletion": "削除を確認", - "This operation is not reversible": "この操作は元に戻せません", - "Script Console": "スクリプトコンソール出力", - "Connections": "接続", - "Table View": "テーブルビュー", - "List View": "リストビュー", - "Close All": "すべて閉じる", - "Upload": "アップロード", - "Download": "ダウンロード", - "Download Speed": "ダウンロード速度", - "Upload Speed": "アップロード速度", - "Host": "ホスト", - "Downloaded": "ダウンロード量", - "Uploaded": "アップロード量", - "DL Speed": "ダウンロード速度", - "UL Speed": "アップロード速度", - "Active Connections": "アクティブな接続", - "Chains": "チェーン", - "Rule": "ルール", - "Process": "プロセス", - "Time": "接続時間", - "Source": "送信元アドレス", - "Destination": "宛先アドレス", - "DestinationPort": "宛先ポート", - "Close Connection": "接続を閉じる", - "Rules": "ルール", - "Rule Provider": "ルールプロバイダー", - "Logs": "ログ", - "Pause": "一時停止", - "Resume": "再開", - "Clear": "クリア", - "Test": "テスト", - "Test All": "すべてテスト", - "Testing...": "テスト中...", - "Create Test": "新規テストを作成", - "Edit Test": "テストを編集", - "Icon": "アイコン", - "Test URL": "テストURL", - "Settings": "設定", - "System Setting": "システム設定", - "Tun Mode": "仮想ネットワークカードモード", - "Install Service": "サービスをインストール", - "Uninstall Service": "サービスのアンインストール", - "Reset to Default": "デフォルト値にリセット", - "Tun Mode Info": "TUN(仮想ネットワークカード)モードはシステムのすべてのトラフィックを制御します。有効にすると、システムプロキシを開く必要はありません。", - "TUN requires Service Mode or Admin Mode": "TUNモードはサービスモードまたは管理者モードが必要です", - "System Proxy Enabled": "システムプロキシが有効になっています。アプリケーションはプロキシを通じてネットワークにアクセスします。", - "System Proxy Disabled": "システムプロキシが無効になっています。ほとんどのユーザーはこのオプションをオンにすることをお勧めします。", - "TUN Mode Enabled": "TUNモードが有効になっています。アプリケーションは仮想ネットワークカードを通じてネットワークにアクセスします。", - "TUN Mode Disabled": "TUNモードが無効になっています。特殊なアプリケーションに適しています。", - "TUN Mode Service Required": "TUNモードはサービスモードが必要です。まずサービスをインストールしてください。", - "TUN Mode Intercept Info": "TUNモードはすべてのアプリケーションのトラフィックを制御できます。システムプロキシ設定に従わない特殊なアプリケーションに適しています。", - "Stack": "TUNモードスタック", - "Device": "TUNネットワークカード名", - "Auto Route": "グローバルルートを自動設定", - "Strict Route": "厳格なルート", - "Auto Detect Interface": "トラフィックの出口インターフェースを自動選択", - "DNS Hijack": "DNSハイジャック", - "MTU": "最大転送単位", - "Service Mode": "サービスモード", - "active": "アクティブ", - "unknown": "不明", - "Install": "インストール", - "Uninstall": "アンインストール", - "System Proxy": "システムプロキシ", - "System Proxy Info": "オペレーティングシステムのプロキシ設定を変更します。有効にできない場合は、手動でオペレーティングシステムのプロキシ設定を変更してください。", - "System Proxy Setting": "システムプロキシ設定", - "Current System Proxy": "現在のシステムプロキシ", - "Enable status": "有効状態:", - "Enabled": "有効", - "Disabled": "無効", - "Server Addr": "サーバーアドレス:", - "Proxy Host": "プロキシホスト", - "Invalid Proxy Host Format": "プロキシホストの形式が無効です", - "Not available": "利用不可", - "Proxy Guard": "システムプロキシガード", - "Proxy Guard Info": "他のソフトウェアがオペレーティングシステムのプロキシ設定を変更するのを防ぐために有効にします。", - "Guard Duration": "プロキシガード間隔", - "Always use Default Bypass": "常にデフォルトのバイパスを使用", - "Proxy Bypass": "プロキシバイパス設定:", - "Bypass": "現在のバイパス:", - "Use PAC Mode": "PACモードを使用", - "PAC Script Content": "PACスクリプト内容", - "PAC URL": "PACアドレス:", - "Auto Launch": "起動時に自動起動", - "Administrator mode may not support auto launch": "管理者モードでは起動時の自動起動がサポートされない場合があります。", - "Silent Start": "サイレント起動", - "Silent Start Info": "アプリケーションを起動すると、バックグラウンドモードで実行され、アプリケーションパネルは表示されません。", - "TG Channel": "Telegramチャンネル", - "Manual": "マニュアル", - "Github Repo": "GitHubリポジトリ", - "Clash Setting": "Clash設定", - "Allow Lan": "LAN接続を許可", - "Network Interface": "ネットワークインターフェース", - "Ip Address": "IPアドレス", - "Mac Address": "MACアドレス", - "IPv6": "IPv6", - "Unified Delay": "統一遅延", - "Unified Delay Info": "統一遅延を有効にすると、2回の遅延テストが行われ、接続ハンドシェイクなどによる異なるタイプのノードの遅延差を解消します。", - "Log Level": "ログレベル", - "Log Level Info": "ログディレクトリのServiceフォルダ内のコアログファイルにのみ適用されます。", - "Port Config": "ポート設定", - "Random Port": "ランダムポート", - "Mixed Port": "混合プロキシポート", - "Socks Port": "SOCKSプロキシポート", - "Http Port": "HTTP(S)プロキシポート", - "Redir Port": "Redir透明プロキシポート", - "Tproxy Port": "TPROXY透明プロキシポート", - "External": "外部制御", - "External Controller": "外部コントローラーの監視アドレス", - "Core Secret": "APIアクセスキー", - "Recommended": "推奨設定", - "Open URL": "URLを開く", - "Replace host, port, secret with %host, %port, %secret": "%host, %port, %secretを使用してホスト、ポート、アクセスキーを表します。", - "Support %host, %port, %secret": "%host, %port, %secretをサポートします。", - "Clash Core": "Clashコア", - "Upgrade": "コアをアップグレード", - "Restart": "コアを再起動", - "Release Version": "正式版", - "Alpha Version": "プレビュー版", - "Please enter your root password": "ルートパスワードを入力してください。", - "Open UWP tool": "UWPツールを開く", - "Open UWP tool Info": "Windows 8以降では、UWPアプリケーション(Microsoft Storeなど)がローカルホストのネットワークサービスに直接アクセスすることが制限されています。このツールを使用すると、この制限を回避できます。", - "Update GeoData": "GeoDataを更新", - "Verge Basic Setting": "Verge基本設定", - "Verge Advanced Setting": "Verge詳細設定", - "Language": "言語設定", - "Theme Mode": "テーマモード", - "theme.light": "ライト", - "theme.dark": "ダーク", - "theme.system": "システム", - "Tray Click Event": "トレイアイコンクリックイベント", - "Show Main Window": "メインウィンドウを表示", - "Show Tray Menu": "トレイメニューを表示", - "Copy Env Type": "環境変数タイプをコピー", - "Copy Success": "コピー成功", - "Start Page": "起動ページ", - "Startup Script": "起動スクリプト", - "Browse": "参照", - "Theme Setting": "テーマ設定", - "Primary Color": "主要色", - "Secondary Color": "次要色", - "Primary Text": "テキスト主要色", - "Secondary Text": "テキスト次要色", - "Info Color": "情報色", - "Warning Color": "警告色", - "Error Color": "エラー色", - "Success Color": "成功色", - "Font Family": "フォントファミリー", - "CSS Injection": "CSSインジェクション", - "Layout Setting": "レイアウト設定", - "Traffic Graph": "トラフィックグラフ", - "Memory Usage": "コアメモリ使用量", - "Memory Cleanup": "クリックしてメモリをクリーンアップ", - "Proxy Group Icon": "プロキシグループアイコン", - "Nav Icon": "ナビゲーションバーアイコン", - "Monochrome": "モノクロアイコン", - "Colorful": "カラーアイコン", - "Tray Icon": "トレイアイコン", - "Common Tray Icon": "通常のトレイアイコン", - "System Proxy Tray Icon": "システムプロキシトレイアイコン", - "Tun Tray Icon": "TUNモードトレイアイコン", - "Miscellaneous": "その他の設定", - "App Log Level": "アプリケーションログレベル", - "Auto Close Connections": "接続を自動的に閉じる", - "Auto Close Connections Info": "プロキシグループで選択されたノードまたはプロキシモードが変更されたときに、既存の接続を閉じます。", - "Auto Check Update": "自動更新チェック", - "Enable Builtin Enhanced": "組み込み拡張機能を有効にする", - "Enable Builtin Enhanced Info": "設定ファイルの互換性処理", - "Proxy Layout Columns": "プロキシページのレイアウト列数", - "Auto Columns": "自動列数", - "Auto Log Clean": "ログを自動的にクリーンアップ", - "Never Clean": "クリーンアップしない", - "Retain _n Days": "{{n}}日間保持", - "Auto Delay Detection": "自動遅延検出", - "Auto Delay Detection Info": "バックグラウンドで現在のノードのレイテンシーを定期的にテストします", - "Default Latency Test": "デフォルトの遅延テストURL", - "Default Latency Test Info": "HTTPクライアントリクエストテストにのみ使用され、設定ファイルには影響しません。", - "Default Latency Timeout": "テストタイムアウト時間", - "Hotkey Setting": "ホットキー設定", - "Enable Global Hotkey": "グローバルホットキーを有効にする", - "open_or_close_dashboard": "ダッシュボードを開く/閉じる", - "clash_mode_rule": "ルールモード", - "clash_mode_global": "グローバルモード", - "clash_mode_direct": "直接接続モード", - "toggle_system_proxy": "システムプロキシを開く/閉じる", - "toggle_tun_mode": "TUNモードを開く/閉じる", - "entry_lightweight_mode": "軽量モードに入る", - "Backup Setting": "バックアップ設定", - "Backup Setting Info": "WebDAVを使用した設定ファイルのバックアップをサポートします。", - "Runtime Config": "現在の設定", - "Open Conf Dir": "設定ディレクトリを開く", - "Open Conf Dir Info": "アプリケーションが正常に動作しない場合は、このフォルダ内のすべてのファイルを!バックアップ!して削除し、アプリケーションを再起動してください。", - "Open Core Dir": "コアディレクトリを開く", - "Open Logs Dir": "ログディレクトリを開く", - "Check for Updates": "更新を確認", - "Go to Release Page": "リリースページに移動", - "Portable Updater Error": "ポータブル版ではアプリケーション内での更新はサポートされていません。手動でダウンロードして置き換えてください。", - "Break Change Update Error": "このバージョンは重大な更新であり、アプリケーション内での更新はサポートされていません。アンインストールしてから手動でダウンロードしてインストールしてください。", - "Open Dev Tools": "開発者ツールを開く", - "Export Diagnostic Info": "診断情報をエクスポート", - "Exit": "終了", - "Verge Version": "Vergeバージョン", - "ReadOnly": "読み取り専用", - "ReadOnlyMessage": "読み取り専用モードでは編集できません。", - "Filter": "ノードをフィルタリング", - "Filter conditions": "フィルタリング条件", - "Match Case": "大文字小文字を区別する", - "Match Whole Word": "完全一致", - "Use Regular Expression": "正規表現を使用する", - "Profile Imported Successfully": "プロファイルのインポートに成功しました。", - "Profile Switched": "プロファイルが切り替えられました。", - "Profile Reactivated": "プロファイルが再アクティブ化されました。", - "Only YAML Files Supported": "YAMLファイルのみサポートされています。", - "Settings Applied": "設定が適用されました。", - "Stopping Core...": "コアを停止中...", - "Restarting Core...": "コアを再起動中...", - "Installing Service...": "サービスをインストール中...", - "Uninstalling Service...": "サービスをアンインストール中...", - "Service Installed Successfully": "サービスのインストールに成功しました。", - "Service Uninstalled Successfully": "サービスのアンインストールに成功しました。", - "Proxy Daemon Duration Cannot be Less than 1 Second": "プロキシデーモンの間隔は1秒以上に設定する必要があります。", - "Invalid Bypass Format": "無効なバイパス形式", - "Waiting for service to be ready...": "サービスの準備を待っています...", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "サービスは準備が整っていましたが、コアの再起動に問題が発生したか、サービスが利用できなくなった可能性があります。ご確認ください。", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "サービスのインストールまたはコアの再起動中に問題が発生しました。サービスが利用できない可能性があります。システムログを確認してください。", - "Service is ready and core restarted": "サービスが準備完了し、コアが再起動されました。", - "Core restarted. Service is now available.": "コアが再起動され、サービスが利用可能になりました。", - "Core Version Updated": "コアバージョンが更新されました。", - "Clash Core Restarted": "Clashコアが再起動されました。", - "GeoData Updated": "GeoDataが更新されました。", - "Currently on the Latest Version": "現在は最新バージョンです。", - "Import Subscription Successful": "サブスクリプションのインポートに成功しました。", - "WebDAV Server URL": "WebDAVサーバーのURL http(s)://", - "Username": "ユーザー名", - "Password": "パスワード", - "Backup": "バックアップ", - "Filename": "ファイル名", - "Actions": "操作", - "Restore": "復元", - "No Backups": "バックアップがありません。", - "WebDAV URL Required": "WebDAVサーバーのURLは必須です。", - "Invalid WebDAV URL": "無効なWebDAVサーバーのURL形式", - "Username Required": "ユーザー名は必須です。", - "Password Required": "パスワードは必須です。", - "WebDAV Config Saved": "WebDAV設定が保存されました。", - "WebDAV Config Save Failed": "WebDAV設定の保存に失敗しました: {{error}}", - "Backup Created": "バックアップが作成されました。", - "Backup Failed": "バックアップに失敗しました: {{error}}", - "Delete Backup": "バックアップを削除", - "Restore Backup": "バックアップを復元", - "Backup Time": "バックアップ時間", - "Restore Success, App will restart in 1s": "復元に成功しました。アプリケーションは1秒後に再起動します。", - "Failed to fetch backup files": "バックアップファイルの取得に失敗しました。", - "Profile": "プロファイル", - "Web UI": "Webインターフェース", - "Dashboard": "ダッシュボード", - "Restart App": "アプリケーションを再起動", - "Restart Clash Core": "Clashコアを再起動", - "TUN Mode": "TUNモード", - "Copy Env": "環境変数をコピー", - "Conf Dir": "設定ディレクトリ", - "Core Dir": "コアディレクトリ", - "Logs Dir": "ログディレクトリ", - "Open Dir": "ディレクトリを開く", - "More": "もっと見る", - "Rule Mode": "ルールモード", - "Global Mode": "グローバルモード", - "Direct Mode": "直接接続モード", - "Enable Tray Speed": "トレイの速度表示を有効にする", - "Enable Tray Icon": "トレイアイコンを有効にする", - "LightWeight Mode": "軽量モード", - "LightWeight Mode Info": "GUIを閉じて、コアのみを実行します。", - "LightWeight Mode Settings": "軽量モード設定", - "Enter LightWeight Mode Now": "今すぐ軽量モードに入る", - "Auto Enter LightWeight Mode": "自動的に軽量モードに入る", - "Auto Enter LightWeight Mode Info": "有効にすると、ウィンドウを閉じてから一定時間後に自動的に軽量モードが有効になります。", - "Auto Enter LightWeight Mode Delay": "自動的に軽量モードに入るまでの遅延時間", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "ウィンドウを閉じると、{{n}}分後に自動的に軽量モードが有効になります。", - "Config Validation Failed": "プロファイル設定の検証に失敗しました。プロファイル設定ファイルを確認してください。変更は取り消されました。エラー詳細:", - "Boot Config Validation Failed": "起動時のプロファイル設定の検証に失敗しました。デフォルト設定で起動しました。プロファイル設定ファイルを確認してください。エラー詳細:", - "Core Change Config Validation Failed": "コアを切り替える際の設定検証に失敗しました。デフォルト設定で起動しました。プロファイル設定ファイルを確認してください。エラー詳細:", - "Config Validation Process Terminated": "検証プロセスが中断されました。", - "Script Syntax Error": "スクリプトの構文エラーがあります。変更は取り消されました。", - "Script Missing Main": "スクリプトにメイン関数がありません。変更は取り消されました。", - "File Not Found": "ファイルが見つかりません。変更は取り消されました。", - "Script File Error": "スクリプトファイルにエラーがあります。変更は取り消されました。", - "Core Changed Successfully": "コアの切り替えに成功しました。", - "Failed to Change Core": "コアの切り替えに失敗しました。", - "YAML Syntax Error": "YAML構文エラーがあります。変更は取り消されました。", - "YAML Read Error": "YAMLファイルの読み取りエラーがあります。変更は取り消されました。", - "YAML Mapping Error": "YAMLマッピングエラーがあります。変更は取り消されました。", - "YAML Key Error": "YAMLキーエラーがあります。変更は取り消されました。", - "YAML Error": "YAMLエラーがあります。変更は取り消されました。", - "Merge File Syntax Error": "上書きファイルの構文エラーがあります。変更は取り消されました。", - "Merge File Mapping Error": "上書きファイルのマッピングエラーがあります。変更は取り消されました。", - "Merge File Key Error": "上書きファイルのキーエラーがあります。変更は取り消されました。", - "Merge File Error": "上書きファイルにエラーがあります。変更は取り消されました。", - "Service Administrator Prompt": "Clash Vergeはシステムサービスをインストールするために管理者権限が必要です。", - "DNS Settings": "DNS設定", - "DNS settings saved": "DNS設定が保存されました。", - "DNS Overwrite": "DNS上書き", - "DNS Settings Warning": "ここの設定がわからない場合は、変更しないでください。DNS上書きを有効にしたままにしてください。", - "Enable DNS": "DNSを有効にする", - "DNS Listen": "DNS監視アドレス", - "Enhanced Mode": "拡張モード", - "Fake IP Range": "Fake IP範囲", - "Fake IP Filter Mode": "Fake IPフィルターモード", - "Enable IPv6 DNS resolution": "IPv6 DNS解決を有効にする", - "Prefer H3": "HTTP/3を優先する", - "DNS DOH使用HTTP/3": "DNS DOHでHTTP/3プロトコルを使用する", - "Respect Rules": "ルートルールに従う", - "DNS connections follow routing rules": "DNS接続はルートルールに従います。", - "Use Hosts": "Hostsファイルを使用する", - "Enable to resolve hosts through hosts file": "Hostsファイルを使用してホスト名を解決する", - "Use System Hosts": "システムのHostsファイルを使用する", - "Enable to resolve hosts through system hosts file": "システムのHostsファイルを使用してホスト名を解決する", - "Direct Nameserver Follow Policy": "直接接続の名前解決サーバーはポリシーに従う", - "Whether to follow nameserver policy": "名前解決サーバーのポリシーに従うかどうか", - "Default Nameserver": "デフォルトの名前解決サーバー", - "Default DNS servers used to resolve DNS servers": "名前解決サーバーを解決するために使用されるデフォルトのDNSサーバー", - "Nameserver": "名前解決サーバー", - "List of DNS servers": "DNSサーバーのリスト。カンマで区切って指定します。", - "Fallback": "フォールバックサーバー", - "List of fallback DNS servers": "フォールバックDNSサーバーのリスト。カンマで区切って指定します。", - "Proxy Server Nameserver": "プロキシサーバーの名前解決サーバー", - "Proxy Node Nameserver": "プロキシノードの名前解決サーバー。プロキシノードのドメイン名を解決するためにのみ使用されます。カンマで区切って指定します。", - "Direct Nameserver": "直接接続の名前解決サーバー", - "Direct outbound Nameserver": "直接接続の出口名前解決サーバー。systemキーワードをサポートします。カンマで区切って指定します。", - "Fake IP Filter": "Fake IPフィルター", - "Domains that skip fake IP resolution": "Fake IP解決をスキップするドメイン名。カンマで区切って指定します。", - "Nameserver Policy": "名前解決サーバーのポリシー", - "Domain-specific DNS server": "特定のドメインのDNSサーバー。複数のサーバーはセミコロンで区切って指定します。形式: domain=server1;server2", - "Fallback Filter Settings": "フォールバックフィルター設定", - "GeoIP Filtering": "GeoIPフィルタリング", - "Enable GeoIP filtering for fallback": "フォールバックのGeoIPフィルタリングを有効にする", - "GeoIP Code": "GeoIP国コード", - "Fallback IP CIDR": "フォールバックIP CIDR", - "IP CIDRs not using fallback servers": "フォールバックサーバーを使用しないIP CIDR。カンマで区切って指定します。", - "Fallback Domain": "フォールバックドメイン", - "Domains using fallback servers": "フォールバックサーバーを使用するドメイン名。カンマで区切って指定します。", - "Hosts Settings": "Hosts設定", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "カスタムのドメイン名からIPまたはドメイン名へのマッピング。カンマで区切って指定します。", - "Home Settings": "ホーム設定", - "Profile Card": "プロファイルカード", - "Current Proxy Card": "現在のプロキシカード", - "Network Settings Card": "ネットワーク設定カード", - "Proxy Mode Card": "プロキシモードカード", - "Traffic Stats Card": "トラフィック統計カード", - "Clash Info Cards": "Clash情報カード", - "System Info Cards": "システム情報カード", - "Website Tests Card": "ウェブサイトテストカード", - "Traffic Stats": "トラフィック統計", - "Website Tests": "ウェブサイトテスト", - "Clash Info": "Clash情報", - "Core Version": "コアバージョン", - "System Proxy Address": "システムプロキシアドレス", - "Uptime": "稼働時間", - "Rules Count": "ルール数", - "System Info": "システム情報", - "OS Info": "オペレーティングシステム情報", - "Running Mode": "実行モード", - "Sidecar Mode": "ユーザーモード", - "Administrator Mode": "管理者モード", - "Last Check Update": "最後の更新チェック", - "Click to import subscription": "クリックしてサブスクリプションをインポート", - "Last Update failed": "前回の更新に失敗しました。", - "Next Up": "次回の更新", - "No schedule": "予定がありません。", - "Unknown": "不明", - "Auto update disabled": "自動更新が無効になっています。", - "Update subscription successfully": "サブスクリプションの更新に成功しました。", - "Update with Clash proxy successfully": "Clashプロキシを使用して更新に成功しました。", - "Update failed even with Clash proxy": "Clashプロキシを使用しても更新に失敗しました。", - "Profile creation failed, retrying with Clash proxy...": "プロファイルの作成に失敗しました。Clashプロキシを使用して再試行します...", - "Profile creation succeeded with Clash proxy": "Clashプロキシを使用してプロファイルの作成に成功しました。", - "Import failed, retrying with Clash proxy...": "インポートに失敗しました。Clashプロキシを使用して再試行します...", - "Profile Imported with Clash proxy": "Clashプロキシを使用してプロファイルのインポートに成功しました。", - "Import failed even with Clash proxy": "Clashプロキシを使用してもインポートに失敗しました。", - "Current Node": "現在のノード", - "No active proxy node": "アクティブなプロキシノードがありません。", - "Network Settings": "ネットワーク設定", - "Proxy Mode": "プロキシモード", - "Group": "プロキシグループ", - "Proxy": "ノード", - "IP Information Card": "IP情報カード", - "IP Information": "IP情報", - "Failed to get IP info": "IP情報の取得に失敗しました。", - "ISP": "インターネットサービスプロバイダー", - "ASN": "自治システム番号", - "ORG": "組織", - "Location": "位置", - "Timezone": "タイムゾーン", - "Auto refresh": "自動更新", - "Unlock Test": "ロック解除テスト", - "Pending": "検査待ち", - "Yes": "サポートする", - "No": "サポートしない", - "Failed": "テストに失敗しました。", - "Completed": "検査完了", - "Disallowed ISP": "許可されていないインターネットサービスプロバイダー", - "Originals Only": "オリジナルのみ", - "Unsupported Country/Region": "サポートされていない国/地域", - "Configuration saved successfully": "ランダム設定を保存完了", - "Controller address copied to clipboard": "API ポートがクリップボードにコピーされました", - "Secret copied to clipboard": "API キーがクリップボードにコピーされました", - "Batch Operations": "バッチ操作", - "Delete Selected Profiles": "選択したプロファイルを削除", - "Deselect All": "すべての選択を解除", - "Done": "完了", - "items": "アイテム", - "Select All": "すべて選択", - "Selected": "選択済み", - "Selected profiles deleted successfully": "選択したプロファイルが正常に削除されました", - "Copy to clipboard": "クリックしてコピー", - "Enable one-click random API port and key. Click to randomize the port and key": "ワンクリックでランダム API ポートとキーを有効化。ポートとキーをランダム化するにはクリックしてください" -} diff --git a/src/locales/jp/connections.json b/src/locales/jp/connections.json new file mode 100644 index 000000000..806f4bb13 --- /dev/null +++ b/src/locales/jp/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "接続" + }, + "components": { + "fields": { + "host": "ホスト", + "dlSpeed": "ダウンロード速度", + "ulSpeed": "アップロード速度", + "chains": "チェーン", + "rule": "ルール", + "process": "プロセス", + "time": "接続時間", + "source": "送信元アドレス", + "destination": "宛先アドレス", + "destinationPort": "宛先ポート", + "type": "タイプ" + }, + "order": { + "default": "Default", + "uploadSpeed": "アップロード速度", + "downloadSpeed": "ダウンロード速度" + }, + "actions": { + "closeConnection": "接続を閉じる" + } + } +} diff --git a/src/locales/jp/home.json b/src/locales/jp/home.json new file mode 100644 index 000000000..e8d224c20 --- /dev/null +++ b/src/locales/jp/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "軽量モード", + "manual": "マニュアル", + "settings": "ホーム設定" + }, + "cards": { + "trafficStats": "トラフィック統計", + "networkSettings": "ネットワーク設定", + "proxyMode": "プロキシモード" + }, + "settings": { + "cards": { + "profile": "プロファイルカード", + "currentProxy": "現在のプロキシカード", + "network": "ネットワーク設定カード", + "proxyMode": "プロキシモードカード", + "traffic": "トラフィック統計カード", + "tests": "ウェブサイトテストカード", + "ip": "IP情報カード", + "clashInfo": "Clash情報カード", + "systemInfo": "システム情報カード" + }, + "title": "ホーム設定" + }, + "title": "ホーム" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "システムプロキシが有効になっています。アプリケーションはプロキシを通じてネットワークにアクセスします。", + "systemProxyDisabled": "システムプロキシが無効になっています。ほとんどのユーザーはこのオプションをオンにすることをお勧めします。", + "tunModeServiceRequired": "TUNモードはサービスモードが必要です。まずサービスをインストールしてください。", + "tunModeEnabled": "TUNモードが有効になっています。アプリケーションは仮想ネットワークカードを通じてネットワークにアクセスします。", + "tunModeDisabled": "TUNモードが無効になっています。特殊なアプリケーションに適しています。" + }, + "tooltips": { + "systemProxy": "オペレーティングシステムのプロキシ設定を変更します。有効にできない場合は、手動でオペレーティングシステムのプロキシ設定を変更してください。", + "tunMode": "TUNモードは全てのアプリケーションのトラフィックを制御できます。システムプロキシ設定に従わない特殊なアプリケーションに適しています。" + } + }, + "clashInfo": { + "title": "Clash情報", + "fields": { + "coreVersion": "コアバージョン", + "systemProxyAddress": "システムプロキシアドレス", + "mixedPort": "Mixed Port", + "uptime": "稼働時間", + "rulesCount": "ルール数" + } + }, + "systemInfo": { + "title": "システム情報", + "fields": { + "osInfo": "オペレーティングシステム情報", + "autoLaunch": "起動時に自動起動", + "runningMode": "実行モード", + "lastCheckUpdate": "最後の更新チェック", + "vergeVersion": "Vergeバージョン" + }, + "actions": { + "settings": "設定" + }, + "tooltips": { + "autoLaunchAdmin": "管理者モードでは起動時の自動起動がサポートされない場合があります。" + }, + "badges": { + "adminMode": "管理者モード", + "serviceMode": "サービスモード", + "sidecarMode": "ユーザーモード", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP情報", + "labels": { + "ip": "IP", + "asn": "自治システム番号", + "isp": "インターネットサービスプロバイダー", + "org": "組織", + "location": "位置", + "timezone": "タイムゾーン", + "autoRefresh": "自動更新", + "unknown": "不明" + }, + "errors": { + "load": "IP情報の取得に失敗しました" + } + }, + "currentProxy": { + "title": "現在のノード", + "actions": { + "refreshDelay": "遅延テスト" + }, + "labels": { + "globalMode": "グローバルモード", + "directMode": "直接接続モード", + "group": "プロキシグループ", + "proxy": "ノード", + "noActiveNode": "アクティブなプロキシノードがありません。" + } + }, + "tests": { + "title": "ウェブサイトテスト" + }, + "traffic": { + "metrics": { + "uploadSpeed": "アップロード速度", + "downloadSpeed": "ダウンロード速度", + "activeConnections": "アクティブな接続", + "memoryUsage": "コアメモリ使用量" + }, + "legends": { + "upload": "アップロード", + "download": "ダウンロード" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "ルールモード", + "global": "グローバルモード", + "direct": "直接接続モード" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/jp/index.ts b/src/locales/jp/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/jp/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/jp/layout.json b/src/locales/jp/layout.json new file mode 100644 index 000000000..8e8a87981 --- /dev/null +++ b/src/locales/jp/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "ホーム", + "proxies": "プロキシ", + "profiles": "プロファイル", + "connections": "接続", + "rules": "ルール", + "logs": "ログ", + "unlock": "テスト", + "settings": "設定" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/jp/logs.json b/src/locales/jp/logs.json new file mode 100644 index 000000000..3ae97f236 --- /dev/null +++ b/src/locales/jp/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "ログ" + } +} diff --git a/src/locales/jp/profiles.json b/src/locales/jp/profiles.json new file mode 100644 index 000000000..6d34770bd --- /dev/null +++ b/src/locales/jp/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "すべてのプロファイルを更新", + "viewRuntimeConfig": "実行時のプロファイルを表示", + "reactivate": "プロファイルを再アクティブ化", + "import": "インポート" + }, + "batch": { + "actions": { + "delete": "選択したプロファイルを削除", + "selectAll": "すべて選択", + "deselectAll": "すべての選択を解除", + "done": "完了" + }, + "summary": { + "selected": "選択済み", + "items": "アイテム" + }, + "title": "バッチ操作" + }, + "importForm": { + "placeholder": "プロファイルファイルのURL", + "actions": { + "paste": "貼り付け" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "YAMLファイルのみサポートされています。" + }, + "notifications": { + "importRetry": "インポートに失敗しました。Clashプロキシを使用して再試行します...", + "importFail": "Clashプロキシを使用してもインポートに失敗しました。", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "プロファイルが切り替えられました。", + "profileReactivated": "プロファイルが再アクティブ化されました。", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "選択したプロファイルが正常に削除されました" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "プロファイル" + }, + "components": { + "card": { + "labels": { + "clickToImport": "クリックしてサブスクリプションをインポート" + } + }, + "fileInput": { + "chooseFile": "ファイルを選択" + }, + "menu": { + "home": "ホーム", + "select": "使用する", + "editInfo": "情報を編集", + "editFile": "ファイルを編集", + "editRules": "ルールを編集", + "editProxies": "ノードを編集", + "editGroups": "プロキシグループを編集", + "extendConfig": "拡張上書き設定", + "extendScript": "拡張スクリプト", + "openFile": "ファイルを開く", + "update": "更新", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "前回の更新に失敗しました。", + "nextUp": "次回の更新", + "noSchedule": "予定がありません。", + "unknown": "不明", + "autoUpdateDisabled": "自動更新が無効になっています。" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "新規プロファイルを作成", + "edit": "プロファイルを編集" + }, + "fields": { + "type": "タイプ", + "description": "説明", + "subscriptionUrl": "サブスクリプションURL", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "更新間隔", + "useSystemProxy": "システムプロキシを使用して更新", + "useClashProxy": "クラッシュプロキシを使用して更新", + "acceptInvalidCerts": "Allows Invalid Certificates (Danger)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "プロファイルの作成に失敗しました。Clashプロキシを使用して再試行します...", + "creationSuccess": "Clashプロキシを使用してプロファイルの作成に成功しました。" + } + } + }, + "proxiesEditor": { + "title": "ノードを編集", + "placeholders": { + "multiUri": "複数のURIは改行で区切ってください(Base64エンコードに対応)" + }, + "actions": { + "prepend": "前置プロキシノードを追加", + "append": "後置プロキシノードを追加" + } + }, + "groupsEditor": { + "title": "プロキシグループを編集", + "errors": { + "nameRequired": "プロキシグループ名は必須です", + "nameExists": "プロキシグループ名はすでに存在します" + }, + "fields": { + "type": "プロキシグループタイプ", + "name": "プロキシグループ名", + "icon": "プロキシグループアイコン", + "proxies": "プロキシを導入", + "provider": "プロキシプロバイダーを導入", + "healthCheckUrl": "ヘルスチェックURL", + "expectedStatus": "期待するステータスコード", + "interval": "チェック間隔", + "maxFailedTimes": "最大失敗回数", + "interfaceName": "出力インターフェース", + "routingMark": "ルーティングマーク", + "filter": "ノードをフィルタリング", + "excludeFilter": "除外ノード", + "excludeType": "除外ノードタイプ", + "includeAll": "すべての出力プロキシ、プロキシプロバイダーを導入", + "includeAllProxies": "すべての出力プロキシを導入", + "includeAllProviders": "すべてのプロキシプロバイダーを導入" + }, + "toggles": { + "lazy": "遅延モード", + "disableUdp": "UDPを無効にする", + "hidden": "プロキシグループを隠す" + }, + "actions": { + "prepend": "前置プロキシグループを追加", + "append": "後置プロキシグループを追加" + } + }, + "editor": { + "actions": { + "format": "文書を整形する" + }, + "messages": { + "readOnly": "読み取り専用モードでは編集できません。" + } + }, + "confirmDelete": { + "title": "削除を確認", + "message": "この操作は元に戻せません" + }, + "logViewer": { + "title": "スクリプトコンソール出力" + } + } +} diff --git a/src/locales/jp/proxies.json b/src/locales/jp/proxies.json new file mode 100644 index 000000000..7667b6943 --- /dev/null +++ b/src/locales/jp/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 チェーンプロキシ", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "プロキシプロバイダー", + "actions": { + "updateAll": "すべて更新", + "update": "更新" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "ノード数", + "delayCheckReset": "遅延テストを実行して固定を解除する" + }, + "tooltips": { + "locate": "現在のノード", + "delayCheck": "遅延テスト", + "sortDefault": "デフォルトでソート", + "sortDelay": "遅延でソート", + "sortName": "名前でソート", + "delayCheckUrl": "遅延テストURL", + "showBasic": "ノードの詳細を隠す", + "showDetail": "ノードの詳細を表示する", + "filter": "ノードをフィルタリング" + }, + "placeholders": { + "delayCheckUrl": "遅延テストURL" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "直接接続モード" + }, + "title": { + "default": "プロキシグループ", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "手動でプロキシを選択", + "url-test": "URLテストによる遅延でプロキシを選択", + "fallback": "利用不可の場合は別のプロキシに切り替える", + "load-balance": "負荷分散によりプロキシを割り当てる", + "relay": "定義されたプロキシチェーンに沿って転送する" + }, + "policies": { + "DIRECT": "直接接続", + "REJECT": "リクエストを拒否", + "REJECT-DROP": "リクエストを破棄", + "PASS": "このルールをスキップ" + } + } + } +} diff --git a/src/locales/jp/rules.json b/src/locales/jp/rules.json new file mode 100644 index 000000000..26411f1bf --- /dev/null +++ b/src/locales/jp/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "ルールプロバイダー", + "dialogTitle": "ルールプロバイダー", + "actions": { + "updateAll": "すべて更新", + "update": "更新" + } + }, + "title": "ルール" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "ルールタイプ", + "content": "ルール内容", + "proxyPolicy": "プロキシポリシー" + }, + "toggles": { + "noResolve": "DNS解決をスキップ" + }, + "actions": { + "prependRule": "前置ルールを追加", + "appendRule": "後置ルールを追加" + }, + "validation": { + "conditionRequired": "ルール条件が必要です", + "invalidRule": "無効なルール" + } + }, + "ruleTypes": { + "DOMAIN": "完全なドメイン名を一致させる", + "DOMAIN-SUFFIX": "ドメインサフィックスを一致させる", + "DOMAIN-KEYWORD": "ドメインキーワードを一致させる", + "DOMAIN-REGEX": "ドメイン正規表現を一致させる", + "GEOSITE": "Geosite内のドメインを一致させる", + "GEOIP": "IPの所属国コードを一致させる", + "SRC-GEOIP": "送信元IPの所属国コードを一致させる", + "IP-ASN": "IPの所属ASNを一致させる", + "SRC-IP-ASN": "送信元IPの所属ASNを一致させる", + "IP-CIDR": "IPアドレス範囲を一致させる", + "IP-CIDR6": "IPアドレス範囲を一致させる", + "SRC-IP-CIDR": "送信元IPアドレス範囲を一致させる", + "IP-SUFFIX": "IPサフィックス範囲を一致させる", + "SRC-IP-SUFFIX": "送信元IPサフィックス範囲を一致させる", + "SRC-PORT": "送信元ポート範囲を一致させる", + "DST-PORT": "宛先ポート範囲を一致させる", + "IN-PORT": "入力ポートを一致させる", + "DSCP": "DSCPマーク(TPROXY UDP入力のみ)", + "PROCESS-NAME": "プロセス名を一致させる(Androidパッケージ名)", + "PROCESS-PATH": "完全なプロセスパスを一致させる", + "PROCESS-NAME-REGEX": "完全なプロセス名を正規表現で一致させる(Androidパッケージ名)", + "PROCESS-PATH-REGEX": "完全なプロセスパスを正規表現で一致させる", + "NETWORK": "トランスポートプロトコルを一致させる (TCP/UDP)", + "UID": "LinuxユーザーIDを一致させる", + "IN-TYPE": "入力タイプを一致させる", + "IN-USER": "入力ユーザー名を一致させる", + "IN-NAME": "入力名を一致させる", + "SUB-RULE": "サブルール", + "RULE-SET": "ルールセットを一致させる", + "AND": "論理積", + "OR": "論理和", + "NOT": "論理否定", + "MATCH": "すべてのリクエストを一致させる" + }, + "title": "ルールを編集" + } + } +} diff --git a/src/locales/jp/settings.json b/src/locales/jp/settings.json new file mode 100644 index 000000000..51635416e --- /dev/null +++ b/src/locales/jp/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "マニュアル", + "telegram": "Telegramチャンネル", + "github": "GitHubリポジトリ" + }, + "title": "設定" + }, + "sections": { + "system": { + "title": "システム設定", + "toggles": { + "tunMode": "仮想ネットワークカードモード", + "systemProxy": "システムプロキシ" + }, + "tooltips": { + "autoLaunchAdmin": "管理者モードでは起動時の自動起動がサポートされない場合があります。", + "silentStart": "アプリケーションを起動すると、バックグラウンドモードで実行され、アプリケーションパネルは表示されません。" + }, + "fields": { + "autoLaunch": "自動起動", + "silentStart": "サイレント起動" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "オペレーティングシステムのプロキシ設定を変更します。有効にできない場合は、手動でオペレーティングシステムのプロキシ設定を変更してください。", + "tunMode": "TUN(仮想ネットワークカード)モードはシステムのすべてのトラフィックを制御します。有効にすると、システムプロキシを開く必要はありません。", + "tunUnavailable": "TUNモードはサービスモードまたは管理者モードが必要です" + }, + "actions": { + "installService": "サービスをインストール", + "uninstallService": "サービスのアンインストール" + }, + "fields": { + "systemProxy": "システムプロキシ", + "tunMode": "仮想ネットワークカードモード" + } + }, + "externalController": { + "title": "外部コントローラーの監視アドレス", + "fields": { + "enable": "外部コントローラーを有効化", + "address": "外部コントローラーの監視アドレス", + "secret": "APIアクセスキー" + }, + "placeholders": { + "address": "必須", + "secret": "推奨設定" + }, + "tooltips": { + "copy": "クリップボードにコピー" + }, + "messages": { + "addressRequired": "コントローラーのアドレスは空にできません", + "secretRequired": "シークレットを空にすることはできません", + "copyFailed": "コピーに失敗しました", + "controllerCopied": "API ポートがクリップボードにコピーされました", + "secretCopied": "API キーがクリップボードにコピーされました" + } + }, + "externalCors": { + "title": "外部 CORS 設定", + "fields": { + "allowPrivateNetwork": "プライベートネットワークへのアクセスを許可", + "allowedOrigins": "許可されたオリジン" + }, + "placeholders": { + "origin": "有効なURLを入力してください" + }, + "actions": { + "add": "追加" + }, + "messages": { + "alwaysIncluded": "常に含まれるオリジン: {{urls}}" + }, + "tooltips": { + "open": "外部 CORS 設定" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Clash設定", + "form": { + "fields": { + "allowLan": "LAN接続を許可", + "dnsOverwrite": "DNS上書き", + "ipv6": "IPv6", + "unifiedDelay": "統一遅延", + "logLevel": "ログレベル", + "portConfig": "ポート設定", + "external": "外部制御", + "webUI": "Webインターフェース", + "clashCore": "Clashコア", + "openUwpTool": "UWPツールを開く", + "updateGeoData": "GeoDataを更新" + }, + "tooltips": { + "networkInterface": "ネットワークインターフェース", + "unifiedDelay": "統一遅延を有効にすると、2回の遅延テストが行われ、接続ハンドシェイクなどによる異なるタイプのノードの遅延差を解消します。", + "logLevel": "ログディレクトリのServiceフォルダ内のコアログファイルにのみ適用されます。", + "openUwpTool": "Windows 8以降では、UWPアプリケーション(Microsoft Storeなど)がローカルホストのネットワークサービスに直接アクセスすることが制限されています。このツールを使用すると、この制限を回避できます。" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge基本設定", + "actions": { + "browse": "参照" + }, + "trayOptions": { + "showMainWindow": "メインウィンドウを表示", + "showTrayMenu": "トレイメニューを表示", + "disable": "無効にする" + }, + "fields": { + "language": "言語設定", + "themeMode": "テーマモード", + "trayClickEvent": "トレイアイコンクリックイベント", + "copyEnvType": "環境変数タイプをコピー", + "startPage": "起動ページ", + "startupScript": "起動スクリプト", + "themeSetting": "テーマ設定", + "layoutSetting": "レイアウト設定", + "misc": "その他の設定", + "hotkeySetting": "ホットキー設定" + } + }, + "advanced": { + "title": "Verge詳細設定", + "tooltips": { + "backupInfo": "WebDAVを使用した設定ファイルのバックアップをサポートします。", + "openConfDir": "アプリケーションが正常に動作しない場合は、このフォルダ内のすべてのファイルを!バックアップ!して削除し、アプリケーションを再起動してください。", + "liteMode": "GUIを閉じて、コアのみを実行します。" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "現在は最新バージョンです。", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "バックアップ設定", + "runtimeConfig": "現在の設定", + "openConfDir": "設定ディレクトリを開く", + "openCoreDir": "コアディレクトリを開く", + "openLogsDir": "ログディレクトリを開く", + "checkUpdates": "更新を確認", + "openDevTools": "開発者ツールを開く", + "liteModeSettings": "軽量モード設定", + "exit": "終了", + "exportDiagnostics": "診断情報をエクスポート", + "vergeVersion": "Vergeバージョン" + } + }, + "theme": { + "title": "テーマ設定", + "fields": { + "primaryColor": "主要色", + "secondaryColor": "次要色", + "primaryText": "テキスト主要色", + "secondaryText": "テキスト次要色", + "infoColor": "情報色", + "warningColor": "警告色", + "errorColor": "エラー色", + "successColor": "成功色", + "fontFamily": "フォントファミリー", + "cssInjection": "CSSインジェクション" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "レイアウト設定", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "トラフィックグラフ", + "memoryUsage": "コアメモリ使用量", + "proxyGroupIcon": "プロキシグループアイコン", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "ナビゲーションバーアイコン", + "trayIcon": "トレイアイコン", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "通常のトレイアイコン", + "systemProxyTrayIcon": "システムプロキシトレイアイコン", + "tunTrayIcon": "TUNモードトレイアイコン", + "enableTrayIcon": "トレイアイコンを有効にする", + "enableTraySpeed": "トレイの速度表示を有効にする" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "モノクロアイコン", + "colorful": "カラーアイコン", + "disable": "無効にする" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "ポート設定", + "fields": { + "mixed": "混合プロキシポート", + "socks": "SOCKSプロキシポート", + "http": "HTTP(S)プロキシポート", + "redir": "Redir透明プロキシポート", + "tproxy": "TPROXY透明プロキシポート" + }, + "actions": { + "random": "ランダムポート" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "正式版", + "alpha": "アルファ版" + } + }, + "liteMode": { + "title": "軽量モード設定", + "actions": { + "enterNow": "今すぐ軽量モードに入る" + }, + "toggles": { + "autoEnter": "自動的に軽量モードに入る" + }, + "tooltips": { + "autoEnter": "有効にすると、ウィンドウを閉じてから一定時間後に自動的に軽量モードが有効になります。" + }, + "fields": { + "delay": "自動的に軽量モードに入るまでの遅延時間" + }, + "messages": { + "autoEnterHint": "ウィンドウを閉じると、{{n}}分後に自動的に軽量モードが有効になります。" + } + }, + "backup": { + "title": "バックアップ設定", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "バックアップ", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "バックアップを削除", + "restore": "復元", + "restoreBackup": "バックアップを復元" + }, + "fields": { + "webdavUrl": "WebDAVサーバーのURL http(s)://", + "username": "ユーザー名", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "WebDAVサーバーのURLは必須です。", + "invalidWebdavUrl": "無効なWebDAVサーバーのURL形式", + "usernameRequired": "ユーザー名は必須です。", + "passwordRequired": "パスワードは必須です。", + "webdavConfigSaved": "WebDAV設定が保存されました。", + "webdavConfigSaveFailed": "WebDAV設定の保存に失敗しました: {{error}}", + "backupCreated": "バックアップが作成されました。", + "backupFailed": "バックアップに失敗しました: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "復元に成功しました。アプリケーションは1秒後に再起動します。", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Confirm to delete this backup file?", + "confirmRestore": "Confirm to restore this backup file?" + }, + "table": { + "filename": "ファイル名", + "backupTime": "バックアップ時間", + "actions": "操作", + "noBackups": "バックアップがありません。", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "その他の設定", + "fields": { + "appLogLevel": "アプリケーションログレベル", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "接続を自動的に閉じる", + "autoCheckUpdate": "自動更新チェック", + "enableBuiltinEnhanced": "組み込み拡張機能を有効にする", + "proxyLayoutColumns": "プロキシページのレイアウト列数", + "autoLogClean": "ログを自動的にクリーンアップ", + "autoDelayDetection": "自動遅延検出", + "defaultLatencyTest": "デフォルトの遅延テストURL", + "defaultLatencyTimeout": "テストタイムアウト時間" + }, + "tooltips": { + "autoCloseConnections": "プロキシグループで選択されたノードまたはプロキシモードが変更されたときに、既存の接続を閉じます。", + "enableBuiltinEnhanced": "設定ファイルの互換性処理", + "autoDelayDetection": "バックグラウンドで現在のノードのレイテンシーを定期的にテストします", + "defaultLatencyTest": "HTTPクライアントリクエストテストにのみ使用され、設定ファイルには影響しません。" + }, + "options": { + "proxyLayoutColumns": { + "auto": "自動列数" + }, + "autoLogClean": { + "never": "クリーンアップしない", + "retainDays": "{{n}}日間保持" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "リリースページに移動", + "update": "更新" + }, + "messages": { + "portableError": "ポータブル版ではアプリケーション内での更新はサポートされていません。手動でダウンロードして置き換えてください。", + "breakChangeError": "このバージョンは重大な更新であり、アプリケーション内での更新はサポートされていません。アンインストールしてから手動でダウンロードしてインストールしてください。" + } + }, + "sysproxy": { + "title": "システムプロキシ設定", + "fieldsets": { + "currentStatus": "現在のシステムプロキシ" + }, + "fields": { + "enableStatus": "有効状態:", + "serverAddr": "サーバーアドレス:", + "pacUrl": "PACアドレス:", + "proxyHost": "プロキシホスト", + "usePacMode": "PACモードを使用", + "proxyGuard": "システムプロキシガード", + "guardDuration": "プロキシガード間隔", + "alwaysUseDefaultBypass": "常にデフォルトのバイパスを使用", + "proxyBypass": "プロキシバイパス設定:", + "bypass": "現在のバイパス:", + "pacScriptContent": "PACスクリプト内容" + }, + "tooltips": { + "proxyGuard": "他のソフトウェアがオペレーティングシステムのプロキシ設定を変更するのを防ぐために有効にします。" + }, + "messages": { + "durationTooShort": "プロキシデーモンの間隔は1秒以上に設定する必要があります。", + "invalidBypass": "無効なバイパス形式", + "invalidProxyHost": "プロキシホストの形式が無効です" + }, + "actions": { + "editPac": "編集 PAC" + } + }, + "tun": { + "title": "仮想ネットワークカードモード", + "fields": { + "stack": "TUNモードスタック", + "device": "Device Name", + "autoRoute": "グローバルルートを自動設定", + "strictRoute": "厳格なルート", + "autoDetectInterface": "トラフィックの出口インターフェースを自動選択", + "dnsHijack": "DNSハイジャック", + "mtu": "最大転送単位" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "設定が適用されました。" + } + }, + "dns": { + "dialog": { + "title": "DNS上書き", + "warning": "ここの設定がわからない場合は、変更しないでください。DNS上書きを有効にしたままにしてください。" + }, + "sections": { + "general": "DNS設定", + "fallbackFilter": "フォールバックフィルター設定", + "hosts": "Hosts設定" + }, + "fields": { + "enable": "DNSを有効にする", + "listen": "DNS監視アドレス", + "enhancedMode": "拡張モード", + "fakeIpRange": "Fake IP範囲", + "fakeIpFilterMode": "Fake IPフィルターモード", + "ipv6": { + "label": "IPv6", + "description": "IPv6 DNS解決を有効にする" + }, + "preferH3": { + "label": "HTTP/3を優先する", + "description": "DNS DOHでHTTP/3プロトコルを使用する" + }, + "respectRules": { + "label": "ルートルールに従う", + "description": "DNS接続はルートルールに従います。" + }, + "useHosts": { + "label": "Hostsファイルを使用する", + "description": "Hostsファイルを使用してホスト名を解決する" + }, + "useSystemHosts": { + "label": "システムのHostsファイルを使用する", + "description": "システムのHostsファイルを使用してホスト名を解決する" + }, + "directPolicy": { + "label": "直接接続の名前解決サーバーはポリシーに従う", + "description": "名前解決サーバーのポリシーに従うかどうか" + }, + "defaultNameserver": { + "label": "デフォルトの名前解決サーバー", + "description": "名前解決サーバーを解決するために使用されるデフォルトのDNSサーバー" + }, + "nameserver": { + "label": "名前解決サーバー", + "description": "DNSサーバーのリスト。カンマで区切って指定します。" + }, + "fallback": { + "label": "フォールバックサーバー", + "description": "フォールバックDNSサーバーのリスト。カンマで区切って指定します。" + }, + "proxy": { + "label": "プロキシサーバーの名前解決サーバー", + "description": "プロキシノードの名前解決サーバー。プロキシノードのドメイン名を解決するためにのみ使用されます。カンマで区切って指定します。" + }, + "directNameserver": { + "label": "直接接続の名前解決サーバー", + "description": "直接接続の出口名前解決サーバー。systemキーワードをサポートします。カンマで区切って指定します。" + }, + "fakeIpFilter": { + "label": "Fake IPフィルター", + "description": "Fake IP解決をスキップするドメイン名。カンマで区切って指定します。" + }, + "nameserverPolicy": { + "label": "名前解決サーバーのポリシー", + "description": "特定のドメインのDNSサーバー。複数のサーバーはセミコロンで区切って指定します。形式: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIPフィルタリング", + "description": "フォールバックのGeoIPフィルタリングを有効にする" + }, + "geoipCode": "GeoIP国コード", + "fallbackIpCidr": { + "label": "フォールバックIP CIDR", + "description": "フォールバックサーバーを使用しないIP CIDR。カンマで区切って指定します。" + }, + "fallbackDomain": { + "label": "フォールバックドメイン", + "description": "フォールバックサーバーを使用するドメイン名。カンマで区切って指定します。" + }, + "hosts": { + "label": "Hosts", + "description": "カスタムのドメイン名からIPまたはドメイン名へのマッピング。カンマで区切って指定します。" + } + }, + "messages": { + "saved": "DNS設定が保存されました。", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "URLを開く" + }, + "title": "Webインターフェース", + "messages": { + "supportedPlaceholders": "%host, %port, %secretをサポートします。", + "placeholderInstruction": "%host, %port, %secretを使用してホスト、ポート、アクセスキーを表します。" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "グローバルホットキーを有効にする" + }, + "title": "ホットキー設定", + "functions": { + "rule": "ルールモード", + "global": "グローバルモード", + "openOrCloseDashboard": "ダッシュボードを開く/閉じる", + "toggleSystemProxy": "システムプロキシを開く/閉じる", + "toggleTunMode": "TUNモードを開く/閉じる", + "entryLightweightMode": "軽量モードに入る", + "direct": "直接接続モード" + } + }, + "password": { + "prompts": { + "enterRoot": "ルートパスワードを入力してください。" + } + }, + "networkInterface": { + "title": "ネットワークインターフェース", + "fields": { + "ipAddress": "IPアドレス", + "macAddress": "MACアドレス" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clashコアが再起動されました。", + "versionUpdated": "コアバージョンが更新されました。", + "alreadyLatestVersion": "すでに最新のコアバージョンを使用しています。", + "changeSuccess": "コアの切り替えに成功しました。", + "changeFailed": "コアの切り替えに失敗しました。", + "geoDataUpdated": "GeoDataが更新されました。" + }, + "clashService": { + "installSuccess": "サービスのインストールに成功しました。", + "uninstallSuccess": "サービスのアンインストールに成功しました。" + }, + "updater": { + "withClashProxySuccess": "Clashプロキシを使用して更新に成功しました。", + "withClashProxyFailed": "Clashプロキシを使用しても更新に失敗しました。" + } + } + }, + "statuses": { + "clash": { + "stopping": "コアを停止中...", + "restarting": "コアを再起動中..." + }, + "clashService": { + "installing": "サービスをインストール中...", + "uninstalling": "サービスをアンインストール中..." + } + } +} diff --git a/src/locales/jp/shared.json b/src/locales/jp/shared.json new file mode 100644 index 000000000..ac83ba54d --- /dev/null +++ b/src/locales/jp/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "キャンセル", + "close": "閉じる", + "confirm": "確認", + "save": "保存", + "delete": "削除", + "edit": "編集", + "new": "新規作成", + "enable": "有効にする", + "upgrade": "コアをアップグレード", + "restart": "コアを再起動", + "resetToDefault": "デフォルト値にリセット", + "refresh": "更新", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "リストビュー", + "tableView": "テーブルビュー", + "pause": "一時停止", + "resume": "再開", + "closeAll": "すべて閉じる", + "clear": "クリア" + }, + "labels": { + "updateAt": "更新日時", + "timeout": "Timeout", + "icon": "アイコン", + "name": "名前", + "readOnly": "読み取り専用", + "expireTime": "有効期限", + "updateTime": "更新時間", + "usedTotal": "使用済み / 合計", + "from": "から", + "password": "パスワード", + "retryAttempts": "Retry attempts", + "downloaded": "ダウンロード量", + "uploaded": "アップロード量" + }, + "statuses": { + "enabled": "有効", + "disabled": "無効", + "saving": "Saving...", + "empty": "空っぽ" + }, + "units": { + "milliseconds": "ミリ秒", + "seconds": "秒", + "minutes": "分", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "フィルタリング条件", + "matchCase": "大文字小文字を区別する", + "matchWholeWord": "完全一致", + "useRegex": "正規表現を使用する" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "最大化", + "minimize": "最小化" + }, + "editorModes": { + "visualization": "可視化", + "advanced": "詳細設定" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "プロファイルのインポートに成功しました。", + "importSubscriptionSuccess": "サブスクリプションのインポートに成功しました。", + "importWithClashProxy": "Clashプロキシを使用してプロファイルのインポートに成功しました。", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "コピー成功", + "saveSuccess": "ランダム設定を保存完了", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "プロファイル設定の検証に失敗しました。プロファイル設定ファイルを確認してください。変更は取り消されました。エラー詳細:", + "bootFailed": "起動時のプロファイル設定の検証に失敗しました。デフォルト設定で起動しました。プロファイル設定ファイルを確認してください。エラー詳細:", + "coreChangeFailed": "コアを切り替える際の設定検証に失敗しました。デフォルト設定で起動しました。プロファイル設定ファイルを確認してください。エラー詳細:", + "processTerminated": "検証プロセスが中断されました。" + }, + "script": { + "syntaxError": "スクリプトの構文エラーがあります。変更は取り消されました。", + "missingMain": "スクリプトにメイン関数がありません。変更は取り消されました。", + "fileNotFound": "ファイルが見つかりません。変更は取り消されました。", + "fileError": "スクリプトファイルにエラーがあります。変更は取り消されました。" + }, + "yaml": { + "syntaxError": "YAML構文エラーがあります。変更は取り消されました。", + "readError": "YAMLファイルの読み取りエラーがあります。変更は取り消されました。", + "mappingError": "YAMLマッピングエラーがあります。変更は取り消されました。", + "keyError": "YAMLキーエラーがあります。変更は取り消されました。", + "generalError": "YAMLエラーがあります。変更は取り消されました。" + }, + "merge": { + "syntaxError": "上書きファイルの構文エラーがあります。変更は取り消されました。", + "mappingError": "上書きファイルのマッピングエラーがあります。変更は取り消されました。", + "keyError": "上書きファイルのキーエラーがあります。変更は取り消されました。", + "generalError": "上書きファイルにエラーがあります。変更は取り消されました。" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/jp/tests.json b/src/locales/jp/tests.json new file mode 100644 index 000000000..0640382d6 --- /dev/null +++ b/src/locales/jp/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "すべてテスト" + }, + "title": "テスト" + }, + "components": { + "item": { + "actions": { + "test": "テスト" + } + } + }, + "modals": { + "test": { + "title": { + "create": "新規テストを作成", + "edit": "テストを編集" + }, + "fields": { + "url": "テストURL" + } + } + }, + "statuses": { + "test": { + "pending": "検査待ち", + "yes": "サポートする", + "no": "サポートしない", + "failed": "テストに失敗しました。", + "completed": "検査完了", + "disallowedIsp": "許可されていないインターネットサービスプロバイダー", + "originalsOnly": "オリジナルのみ", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "サポートされていない国/地域", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "テスト中..." + }, + "empty": "アンロックテスト項目はありません", + "messages": { + "detectionFailedWithName": "{{name}} の検出に失敗しました", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "ロック解除テスト" + } + } +} diff --git a/src/locales/ko.json b/src/locales/ko.json deleted file mode 100644 index b5b295714..000000000 --- a/src/locales/ko.json +++ /dev/null @@ -1,403 +0,0 @@ -{ - "millis": "밀리초", - "seconds": "초", - "mins": "분", - "Back": "뒤로", - "Close": "닫기", - "Cancel": "취소", - "Confirm": "확인", - "Maximize": "최대화", - "Minimize": "최소화", - "Format document": "문서 포맷", - "Empty": "비어있음", - "New": "새로 만들기", - "Edit": "편집", - "Save": "저장", - "Delete": "삭제", - "Enable": "활성화", - "Disable": "비활성화", - "Label-Home": "홈", - "Label-Proxies": "프록시", - "Label-Profiles": "프로필", - "Label-Connections": "연결", - "Label-Rules": "규칙", - "Label-Logs": "로그", - "Label-Unlock": "테스트", - "Label-Settings": "설정", - "Proxies": "프록시", - "Proxy Groups": "프록시 그룹", - "Proxy Provider": "프록시 제공자", - "Proxy Count": "프록시 개수", - "Update All": "모두 업데이트", - "Update At": "업데이트 시간", - "rule": "규칙", - "global": "전역", - "direct": "직접", - "Chain Proxy": "🔗 체인 프록시", - "script": "스크립트", - "locate": "로케이트", - "Delay check": "지연 확인", - "Sort by default": "기본값으로 정렬", - "Sort by delay": "지연시간으로 정렬", - "Sort by name": "이름으로 정렬", - "Delay check URL": "지연 확인 URL", - "Delay check to cancel fixed": "고정 취소를 위한 지연 확인", - "Proxy basic": "프록시 기본", - "Proxy detail": "프록시 상세", - "Profiles": "프로필", - "Update All Profiles": "모든 프로필 업데이트", - "View Runtime Config": "런타임 설정 보기", - "Reactivate Profiles": "프로필 재활성화", - "Paste": "붙여넣기", - "Profile URL": "프로필 URL", - "Import": "가져오기", - "From": "출처", - "Update Time": "업데이트 시간", - "Used / Total": "사용됨 / 전체", - "Expire Time": "만료 시간", - "Create Profile": "프로필 생성", - "Edit Profile": "프로필 편집", - "Edit Proxies": "프록시 편집", - "Use newlines for multiple uri": "여러 URI의 경우 줄바꿈 사용(Base64 인코딩 지원)", - "Edit Rules": "규칙 편집", - "Rule Type": "규칙 유형", - "Rule Content": "규칙 내용", - "Proxy Policy": "프록시 정책", - "No Resolve": "해석 안함", - "Prepend Rule": "규칙 앞에 추가", - "Append Rule": "규칙 뒤에 추가", - "Prepend Group": "그룹 앞에 추가", - "Append Group": "그룹 뒤에 추가", - "Prepend Proxy": "프록시 앞에 추가", - "Append Proxy": "프록시 뒤에 추가", - "Rule Condition Required": "규칙 조건 필요", - "Invalid Rule": "잘못된 규칙", - "Advanced": "고급", - "Visualization": "시각화", - "DOMAIN": "전체 도메인 이름과 일치", - "DOMAIN-SUFFIX": "도메인 접미사와 일치", - "DOMAIN-KEYWORD": "도메인 키워드와 일치", - "DOMAIN-REGEX": "정규 표현식을 사용한 도메인 일치", - "GEOSITE": "Geosite 내의 도메인과 일치", - "GEOIP": "IP 주소의 국가 코드와 일치", - "SRC-GEOIP": "소스 IP 주소의 국가 코드와 일치", - "IP-ASN": "IP 주소의 ASN과 일치", - "SRC-IP-ASN": "소스 IP 주소의 ASN과 일치", - "IP-CIDR": "IP 주소 범위와 일치", - "IP-CIDR6": "IPv6 주소 범위와 일치", - "SRC-IP-CIDR": "소스 IP 주소 범위와 일치", - "IP-SUFFIX": "IP 주소 접미사 범위와 일치", - "SRC-IP-SUFFIX": "소스 IP 주소 접미사 범위와 일치", - "SRC-PORT": "소스 포트 범위와 일치", - "DST-PORT": "대상 포트 범위와 일치", - "IN-PORT": "인바운드 포트와 일치", - "DSCP": "DSCP 마킹(tproxy UDP 인바운드만 해당)", - "PROCESS-NAME": "프로세스 이름과 일치(안드로이드 패키지 이름)", - "PROCESS-PATH": "전체 프로세스 경로와 일치", - "PROCESS-NAME-REGEX": "정규 표현식을 사용한 전체 프로세스 이름 일치(안드로이드 패키지 이름)", - "PROCESS-PATH-REGEX": "정규 표현식을 사용한 전체 프로세스 경로 일치", - "NETWORK": "전송 프로토콜과 일치(tcp/udp)", - "UID": "Linux 사용자 ID와 일치", - "IN-TYPE": "인바운드 유형과 일치", - "IN-USER": "인바운드 사용자 이름과 일치", - "IN-NAME": "인바운드 이름과 일치", - "SUB-RULE": "하위 규칙", - "RULE-SET": "규칙 세트와 일치", - "AND": "논리 AND", - "OR": "논리 OR", - "NOT": "논리 NOT", - "MATCH": "모든 요청과 일치", - "DIRECT": "데이터가 직접 아웃바운드로 이동", - "REJECT": "요청 차단", - "REJECT-DROP": "요청 폐기", - "PASS": "일치할 경우 이 규칙 건너뛰기", - "Edit Groups": "프록시 그룹 편집", - "Group Type": "그룹 유형", - "select": "수동으로 프록시 선택", - "url-test": "URL 테스트 지연을 기준으로 프록시 선택", - "fallback": "오류 발생 시 다른 프록시로 전환", - "load-balance": "부하 분산에 따라 프록시 분배", - "relay": "정의된 프록시 체인을 통과", - "Group Name": "그룹 이름", - "Use Proxies": "프록시 사용", - "Use Provider": "제공자 사용", - "Health Check Url": "상태 확인 URL", - "Expected Status": "예상 상태", - "Interval": "간격", - "Lazy": "지연 로딩", - "Timeout": "타임아웃", - "Max Failed Times": "최대 실패 횟수", - "Interface Name": "인터페이스 이름", - "Routing Mark": "라우팅 마크", - "Include All": "모든 프록시 및 제공자 포함", - "Include All Providers": "모든 제공자 포함", - "Include All Proxies": "모든 프록시 포함", - "Exclude Filter": "제외 필터", - "Exclude Type": "제외 유형", - "Disable UDP": "UDP 비활성화", - "Hidden": "숨김", - "Group Name Required": "그룹 이름 필수", - "Group Name Already Exists": "그룹 이름이 이미 존재함", - "Extend Config": "설정 확장", - "Extend Script": "스크립트 확장", - "Global Merge": "전역 설정 확장", - "Global Script": "전역 스크립트 확장", - "Type": "유형", - "Name": "이름", - "Descriptions": "설명", - "Subscription URL": "구독 URL", - "Update Interval": "업데이트 간격", - "Choose File": "파일 선택", - "Use System Proxy": "시스템 프록시 사용", - "Use Clash Proxy": "Clash 프록시 사용", - "Accept Invalid Certs (Danger)": "잘못된 인증서 허용(위험)", - "Refresh": "새로고침", - "Home": "홈", - "Select": "선택", - "Edit Info": "정보 편집", - "Edit File": "파일 편집", - "Open File": "파일 열기", - "Update": "업데이트", - "Update(Proxy)": "업데이트(프록시)", - "Confirm deletion": "삭제 확인", - "This operation is not reversible": "이 작업은 되돌릴 수 없습니다", - "Script Console": "스크립트 콘솔", - "To Top": "맨 위로", - "To End": "끝으로", - "Connections": "연결", - "Table View": "테이블 보기", - "List View": "목록 보기", - "Close All": "모두 닫기", - "Upload": "업로드", - "Download": "다운로드", - "Download Speed": "다운로드 속도", - "Upload Speed": "업로드 속도", - "Host": "호스트", - "Downloaded": "다운로드됨", - "Uploaded": "업로드됨", - "DL Speed": "다운로드 속도", - "UL Speed": "업로드 속도", - "Active Connections": "활성 연결", - "Chains": "체인", - "Rule": "규칙", - "Process": "프로세스", - "Time": "시간", - "Source": "소스", - "Destination": "목적지", - "DestinationPort": "목적지 포트", - "Close Connection": "연결 닫기", - "Rules": "규칙", - "Rule Provider": "규칙 제공자", - "Logs": "로그", - "Pause": "일시 정지", - "Resume": "재개", - "Clear": "지우기", - "Test": "테스트", - "Test All": "모두 테스트", - "Testing...": "테스트 중...", - "Create Test": "테스트 생성", - "Edit Test": "테스트 편집", - "Icon": "아이콘", - "Test URL": "테스트 URL", - "Settings": "설정", - "System Setting": "시스템 설정", - "Tun Mode": "Tun 모드", - "Stack": "스택", - "Auto Route": "자동 라우팅", - "Auto Detect Interface": "인터페이스 자동 감지", - "MTU": "MTU", - "Service Mode": "서비스 모드", - "System Proxy": "시스템 프록시", - "Silent Start": "자동 시작", - "Clash Setting": "Clash 설정", - "IPv6": "IPv6", - "Log Level": "로그 레벨", - "Mixed Port": "혼합 포트", - "Verge Basic Setting": "Verge 기본 설정", - "Language": "언어", - "Theme Mode": "테마 모드", - "Tray Click Event": "트레이 클릭 이벤트", - "Show Main Window": "메인 창 표시", - "Show Tray Menu": "트레이 메뉴 표시", - "Copy Env Type": "환경 유형 복사", - "Copy Success": "복사 성공", - "Start Page": "시작 페이지", - "Startup Script": "시작 스크립트", - "Primary Color": "기본 색상", - "Layout Setting": "레이아웃 설정", - "Traffic Graph": "트래픽 그래프", - "Memory Usage": "메모리 사용량", - "Auto Delay Detection": "자동 지연 감지", - "Auto Delay Detection Info": "백그라운드에서 현재 노드의 지연을 주기적으로 검사합니다", - "Hotkey Setting": "단축키 설정", - "Filter": "필터", - "Import Subscription Successful": "구독 가져오기 성공", - "Username": "사용자 이름", - "Password": "비밀번호", - "Theme": "테마", - "Config Validation Failed": "설정 검증 실패", - "Boot Config Validation Failed": "부팅 설정 검증 실패", - "Core Change Config Validation Failed": "코어 변경 설정 검증 실패", - "Config Validation Process Terminated": "설정 검증 프로세스 종료됨", - "Script Syntax Error": "스크립트 구문 오류", - "Script Missing Main": "스크립트 메인 없음", - "File Not Found": "파일을 찾을 수 없음", - "Script File Error": "스크립트 파일 오류", - "Core Changed Successfully": "코어 변경 성공", - "Failed to Change Core": "코어 변경 실패", - "YAML Syntax Error": "YAML 구문 오류", - "YAML Read Error": "YAML 읽기 오류", - "YAML Mapping Error": "YAML 매핑 오류", - "YAML Key Error": "YAML 키 오류", - "YAML Error": "YAML 오류", - "Merge File Syntax Error": "병합 파일 구문 오류", - "Merge File Mapping Error": "병합 파일 매핑 오류", - "Merge File Key Error": "병합 파일 키 오류", - "Merge File Error": "병합 파일 오류", - "Update with Clash proxy successfully": "Clash 프록시로 업데이트 성공", - "Update failed even with Clash proxy": "Clash 프록시로도 업데이트 실패", - "Failed": "실패", - "Address": "주소", - "Allow LAN": "LAN 허용", - "Always": "항상", - "Appearance": "외관", - "Auth Proxy": "인증 프록시", - "Authorization for requests coming through HTTP Proxy (e.g. local connections)": "HTTP 프록시를 통한 요청에 대한 인증 (예: 로컬 연결)", - "Auto": "자동", - "Auto Start": "자동 시작", - "Blue": "파란색", - "Built-in Web UI": "내장 웹 UI", - "By Traffic": "트래픽별", - "Cannot Import Empty Subscription URL": "빈 구독 URL을 가져올 수 없습니다", - "Capture": "캡처", - "Check Network": "네트워크 확인", - "Check Updates": "업데이트 확인", - "Check Updates on Start": "시작 시 업데이트 확인", - "Clean Cache": "캐시 정리", - "Color Scheme": "색상 구성표", - "Compact Mode": "압축 모드", - "Copy Failed": "복사 실패", - "Core Config": "코어 설정", - "Core Type": "코어 유형", - "Create Profile Failed": "프로필 생성 실패", - "Create Profile Successful": "프로필 생성 성공", - "Current Config": "현재 설정", - "Customize primary color": "기본 색상 사용자 정의", - "Cyan": "청록색", - "Danger Zone": "위험 영역", - "Dark": "다크", - "Default": "기본값", - "Delete Profile Failed": "프로필 삭제 실패", - "Delete Profile Successful": "프로필 삭제 성공", - "Enable API": "API 활성화", - "Enable Clash.Meta Logs": "Clash.Meta 로그 활성화", - "Enable Default DNS Hijack": "기본 DNS 하이재킹 활성화", - "Enable Hotkeys": "단축키 활성화", - "Enable Lan": "LAN 활성화", - "Enable Verge Logs": "Verge 로그 활성화", - "Endpoint Independent Nat": "엔드포인트 독립 NAT", - "Error": "오류", - "Expected": "예상됨", - "Experimental Features": "실험적 기능", - "For Alpha Version": "알파 버전용", - "General": "일반", - "Geox Password": "Geox 비밀번호", - "Geox User": "Geox 사용자", - "Git Proxy": "Git 프록시", - "Green": "녹색", - "Hidden Window on Start": "시작 시 창 숨기기", - "Hotkey Enable": "단축키 활성화", - "Icon Group Type": "아이콘 그룹 유형", - "Include Reserved": "예약된 IP 포함", - "Inject CSS": "CSS 주입", - "Inject HTML": "HTML 주입", - "Inject a custom CSS content into the GUI": "사용자 정의 CSS 내용을 GUI에 주입", - "Inject a custom HTML content into the GUI (appended in body)": "사용자 정의 HTML 내용을 GUI에 주입 (본문에 추가)", - "Input Subscription URL": "구독 URL 입력", - "Installed Web UI": "설치된 웹 UI", - "Latest Build Version": "최신 빌드 버전", - "Light": "라이트", - "Log File": "로그 파일", - "Log Notice": "로그 알림", - "Method": "메소드", - "Misc Setting": "기타 설정", - "Mixin": "혼합", - "Mode": "모드", - "Network": "네트워크", - "On Update": "업데이트 시", - "Open Config Dir": "설정 디렉토리 열기", - "Open Config Folder": "설정 폴더 열기", - "Open Dashboard": "대시보드 열기", - "Others": "기타", - "Patch Profile Failed": "프로필 패치 실패", - "Patch Profile Successful": "프로필 패치 성공", - "Pink": "분홍색", - "Port": "포트", - "Profile Already Exists": "프로필이 이미 존재합니다", - "Profile Format": "프로필 포맷", - "Profile Token": "프로필 토큰", - "Profile User Agent": "프로필 사용자 에이전트", - "Proxy Detail": "프록시 상세", - "Proxy Item Height": "프록시 항목 높이", - "Proxy Item Width": "프록시 항목 너비", - "Proxy Setting": "프록시 설정", - "Purple": "보라색", - "Red": "빨간색", - "Require Clash Core Running": "Clash 코어 실행 필요", - "Reset Verge Theme": "Verge 테마 재설정", - "Select Active Profile Failed": "활성 프로필 선택 실패", - "Select Active Profile Successful": "활성 프로필 선택 성공", - "Select a config file": "설정 파일 선택", - "Set System Proxy": "시스템 프록시 설정", - "Set as System Auto Proxy": "시스템 자동 프록시로 설정", - "Set as System Proxy": "시스템 프록시로 설정", - "Silent Start Option": "자동 시작 옵션", - "Skip Cert Verify": "인증서 확인 건너뛰기", - "Specify YAML": "YAML 지정", - "Start Core on Start": "시작 시 코어 시작", - "Start Core with System": "시스템과 함께 코어 시작", - "Start Core with System Proxy": "시스템 프록시와 함께 코어 시작", - "Start Core with Tun": "Tun과 함께 코어 시작", - "Start Option": "시작 옵션", - "Start With System": "시스템과 함께 시작", - "Status": "상태", - "Succeed": "성공", - "System": "시스템", - "System Auto Proxy Status": "시스템 자동 프록시 상태", - "System Config": "시스템 설정", - "System Hotkey": "시스템 단축키", - "System Proxy Permission": "시스템 프록시 권한", - "System Proxy Status": "시스템 프록시 상태", - "System Stack Type": "시스템 스택 유형", - "TCP Fast Open": "TCP 빠른 열기", - "TcpConcurrent": "TCP 동시성", - "The User Agent to use when refreshing a subscription profile.": "구독 프로필을 새로 고칠 때 사용할 사용자 에이전트입니다.", - "The expected content type to send in the `Accept` header when refreshing a subscription profile.": "구독 프로필을 새로 고칠 때 `Accept` 헤더에 보낼 예상 컨텐츠 타입입니다.", - "Theme Color": "테마 색상", - "Timeout (ms)": "타임아웃 (ms)", - "Transparent Proxy": "투명 프록시", - "URL": "URL", - "Undefined stack": "정의되지 않은 스택", - "Update Failed": "업데이트 실패", - "Update Interval(minute)": "업데이트 간격(분)", - "Update Setting": "업데이트 설정", - "Update Successful": "업데이트 성공", - "Verge Log": "Verge 로그", - "Verge Setting": "Verge 설정", - "View Profile-Content": "프로필-내용 보기", - "View Profile-Merge": "프로필-병합 보기", - "View Profile-Original": "프로필-원본 보기", - "View Profile-Runtime": "프로필-런타임 보기", - "View Profile-Script": "프로필-스크립트 보기", - "Warning": "경고", - "Web UI List": "웹 UI 목록", - "WebDav Download": "WebDav 다운로드", - "WebDav Password": "WebDav 비밀번호", - "WebDav Setting": "WebDav 설정", - "WebDav Status": "WebDav 상태", - "WebDav URL": "WebDav URL", - "WebDav Upload": "WebDav 업로드", - "WebDav Username": "WebDav 사용자 이름", - "WebUI Current Port": "웹 UI 현재 포트", - "Yellow": "노란색" -} diff --git a/src/locales/ko/connections.json b/src/locales/ko/connections.json new file mode 100644 index 000000000..f277d252a --- /dev/null +++ b/src/locales/ko/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "연결" + }, + "components": { + "fields": { + "host": "호스트", + "dlSpeed": "다운로드 속도", + "ulSpeed": "업로드 속도", + "chains": "체인", + "rule": "규칙", + "process": "프로세스", + "time": "시간", + "source": "소스", + "destination": "목적지", + "destinationPort": "목적지 포트", + "type": "유형" + }, + "order": { + "default": "기본", + "uploadSpeed": "업로드 속도", + "downloadSpeed": "다운로드 속도" + }, + "actions": { + "closeConnection": "연결 닫기" + } + } +} diff --git a/src/locales/ko/home.json b/src/locales/ko/home.json new file mode 100644 index 000000000..4cd949afc --- /dev/null +++ b/src/locales/ko/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "경량 모드", + "manual": "사용 설명서", + "settings": "홈 설정" + }, + "cards": { + "trafficStats": "트래픽 통계", + "networkSettings": "네트워크 설정", + "proxyMode": "프록시 모드" + }, + "settings": { + "cards": { + "profile": "프로필 카드", + "currentProxy": "현재 프록시 카드", + "network": "네트워크 설정 카드", + "proxyMode": "프록시 모드 카드", + "traffic": "트래픽 통계 카드", + "tests": "웹사이트 테스트 카드", + "ip": "IP 정보 카드", + "clashInfo": "Clash 정보 카드", + "systemInfo": "시스템 정보 카드" + }, + "title": "홈 설정" + }, + "title": "홈" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "시스템 프록시가 활성화되었습니다. 애플리케이션이 프록시를 통해 네트워크에 접근합니다", + "systemProxyDisabled": "시스템 프록시가 비활성화되었습니다. 대부분의 사용자에게 이 옵션을 켜는 것을 권장합니다", + "tunModeServiceRequired": "TUN 모드는 서비스 모드가 필요합니다. 먼저 서비스를 설치하세요", + "tunModeEnabled": "TUN 모드가 활성화되었습니다. 애플리케이션이 가상 네트워크 카드를 통해 네트워크에 접근합니다", + "tunModeDisabled": "TUN 모드가 비활성화되었습니다. 특수 애플리케이션에 적합합니다" + }, + "tooltips": { + "systemProxy": "운영 체제의 프록시 설정을 수정합니다. 활성화에 실패하면 운영 체제의 프록시 설정을 수동으로 수정하세요", + "tunMode": "TUN 모드는 모든 애플리케이션 트래픽을 인수할 수 있으며 시스템 프록시를 따르지 않는 특수 앱에 적합합니다" + } + }, + "clashInfo": { + "title": "Clash 정보", + "fields": { + "coreVersion": "코어 버전", + "systemProxyAddress": "시스템 프록시 주소", + "mixedPort": "혼합 포트", + "uptime": "업타임", + "rulesCount": "규칙 개수" + } + }, + "systemInfo": { + "title": "시스템 정보", + "fields": { + "osInfo": "OS 정보", + "autoLaunch": "자동 실행", + "runningMode": "실행 모드", + "lastCheckUpdate": "마지막 업데이트 확인", + "vergeVersion": "Verge 버전" + }, + "actions": { + "settings": "설정" + }, + "tooltips": { + "autoLaunchAdmin": "관리자 모드에서는 자동 실행이 지원되지 않을 수 있습니다" + }, + "badges": { + "adminMode": "관리자 모드", + "serviceMode": "서비스 모드", + "sidecarMode": "사용자 모드", + "adminServiceMode": "관리자 + 서비스 모드" + } + }, + "ipInfo": { + "title": "IP 정보", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "위치", + "timezone": "시간대", + "autoRefresh": "자동 새로고침", + "unknown": "알 수 없음" + }, + "errors": { + "load": "IP 정보를 가져오지 못했습니다" + } + }, + "currentProxy": { + "title": "현재 노드", + "actions": { + "refreshDelay": "지연 확인" + }, + "labels": { + "globalMode": "전역 모드", + "directMode": "직접 모드", + "group": "그룹", + "proxy": "프록시", + "noActiveNode": "활성 프록시 노드 없음" + } + }, + "tests": { + "title": "웹사이트 테스트" + }, + "traffic": { + "metrics": { + "uploadSpeed": "업로드 속도", + "downloadSpeed": "다운로드 속도", + "activeConnections": "활성 연결", + "memoryUsage": "코어 사용량" + }, + "legends": { + "upload": "업로드", + "download": "다운로드" + }, + "patterns": { + "minutes": "{{time}}분" + } + }, + "clashMode": { + "errors": { + "communication": "코어 통신 오류" + }, + "labels": { + "rule": "규칙", + "global": "전역", + "direct": "직접" + }, + "descriptions": { + "rule": "규칙 세트에 따라 자동으로 프록시를 선택합니다.", + "global": "모든 네트워크 요청을 선택한 프록시를 통해 전달합니다.", + "direct": "프록시를 우회하여 직접 인터넷에 연결합니다." + } + } + } +} diff --git a/src/locales/ko/index.ts b/src/locales/ko/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/ko/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/ko/layout.json b/src/locales/ko/layout.json new file mode 100644 index 000000000..ffc3ccb27 --- /dev/null +++ b/src/locales/ko/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "홈", + "proxies": "프록시", + "profiles": "프로필", + "connections": "연결", + "rules": "규칙", + "logs": "로그", + "unlock": "테스트", + "settings": "설정" + }, + "menu": { + "reorderMode": "메뉴 재정렬 모드", + "unlock": "메뉴 순서 잠금 해제", + "lock": "메뉴 순서 잠금" + } + } + } +} diff --git a/src/locales/ko/logs.json b/src/locales/ko/logs.json new file mode 100644 index 000000000..a5e30a1da --- /dev/null +++ b/src/locales/ko/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "로그" + } +} diff --git a/src/locales/ko/profiles.json b/src/locales/ko/profiles.json new file mode 100644 index 000000000..9b3647cbe --- /dev/null +++ b/src/locales/ko/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "모든 프로필 업데이트", + "viewRuntimeConfig": "런타임 설정 보기", + "reactivate": "프로필 재활성화", + "import": "가져오기" + }, + "batch": { + "actions": { + "delete": "선택한 프로필 삭제", + "selectAll": "모두 선택", + "deselectAll": "모두 선택 해제", + "done": "완료" + }, + "summary": { + "selected": "선택됨", + "items": "항목" + }, + "title": "일괄 작업" + }, + "importForm": { + "placeholder": "프로필 URL", + "actions": { + "paste": "붙여넣기" + } + }, + "feedback": { + "errors": { + "invalidUrl": "잘못된 프로필 URL입니다. http:// 또는 https://로 시작하는 URL을 입력하세요", + "onlyYaml": "YAML 파일만 지원됩니다" + }, + "notifications": { + "importRetry": "가져오기에 실패했습니다. Clash 프록시로 다시 시도 중...", + "importFail": "Clash 프록시로도 가져오기에 실패했습니다", + "importNeedsRefresh": "프로필을 가져왔지만 수동 새로고침이 필요할 수 있습니다", + "importSuccess": "프로필을 성공적으로 가져왔습니다. 보이지 않으면 재시작하세요", + "profileSwitched": "프로필 전환됨", + "profileReactivated": "프로필 재활성화됨", + "switchInterrupted": "새 선택으로 인해 프로필 전환이 중단되었습니다", + "batchDeleted": "선택한 프로필이 삭제되었습니다" + }, + "notices": { + "forceRefreshCompleted": "강제 새로고침 완료", + "emergencyRefreshFailed": "긴급 새로고침 실패: {{message}}" + } + }, + "title": "프로필" + }, + "components": { + "card": { + "labels": { + "clickToImport": "클릭하여 구독 가져오기" + } + }, + "fileInput": { + "chooseFile": "파일 선택" + }, + "menu": { + "home": "홈", + "select": "선택", + "editInfo": "정보 편집", + "editFile": "파일 편집", + "editRules": "규칙 편집", + "editProxies": "프록시 편집", + "editGroups": "프록시 그룹 편집", + "extendConfig": "설정 확장", + "extendScript": "스크립트 확장", + "openFile": "파일 열기", + "update": "업데이트", + "updateViaProxy": "프록시를 통해 업데이트" + }, + "more": { + "global": { + "merge": "전역 확장 구성", + "script": "전역 확장 스크립트" + }, + "chips": { + "merge": "병합", + "script": "스크립트" + } + }, + "profileItem": { + "tooltips": { + "showLast": "클릭하여 마지막 업데이트 시간 표시", + "showNext": "클릭하여 다음 업데이트 표시" + }, + "status": { + "lastUpdateFailed": "마지막 업데이트 실패", + "nextUp": "다음 예정", + "noSchedule": "예약 없음", + "unknown": "알 수 없음", + "autoUpdateDisabled": "자동 업데이트 비활성화됨" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "프로필 생성", + "edit": "프로필 편집" + }, + "fields": { + "type": "유형", + "description": "설명", + "subscriptionUrl": "구독 URL", + "httpTimeout": "HTTP 요청 시간 초과", + "updateInterval": "업데이트 간격", + "useSystemProxy": "시스템 프록시 사용", + "useClashProxy": "Clash 프록시 사용", + "acceptInvalidCerts": "잘못된 인증서 허용(위험)", + "allowAutoUpdate": "자동 업데이트 허용" + }, + "feedback": { + "notifications": { + "creationRetry": "프로필 생성 실패, Clash 프록시로 다시 시도 중...", + "creationSuccess": "Clash 프록시로 프로필 생성 성공" + } + } + }, + "proxiesEditor": { + "title": "프록시 편집", + "placeholders": { + "multiUri": "여러 URI의 경우 줄바꿈 사용(Base64 인코딩 지원)" + }, + "actions": { + "prepend": "프록시 앞에 추가", + "append": "프록시 뒤에 추가" + } + }, + "groupsEditor": { + "title": "프록시 그룹 편집", + "errors": { + "nameRequired": "그룹 이름 필수", + "nameExists": "그룹 이름이 이미 존재함" + }, + "fields": { + "type": "그룹 유형", + "name": "그룹 이름", + "icon": "프록시 그룹 아이콘", + "proxies": "프록시 사용", + "provider": "제공자 사용", + "healthCheckUrl": "상태 확인 URL", + "expectedStatus": "예상 상태", + "interval": "간격", + "maxFailedTimes": "최대 실패 횟수", + "interfaceName": "인터페이스 이름", + "routingMark": "라우팅 마크", + "filter": "필터", + "excludeFilter": "제외 필터", + "excludeType": "제외 유형", + "includeAll": "모든 프록시 및 제공자 포함", + "includeAllProxies": "모든 프록시 포함", + "includeAllProviders": "모든 제공자 포함" + }, + "toggles": { + "lazy": "지연 로딩", + "disableUdp": "UDP 비활성화", + "hidden": "숨김" + }, + "actions": { + "prepend": "그룹 앞에 추가", + "append": "그룹 뒤에 추가" + } + }, + "editor": { + "actions": { + "format": "문서 포맷" + }, + "messages": { + "readOnly": "읽기 전용 편집기에서는 편집할 수 없습니다" + } + }, + "confirmDelete": { + "title": "삭제 확인", + "message": "이 작업은 되돌릴 수 없습니다" + }, + "logViewer": { + "title": "스크립트 콘솔" + } + } +} diff --git a/src/locales/ko/proxies.json b/src/locales/ko/proxies.json new file mode 100644 index 000000000..09ce8674d --- /dev/null +++ b/src/locales/ko/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "규칙", + "global": "전역", + "direct": "직접" + }, + "actions": { + "toggleChain": "🔗 체인 프록시", + "connect": "연결", + "disconnect": "연결 해제", + "connecting": "연결 중...", + "clearChainConfig": "체인 구성 삭제" + }, + "provider": { + "title": "프록시 제공자", + "actions": { + "updateAll": "모두 업데이트", + "update": "업데이트" + } + }, + "rules": { + "title": "프록시 규칙", + "select": "규칙 선택" + }, + "labels": { + "proxyCount": "프록시 개수", + "delayCheckReset": "고정 취소를 위한 지연 확인" + }, + "tooltips": { + "locate": "위치 찾기", + "delayCheck": "지연 확인", + "sortDefault": "기본 정렬", + "sortDelay": "지연으로 정렬", + "sortName": "이름으로 정렬", + "delayCheckUrl": "지연 확인 URL", + "showBasic": "프록시 기본", + "showDetail": "프록시 상세", + "filter": "필터" + }, + "placeholders": { + "delayCheckUrl": "지연 확인 URL" + }, + "chain": { + "header": "체인 프록시 구성", + "empty": "구성된 프록시 체인이 없습니다", + "instruction": "프록시 체인에 추가하려면 순서대로 노드를 클릭하세요", + "minimumNodes": "체인 프록시는 최소 2개의 노드가 필요합니다", + "minimumNodesHint": "체인 프록시는 최소 2개의 노드가 필요합니다. 하나 더 추가하세요.", + "connectFailed": "프록시 체인 연결 실패", + "disconnectFailed": "프록시 체인 연결 해제 실패", + "duplicateNode": "프록시 노드가 체인에 이미 존재합니다" + }, + "messages": { + "directMode": "직접 모드" + }, + "title": { + "default": "프록시 그룹", + "chainMode": "프록시 체인 모드" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} 업데이트 성공", + "updateFailed": "{{name}} 업데이트 실패: {{message}}", + "genericError": "업데이트 실패: {{message}}", + "none": "업데이트할 제공자가 없습니다", + "allUpdated": "모든 제공자가 업데이트되었습니다" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "수동으로 프록시 선택", + "url-test": "URL 테스트 지연을 기준으로 프록시 선택", + "fallback": "오류 발생 시 다른 프록시로 전환", + "load-balance": "부하 분산에 따라 프록시 분배", + "relay": "정의된 프록시 체인을 통과" + }, + "policies": { + "DIRECT": "데이터가 직접 아웃바운드로 이동", + "REJECT": "요청 차단", + "REJECT-DROP": "요청 폐기", + "PASS": "일치할 경우 이 규칙 건너뛰기" + } + } + } +} diff --git a/src/locales/ko/rules.json b/src/locales/ko/rules.json new file mode 100644 index 000000000..26e0a9fd1 --- /dev/null +++ b/src/locales/ko/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "규칙 제공자", + "dialogTitle": "규칙 제공자", + "actions": { + "updateAll": "모두 업데이트", + "update": "업데이트" + } + }, + "title": "규칙" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} 업데이트 성공", + "updateFailed": "{{name}} 업데이트 실패: {{message}}", + "genericError": "업데이트 실패: {{message}}", + "none": "업데이트할 제공자가 없습니다", + "allUpdated": "모든 제공자가 업데이트되었습니다" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "규칙 유형", + "content": "규칙 내용", + "proxyPolicy": "프록시 정책" + }, + "toggles": { + "noResolve": "해석 안함" + }, + "actions": { + "prependRule": "규칙 앞에 추가", + "appendRule": "규칙 뒤에 추가" + }, + "validation": { + "conditionRequired": "규칙 조건 필요", + "invalidRule": "잘못된 규칙" + } + }, + "ruleTypes": { + "DOMAIN": "전체 도메인 이름과 일치", + "DOMAIN-SUFFIX": "도메인 접미사와 일치", + "DOMAIN-KEYWORD": "도메인 키워드와 일치", + "DOMAIN-REGEX": "정규 표현식을 사용한 도메인 일치", + "GEOSITE": "Geosite 내의 도메인과 일치", + "GEOIP": "IP 주소의 국가 코드와 일치", + "SRC-GEOIP": "소스 IP 주소의 국가 코드와 일치", + "IP-ASN": "IP 주소의 ASN과 일치", + "SRC-IP-ASN": "소스 IP 주소의 ASN과 일치", + "IP-CIDR": "IP 주소 범위와 일치", + "IP-CIDR6": "IPv6 주소 범위와 일치", + "SRC-IP-CIDR": "소스 IP 주소 범위와 일치", + "IP-SUFFIX": "IP 주소 접미사 범위와 일치", + "SRC-IP-SUFFIX": "소스 IP 주소 접미사 범위와 일치", + "SRC-PORT": "소스 포트 범위와 일치", + "DST-PORT": "대상 포트 범위와 일치", + "IN-PORT": "인바운드 포트와 일치", + "DSCP": "DSCP 마킹(tproxy UDP 인바운드만 해당)", + "PROCESS-NAME": "프로세스 이름과 일치(안드로이드 패키지 이름)", + "PROCESS-PATH": "전체 프로세스 경로와 일치", + "PROCESS-NAME-REGEX": "정규 표현식을 사용한 전체 프로세스 이름 일치(안드로이드 패키지 이름)", + "PROCESS-PATH-REGEX": "정규 표현식을 사용한 전체 프로세스 경로 일치", + "NETWORK": "전송 프로토콜과 일치(tcp/udp)", + "UID": "Linux 사용자 ID와 일치", + "IN-TYPE": "인바운드 유형과 일치", + "IN-USER": "인바운드 사용자 이름과 일치", + "IN-NAME": "인바운드 이름과 일치", + "SUB-RULE": "하위 규칙", + "RULE-SET": "규칙 세트와 일치", + "AND": "논리 AND", + "OR": "논리 OR", + "NOT": "논리 NOT", + "MATCH": "모든 요청과 일치" + }, + "title": "규칙 편집" + } + } +} diff --git a/src/locales/ko/settings.json b/src/locales/ko/settings.json new file mode 100644 index 000000000..1fe918129 --- /dev/null +++ b/src/locales/ko/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "문서", + "telegram": "Telegram 채널", + "github": "GitHub 저장소" + }, + "title": "설정" + }, + "sections": { + "system": { + "title": "시스템 설정", + "toggles": { + "tunMode": "TUN 모드", + "systemProxy": "시스템 프록시" + }, + "tooltips": { + "autoLaunchAdmin": "관리자 모드에서는 자동 실행이 지원되지 않을 수 있습니다", + "silentStart": "패널을 표시하지 않고 백그라운드에서 시작합니다" + }, + "fields": { + "autoLaunch": "자동 실행", + "silentStart": "백그라운드 시작" + }, + "notifications": { + "tunMode": { + "autoDisabled": "서비스를 사용할 수 없어 TUN 모드가 자동으로 비활성화되었습니다", + "autoDisableFailed": "TUN 모드를 자동으로 비활성화하지 못했습니다" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "운영 체제의 프록시 설정을 수정합니다. 활성화에 실패하면 운영 체제의 프록시를 수동으로 설정하세요", + "tunMode": "TUN(가상 NIC) 모드: 시스템 전체 트래픽을 캡처합니다. 활성화 시 시스템 프록시를 사용할 필요가 없습니다.", + "tunUnavailable": "TUN은 서비스 모드 또는 관리자 모드가 필요합니다" + }, + "actions": { + "installService": "서비스 설치", + "uninstallService": "서비스 제거" + }, + "fields": { + "systemProxy": "시스템 프록시", + "tunMode": "TUN 모드" + } + }, + "externalController": { + "title": "외부 컨트롤러", + "fields": { + "enable": "외부 컨트롤러 사용", + "address": "외부 컨트롤러 주소", + "secret": "코어 비밀키" + }, + "placeholders": { + "address": "필수", + "secret": "권장" + }, + "tooltips": { + "copy": "클립보드에 복사" + }, + "messages": { + "addressRequired": "컨트롤러 주소는 비워둘 수 없습니다", + "secretRequired": "비밀키는 비워둘 수 없습니다", + "copyFailed": "복사 실패", + "controllerCopied": "컨트롤러 주소가 클립보드에 복사되었습니다", + "secretCopied": "비밀키가 클립보드에 복사되었습니다" + } + }, + "externalCors": { + "title": "외부 CORS 구성", + "fields": { + "allowPrivateNetwork": "프라이빗 네트워크 접근 허용", + "allowedOrigins": "허용된 오리진" + }, + "placeholders": { + "origin": "유효한 URL을 입력하세요" + }, + "actions": { + "add": "추가" + }, + "messages": { + "alwaysIncluded": "항상 포함되는 오리진: {{urls}}" + }, + "tooltips": { + "open": "외부 CORS 설정" + } + }, + "appearance": { + "light": "라이트", + "dark": "다크", + "system": "시스템" + }, + "clash": { + "title": "Clash 설정", + "form": { + "fields": { + "allowLan": "LAN 허용", + "dnsOverwrite": "DNS 덮어쓰기", + "ipv6": "IPv6", + "unifiedDelay": "지연 통합", + "logLevel": "로그 레벨", + "portConfig": "포트 설정", + "external": "외부", + "webUI": "Web UI", + "clashCore": "Clash 코어", + "openUwpTool": "UWP 도구 열기", + "updateGeoData": "GeoData 업데이트" + }, + "tooltips": { + "networkInterface": "네트워크 인터페이스", + "unifiedDelay": "지연 통합을 켜면, 서로 다른 유형의 노드에서 연결 핸드셰이크 등으로 발생하는 지연 차이를 제거하기 위해 두 번의 지연 테스트를 수행합니다", + "logLevel": "이 매개변수는 로그 디렉터리 Service 폴더의 커널 로그 파일에만 적용됩니다", + "openUwpTool": "Windows 8 이후 UWP 앱(예: Microsoft Store)은 로컬 호스트 네트워크 서비스에 직접 접근이 제한됩니다. 이 도구로 해당 제한을 우회할 수 있습니다" + }, + "options": { + "logLevel": { + "debug": "디버그", + "info": "정보", + "warning": "경고", + "error": "오류", + "silent": "무음" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge 기본 설정", + "actions": { + "browse": "찾아보기" + }, + "trayOptions": { + "showMainWindow": "메인 창 표시", + "showTrayMenu": "트레이 메뉴 표시", + "disable": "비활성화" + }, + "fields": { + "language": "언어", + "themeMode": "테마 모드", + "trayClickEvent": "트레이 클릭 이벤트", + "copyEnvType": "환경 유형 복사", + "startPage": "시작 페이지", + "startupScript": "시작 스크립트", + "themeSetting": "테마 설정", + "layoutSetting": "레이아웃 설정", + "misc": "기타", + "hotkeySetting": "단축키 설정" + } + }, + "advanced": { + "title": "Verge 고급 설정", + "tooltips": { + "backupInfo": "설정 파일의 로컬 또는 WebDAV 백업을 지원합니다", + "openConfDir": "소프트웨어가 비정상 동작할 경우, 이 폴더의 파일을 백업 후 모두 삭제하고 재시작하세요", + "liteMode": "GUI를 닫고 커널만 실행 상태로 유지합니다" + }, + "actions": { + "copyVersion": "버전 복사" + }, + "notifications": { + "latestVersion": "현재 최신 버전입니다", + "versionCopied": "버전이 클립보드에 복사되었습니다" + }, + "fields": { + "backupSetting": "백업 설정", + "runtimeConfig": "런타임 구성", + "openConfDir": "설정 디렉터리 열기", + "openCoreDir": "코어 디렉터리 열기", + "openLogsDir": "로그 디렉터리 열기", + "checkUpdates": "업데이트 확인", + "openDevTools": "개발자 도구", + "liteModeSettings": "경량 모드 설정", + "exit": "종료", + "exportDiagnostics": "진단 정보 내보내기", + "vergeVersion": "Verge 버전" + } + }, + "theme": { + "title": "테마 설정", + "fields": { + "primaryColor": "기본 색상", + "secondaryColor": "보조 색상", + "primaryText": "기본 텍스트", + "secondaryText": "보조 텍스트", + "infoColor": "정보 색상", + "warningColor": "경고 색상", + "errorColor": "오류 색상", + "successColor": "성공 색상", + "fontFamily": "글꼴", + "cssInjection": "CSS 삽입" + }, + "actions": { + "editCss": "CSS 편집" + }, + "dialogs": { + "editCssTitle": "CSS 편집" + } + }, + "layout": { + "title": "레이아웃 설정", + "fields": { + "preferSystemTitlebar": "시스템 제목 표시줄 사용", + "trafficGraph": "트래픽 그래프", + "memoryUsage": "메모리 사용량", + "proxyGroupIcon": "프록시 그룹 아이콘", + "hoverNavigator": "호버 점프 내비게이터", + "hoverNavigatorDelay": "호버 점프 내비게이터 지연", + "navIcon": "내비게이션 아이콘", + "trayIcon": "트레이 아이콘", + "showProxyGroupsInline": "프록시 그룹 인라인 표시", + "commonTrayIcon": "공용 트레이 아이콘", + "systemProxyTrayIcon": "시스템 프록시 트레이 아이콘", + "tunTrayIcon": "TUN 트레이 아이콘", + "enableTrayIcon": "트레이 아이콘 사용", + "enableTraySpeed": "트레이 속도 표시 사용" + }, + "tooltips": { + "hoverNavigator": "알파벳에 마우스를 올리면 해당 프록시 그룹으로 자동 스크롤합니다", + "hoverNavigatorDelay": "호버 시 자동 스크롤까지의 지연(밀리초)" + }, + "options": { + "icon": { + "monochrome": "단색", + "colorful": "컬러", + "disable": "비활성화" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "포트 설정", + "fields": { + "mixed": "혼합 포트", + "socks": "SOCKS 포트", + "http": "HTTP(S) 포트", + "redir": "Redir 포트", + "tproxy": "TProxy 포트" + }, + "actions": { + "random": "임의 포트" + }, + "messages": { + "saved": "포트 설정이 저장되었습니다", + "saveFailed": "포트 설정 저장에 실패했습니다" + } + }, + "clashCore": { + "variants": { + "release": "안정 버전", + "alpha": "알파 버전" + } + }, + "liteMode": { + "title": "경량 모드 설정", + "actions": { + "enterNow": "지금 경량 모드로 전환" + }, + "toggles": { + "autoEnter": "경량 모드 자동 진입" + }, + "tooltips": { + "autoEnter": "창을 닫은 뒤 일정 시간이 지나면 자동으로 경량 모드가 활성화됩니다" + }, + "fields": { + "delay": "경량 모드 자동 진입 지연" + }, + "messages": { + "autoEnterHint": "창을 닫으면 {{n}}분 후 자동으로 경량 모드가 활성화됩니다" + } + }, + "backup": { + "title": "백업 설정", + "tabs": { + "local": "로컬 백업", + "webdav": "WebDAV 백업" + }, + "actions": { + "selectTarget": "백업 대상 선택", + "backup": "백업", + "export": "내보내기", + "exportBackup": "백업 내보내기", + "deleteBackup": "백업 삭제", + "restore": "복원", + "restoreBackup": "백업 복원" + }, + "fields": { + "webdavUrl": "WebDAV 서버 URL", + "username": "사용자 이름", + "info": "백업은 애플리케이션 데이터 디렉터리에 로컬로 저장됩니다. 아래 목록을 사용해 복원하거나 삭제할 수 있습니다." + }, + "messages": { + "webdavUrlRequired": "WebDAV URL은 비워둘 수 없습니다", + "invalidWebdavUrl": "유효하지 않은 WebDAV URL 형식입니다", + "usernameRequired": "사용자 이름은 비워둘 수 없습니다", + "passwordRequired": "비밀번호는 비워둘 수 없습니다", + "webdavConfigSaved": "WebDAV 구성이 저장되었습니다", + "webdavConfigSaveFailed": "WebDAV 구성 저장 실패: {{error}}", + "backupCreated": "백업이 생성되었습니다", + "backupFailed": "백업 실패: {{error}}", + "localBackupCreated": "로컬 백업이 생성되었습니다", + "localBackupFailed": "로컬 백업 실패", + "restoreSuccess": "복원 성공, 1초 후 앱이 재시작됩니다", + "localBackupExported": "로컬 백업이 내보내졌습니다", + "localBackupExportFailed": "로컬 백업 내보내기 실패", + "confirmDelete": "이 백업 파일을 삭제하시겠습니까?", + "confirmRestore": "이 백업 파일을 복원하시겠습니까?" + }, + "table": { + "filename": "파일명", + "backupTime": "백업 시간", + "actions": "작업", + "noBackups": "사용 가능한 백업이 없습니다", + "rowsPerPage": "페이지당 행 수" + } + }, + "misc": { + "title": "기타", + "fields": { + "appLogLevel": "앱 로그 레벨", + "appLogMaxSize": "앱 로그 최대 크기", + "appLogMaxCount": "앱 로그 최대 개수", + "autoCloseConnections": "연결 자동 종료", + "autoCheckUpdate": "업데이트 자동 확인", + "enableBuiltinEnhanced": "내장 향상 기능 사용", + "proxyLayoutColumns": "프록시 레이아웃 열 수", + "autoLogClean": "로그 자동 정리", + "autoDelayDetection": "자동 지연 감지", + "defaultLatencyTest": "기본 지연 테스트", + "defaultLatencyTimeout": "기본 지연 제한시간" + }, + "tooltips": { + "autoCloseConnections": "프록시 그룹 선택 또는 프록시 모드 변경 시 기존 연결을 종료합니다", + "enableBuiltinEnhanced": "구성 파일에 대한 호환성 처리를 수행합니다", + "autoDelayDetection": "백그라운드에서 현재 노드의 지연을 주기적으로 검사합니다", + "defaultLatencyTest": "HTTP 클라이언트 요청 테스트에만 사용되며 구성 파일에는 영향을 주지 않습니다" + }, + "options": { + "proxyLayoutColumns": { + "auto": "자동" + }, + "autoLogClean": { + "never": "정리 안 함", + "retainDays": "{{n}}일 보관" + } + } + }, + "update": { + "title": "새 버전 v{{version}}", + "actions": { + "goToRelease": "릴리스 페이지로 이동", + "update": "업데이트" + }, + "messages": { + "portableError": "포터블 버전은 앱 내 업데이트를 지원하지 않습니다. 수동으로 다운로드하여 교체하세요", + "breakChangeError": "이 버전은 메이저 업데이트로 앱 내 업데이트를 지원하지 않습니다. 프로그램을 제거한 뒤 새 버전을 수동으로 설치하세요" + } + }, + "sysproxy": { + "title": "시스템 프록시 설정", + "fieldsets": { + "currentStatus": "현재 시스템 프록시" + }, + "fields": { + "enableStatus": "활성 상태:", + "serverAddr": "서버 주소: ", + "pacUrl": "PAC URL: ", + "proxyHost": "프록시 호스트", + "usePacMode": "PAC 모드 사용", + "proxyGuard": "프록시 가드", + "guardDuration": "가드 지속시간", + "alwaysUseDefaultBypass": "기본 우회 주소 항상 사용", + "proxyBypass": "프록시 우회 설정: ", + "bypass": "우회: ", + "pacScriptContent": "PAC 스크립트 내용" + }, + "tooltips": { + "proxyGuard": "다른 소프트웨어가 운영 체제의 프록시 설정을 변경하지 못하도록 방지합니다" + }, + "messages": { + "durationTooShort": "프록시 데몬 지속시간은 1초 미만일 수 없습니다", + "invalidBypass": "잘못된 우회 형식", + "invalidProxyHost": "잘못된 프록시 호스트 형식" + }, + "actions": { + "editPac": "PAC 편집" + } + }, + "tun": { + "title": "TUN 모드", + "fields": { + "stack": "스택", + "device": "장치 이름", + "autoRoute": "자동 라우팅", + "strictRoute": "엄격 라우팅", + "autoDetectInterface": "인터페이스 자동 감지", + "dnsHijack": "DNS 하이재킹", + "mtu": "MTU" + }, + "tooltips": { + "dnsHijack": "여러 DNS 서버는 쉼표(,)로 구분하세요" + }, + "messages": { + "applied": "설정이 적용되었습니다" + } + }, + "dns": { + "dialog": { + "title": "DNS 덮어쓰기", + "warning": "이 설정에 익숙하지 않다면 수정하지 말고 DNS 덮어쓰기를 활성화 상태로 유지하세요" + }, + "sections": { + "general": "DNS 설정", + "fallbackFilter": "폴백 필터 설정", + "hosts": "호스트 설정" + }, + "fields": { + "enable": "DNS 사용", + "listen": "DNS 리슨", + "enhancedMode": "향상 모드", + "fakeIpRange": "가짜 IP 범위", + "fakeIpFilterMode": "가짜 IP 필터 모드", + "ipv6": { + "label": "IPv6", + "description": "IPv6 DNS 해석 사용" + }, + "preferH3": { + "label": "H3 우선", + "description": "DNS DOH에서 HTTP/3 사용" + }, + "respectRules": { + "label": "규칙 준수", + "description": "DNS 연결이 라우팅 규칙을 따릅니다" + }, + "useHosts": { + "label": "Hosts 사용", + "description": "호스트 파일을 통해 해석하도록 활성화" + }, + "useSystemHosts": { + "label": "시스템 Hosts 사용", + "description": "시스템 호스트 파일을 통해 해석하도록 활성화" + }, + "directPolicy": { + "label": "직접 Nameserver 정책 따르기", + "description": "Nameserver 정책을 따를지 여부" + }, + "defaultNameserver": { + "label": "기본 Nameserver", + "description": "DNS 서버 해석에 사용되는 기본 DNS 서버" + }, + "nameserver": { + "label": "Nameserver", + "description": "DNS 서버 목록, 쉼표로 구분" + }, + "fallback": { + "label": "폴백", + "description": "폴백 DNS 서버 목록, 쉼표로 구분" + }, + "proxy": { + "label": "프록시 서버 Nameserver", + "description": "프록시 노드 도메인 해석용 DNS 서버" + }, + "directNameserver": { + "label": "직접 Nameserver", + "description": "직접 출구 도메인 해석용 DNS 서버, 'system' 키워드 지원, 쉼표로 구분" + }, + "fakeIpFilter": { + "label": "가짜 IP 필터", + "description": "가짜 IP 해석을 건너뛰는 도메인, 쉼표로 구분" + }, + "nameserverPolicy": { + "label": "Nameserver 정책", + "description": "도메인별 DNS 서버, 여러 서버는 세미콜론으로 구분, 형식: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP 필터링", + "description": "폴백에 GeoIP 필터링 사용" + }, + "geoipCode": "GeoIP 코드", + "fallbackIpCidr": { + "label": "폴백 IP CIDR", + "description": "폴백 서버를 사용하지 않는 IP CIDR, 쉼표로 구분" + }, + "fallbackDomain": { + "label": "폴백 도메인", + "description": "폴백 서버를 사용하는 도메인, 쉼표로 구분" + }, + "hosts": { + "label": "Hosts", + "description": "사용자 정의 도메인→IP 또는 도메인 매핑" + } + }, + "messages": { + "saved": "DNS 설정이 저장되었습니다", + "configError": "DNS 구성 오류:" + }, + "errors": { + "invalid": "잘못된 구성", + "invalidYaml": "잘못된 YAML 형식" + } + }, + "webUI": { + "actions": { + "openUrl": "URL 열기" + }, + "title": "Web UI", + "messages": { + "supportedPlaceholders": "지원되는 자리표시자: %host, %port, %secret", + "placeholderInstruction": "host, port, secret을 %host, %port, %secret로 바꿔 입력하세요" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "전역 단축키 사용" + }, + "title": "단축키 설정", + "functions": { + "rule": "규칙 모드", + "global": "전역 모드", + "openOrCloseDashboard": "대시보드 열기/닫기", + "toggleSystemProxy": "시스템 프록시 켜기/끄기", + "toggleTunMode": "TUN 모드 켜기/끄기", + "entryLightweightMode": "경량 모드 진입", + "direct": "직접 모드" + } + }, + "password": { + "prompts": { + "enterRoot": "루트 암호를 입력하세요" + } + }, + "networkInterface": { + "title": "네트워크 인터페이스", + "fields": { + "ipAddress": "IP 주소", + "macAddress": "MAC 주소" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clash 코어가 재시작되었습니다", + "versionUpdated": "코어 버전이 업데이트되었습니다", + "alreadyLatestVersion": "이미 최신 코어 버전을 사용 중입니다", + "changeSuccess": "코어 변경 성공", + "changeFailed": "코어 변경 실패", + "geoDataUpdated": "GeoData가 업데이트되었습니다" + }, + "clashService": { + "installSuccess": "서비스가 설치되었습니다", + "uninstallSuccess": "서비스가 제거되었습니다" + }, + "updater": { + "withClashProxySuccess": "Clash 프록시로 업데이트 성공", + "withClashProxyFailed": "Clash 프록시로도 업데이트 실패" + } + } + }, + "statuses": { + "clash": { + "stopping": "코어 중지 중...", + "restarting": "코어 재시작 중..." + }, + "clashService": { + "installing": "서비스 설치 중...", + "uninstalling": "서비스 제거 중..." + } + } +} diff --git a/src/locales/ko/shared.json b/src/locales/ko/shared.json new file mode 100644 index 000000000..ca8e69842 --- /dev/null +++ b/src/locales/ko/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "취소", + "close": "닫기", + "confirm": "확인", + "save": "저장", + "delete": "삭제", + "edit": "편집", + "new": "새로 만들기", + "enable": "활성화", + "upgrade": "업그레이드", + "restart": "재시작", + "resetToDefault": "기본값으로 재설정", + "refresh": "새로고침", + "retry": "재시도", + "refreshPage": "페이지 새로고침", + "showDetails": "세부정보 보기", + "hideDetails": "세부정보 숨기기", + "listView": "목록 보기", + "tableView": "테이블 보기", + "pause": "일시 정지", + "resume": "재개", + "closeAll": "모두 닫기", + "clear": "지우기" + }, + "labels": { + "updateAt": "업데이트 시간", + "timeout": "시간 초과", + "icon": "아이콘", + "name": "이름", + "readOnly": "읽기 전용", + "expireTime": "만료 시간", + "updateTime": "업데이트 시간", + "usedTotal": "사용됨 / 전체", + "from": "출처", + "password": "비밀번호", + "retryAttempts": "재시도 횟수", + "downloaded": "다운로드됨", + "uploaded": "업로드됨" + }, + "statuses": { + "enabled": "사용", + "disabled": "비활성화", + "saving": "저장 중...", + "empty": "비어있음" + }, + "units": { + "milliseconds": "밀리초", + "seconds": "초", + "minutes": "분", + "kilobytes": "KB", + "files": "파일" + }, + "placeholders": { + "filter": "필터 조건", + "matchCase": "대/소문자 구분", + "matchWholeWord": "단어 전체 일치", + "useRegex": "정규식 사용" + }, + "validation": { + "invalidRegex": "잘못된 정규식" + }, + "window": { + "maximize": "최대화", + "minimize": "최소화" + }, + "editorModes": { + "visualization": "시각화", + "advanced": "고급" + }, + "feedback": { + "errors": { + "trafficStats": "트래픽 통계 오류", + "trafficStatsDescription": "트래픽 통계 구성 요소에서 오류가 발생하여 충돌을 방지하기 위해 비활성화되었습니다." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "프로필 가져오기 성공", + "importSubscriptionSuccess": "구독 가져오기 성공", + "importWithClashProxy": "Clash 프록시로 프로필 가져오기", + "updateAvailable": "업데이트 가능", + "saved": "저장되었습니다", + "common": { + "copySuccess": "복사 성공", + "saveSuccess": "설정이 저장되었습니다", + "saveFailed": "설정 저장 실패" + } + }, + "validation": { + "config": { + "failed": "설정 검증 실패", + "bootFailed": "부팅 설정 검증 실패", + "coreChangeFailed": "코어 변경 설정 검증 실패", + "processTerminated": "설정 검증 프로세스 종료됨" + }, + "script": { + "syntaxError": "스크립트 구문 오류", + "missingMain": "스크립트 메인 없음", + "fileNotFound": "파일을 찾을 수 없음", + "fileError": "스크립트 파일 오류" + }, + "yaml": { + "syntaxError": "YAML 구문 오류", + "readError": "YAML 읽기 오류", + "mappingError": "YAML 매핑 오류", + "keyError": "YAML 키 오류", + "generalError": "YAML 오류" + }, + "merge": { + "syntaxError": "병합 파일 구문 오류", + "mappingError": "병합 파일 매핑 오류", + "keyError": "병합 파일 키 오류", + "generalError": "병합 파일 오류" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/ko/tests.json b/src/locales/ko/tests.json new file mode 100644 index 000000000..b4d5c8832 --- /dev/null +++ b/src/locales/ko/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "모두 테스트" + }, + "title": "테스트" + }, + "components": { + "item": { + "actions": { + "test": "테스트" + } + } + }, + "modals": { + "test": { + "title": { + "create": "테스트 생성", + "edit": "테스트 편집" + }, + "fields": { + "url": "테스트 URL" + } + } + }, + "statuses": { + "test": { + "pending": "대기 중", + "yes": "예", + "no": "아니오", + "failed": "실패", + "completed": "완료", + "disallowedIsp": "허용되지 않는 ISP", + "originalsOnly": "오리지널만", + "noDisney": "아니오 (Disney+에 의해 IP 차단)", + "unsupportedRegion": "지원되지 않는 국가/지역", + "failedNetwork": "실패 (네트워크 연결)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "테스트 중..." + }, + "empty": "잠금 해제 테스트 항목이 없습니다", + "messages": { + "detectionFailedWithName": "{{name}} 감지에 실패했습니다", + "detectionTimeout": "감지 시간 초과 또는 실패" + }, + "title": "잠금 해제 테스트" + } + } +} diff --git a/src/locales/ru.json b/src/locales/ru.json deleted file mode 100644 index a2ccac337..000000000 --- a/src/locales/ru.json +++ /dev/null @@ -1,603 +0,0 @@ -{ - "millis": "миллисекунды", - "seconds": "секунды", - "mins": "минуты", - "Back": "Назад", - "Close": "Закрыть", - "Cancel": "Отмена", - "Confirm": "Подтвердить", - "Maximize": "Развернуть", - "Minimize": "Свернуть", - "Format document": "Форматировать документ", - "Empty": "Пусто", - "New": "Новый", - "Edit": "Редактировать", - "Save": "Сохранить", - "Delete": "Удалить", - "Enable": "Включить", - "Disable": "Отключить", - "Label-Home": "Главная", - "Label-Proxies": "Прокси", - "Label-Profiles": "Профили", - "Label-Connections": "Соединения", - "Label-Rules": "Правила", - "Label-Logs": "Логи", - "Label-Unlock": "Тест", - "Label-Settings": "Настройки", - "Proxies": "Прокси", - "Proxy Groups": "Группы прокси", - "Proxy Provider": "Провайдер прокси", - "Update All": "Обновить все", - "Update At": "Обновлено в", - "rule": "правила", - "global": "глобальный", - "direct": "прямой", - "Chain Proxy": "🔗 Цепной прокси", - "Chain Proxy Config": "Конфигурация цепочки прокси", - "Click nodes in order to add to proxy chain": "Нажимайте узлы по порядку, чтобы добавить в цепочку прокси", - "No proxy chain configured": "Цепочка прокси не настроена", - "Proxy Order": "Порядок прокси", - "timeout": "Тайм-аут", - "Clear All": "Очистить всё", - "script": "скриптовый", - "locate": "Местоположение", - "Delay check": "Проверка задержки", - "Sort by default": "Сортировать по умолчанию", - "Sort by delay": "Сортировать по задержке", - "Sort by name": "Сортировать по названию", - "Delay check URL": "URL проверки задержки", - "Delay check to cancel fixed": "Проверка задержки для отмены фиксированного", - "Proxy basic": "Отображать меньше сведений о прокси", - "Proxy detail": "Отображать больше сведений о прокси", - "Profiles": "Профили", - "Update All Profiles": "Обновить все профили", - "View Runtime Config": "Просмотреть используемый конфиг", - "Reactivate Profiles": "Перезапустить профиль", - "Paste": "Вставить", - "Profile URL": "URL профиля", - "Import": "Импорт", - "From": "От", - "Update Time": "Время обновления", - "Used / Total": "Использовано / Всего", - "Expire Time": "Время окончания", - "Create Profile": "Создать профиль", - "Edit Profile": "Изменить профиль", - "Edit Proxies": "Редактировать прокси", - "Use newlines for multiple uri": "Используйте символы новой строки для нескольких URI (поддерживается кодировка Base64)", - "Edit Rules": "Редактировать правила", - "Rule Type": "Тип правила", - "Rule Content": "Содержимое правила", - "Proxy Policy": "Политика прокси", - "No Resolve": "Без разрешения", - "Prepend Rule": "Добавить правило в начало", - "Append Rule": "Добавить правило в конец", - "Prepend Group": "Добавить группу в начало", - "Append Group": "Добавить группу в конец", - "Prepend Proxy": "Добавить прокси в начало", - "Append Proxy": "Добавить прокси в конец", - "Rule Condition Required": "Требуется условие правила", - "Invalid Rule": "Недействительное правило", - "Advanced": "Дополнительно", - "Visualization": "Визуализация", - "DOMAIN": "Соответствует полному доменному имени", - "DOMAIN-SUFFIX": "Соответствует суффиксу домена", - "DOMAIN-KEYWORD": "Соответствует ключевому слову домена", - "DOMAIN-REGEX": "Соответствует домену с использованием регулярных выражений", - "GEOSITE": "Соответствует доменам в Geosite", - "GEOIP": "Соответствует коду страны IP-адреса", - "SRC-GEOIP": "Соответствует коду страны исходного IP-адреса", - "IP-ASN": "Соответствует ASN IP-адреса", - "SRC-IP-ASN": "Соответствует ASN исходного IP-адреса", - "IP-CIDR": "Соответствует диапазону IP-адресов", - "IP-CIDR6": "Соответствует диапазону IPv6-адресов", - "SRC-IP-CIDR": "Соответствует диапазону исходных IP-адресов", - "IP-SUFFIX": "Соответствует диапазону суффиксов IP-адресов", - "SRC-IP-SUFFIX": "Соответствует диапазону суффиксов исходных IP-адресов", - "SRC-PORT": "Соответствует диапазону исходных портов", - "DST-PORT": "Соответствует диапазону целевых портов", - "IN-PORT": "Соответствует входящему порту", - "DSCP": "Маркировка DSCP (только для tproxy UDP входящего)", - "PROCESS-NAME": "Соответствует имени процесса (имя пакета Android)", - "PROCESS-PATH": "Соответствует полному пути процесса", - "PROCESS-NAME-REGEX": "Соответствует имени процесса с использованием регулярных выражений (имя пакета Android)", - "PROCESS-PATH-REGEX": "Соответствует полному пути процесса с использованием регулярных выражений", - "NETWORK": "Соответствует транспортному протоколу (tcp/udp)", - "UID": "Соответствует USER ID в Linux", - "IN-TYPE": "Соответствует типу входящего соединения", - "IN-USER": "Соответствует имени пользователя входящего соединения", - "IN-NAME": "Соответствует имени входящего соединения", - "SUB-RULE": "Подправило", - "RULE-SET": "Соответствует набору правил", - "AND": "Логическое И", - "OR": "Логическое ИЛИ", - "NOT": "Логическое НЕ", - "MATCH": "Соответствует всем запросам", - "DIRECT": "Данные направляются напрямую наружу", - "REJECT": "Перехватывает запросы", - "REJECT-DROP": "Отклоняет запросы", - "PASS": "Пропускает это правило при совпадении", - "Edit Groups": "Редактировать группы прокси", - "Group Type": "Тип группы", - "select": "Выбор прокси вручную", - "url-test": "Выбор прокси на основе задержки теста URL", - "fallback": "Переключение на другой прокси при ошибке", - "load-balance": "Распределение прокси на основе балансировки нагрузки", - "relay": "Передача через определенную цепочку прокси", - "Group Name": "Имя группы", - "Use Proxies": "Использовать прокси", - "Use Provider": "Использовать провайдера", - "Health Check Url": "URL проверки здоровья", - "Expected Status": "Ожидаемый статус", - "Interval": "Интервал", - "Lazy": "Ленивый", - "Timeout": "Таймаут", - "Max Failed Times": "Максимальное количество неудач", - "Interface Name": "Имя интерфейса", - "Routing Mark": "Марка маршрутизации", - "Include All": "Включить все прокси и провайдеры", - "Include All Providers": "Включить всех провайдеров", - "Include All Proxies": "Включить все прокси", - "Exclude Filter": "Исключить фильтр", - "Exclude Type": "Тип исключения", - "Disable UDP": "Отключить UDP", - "Hidden": "Скрытый", - "Group Name Required": "Требуется имя группы", - "Group Name Already Exists": "Имя группы уже существует", - "Extend Config": "Изменить Merge", - "Extend Script": "Изменить Script", - "Global Merge": "Глобальный расширенный Настройки", - "Global Script": "Глобальный расширенный скрипт", - "Type": "Тип", - "Name": "Название", - "Descriptions": "Описание", - "Subscription URL": "URL подписки", - "Update Interval": "Интервал обновления", - "Choose File": "Выбрать файл", - "Use System Proxy": "Использовать системный прокси для обновления", - "Use Clash Proxy": "Использовать прокси Clash для обновления", - "Accept Invalid Certs (Danger)": "Принимать недействительные сертификаты (ОПАСНО)", - "Refresh": "Обновить", - "Home": "Главная", - "Select": "Выбрать", - "Edit Info": "Изменить информацию", - "Edit File": "Изменить файл", - "Open File": "Открыть файл", - "Update": "Обновить", - "Update(Proxy)": "Обновить (прокси)", - "Confirm deletion": "Подтвердите удаление", - "This operation is not reversible": "Эта операция необратима", - "Script Console": "Консоль скрипта", - "To Top": "Наверх", - "To End": "Вниз", - "Connections": "Соединения", - "Table View": "Отображать в виде таблицы", - "List View": "Отображать в виде списка", - "Close All": "Закрыть всё", - "Upload": "Загрузка", - "Download": "Скачивание", - "Download Speed": "Скорость скачивания", - "Upload Speed": "Скорость загрузки", - "Host": "Хост", - "Downloaded": "Скачано", - "Uploaded": "Загружено", - "DL Speed": "Скорость скачивания", - "UL Speed": "Скорость загрузки", - "Active Connections": "Активные соединения", - "Chains": "Цепочки", - "Rule": "Правило", - "Process": "Процесс", - "Time": "Время подключения", - "Source": "Исходный адрес", - "Destination": "IP-адрес назначения", - "DestinationPort": "Целевой порт", - "Close Connection": "Закрыть соединение", - "Rules": "Правила", - "Rule Provider": "Провайдеры правил", - "Logs": "Логи", - "Pause": "Пауза", - "Resume": "Возобновить", - "Clear": "Очистить", - "Test": "Тест", - "Test All": "Тестировать все", - "Testing...": "Тестирование ...", - "Create Test": "Создать тест", - "Edit Test": "Редактировать тест", - "Icon": "Иконка", - "Test URL": "URL проверка", - "Settings": "Настройки", - "System Setting": "Настройки системы", - "Tun Mode": "Режим TUN", - "TUN requires Service Mode": "Режим TUN требует установленную службу Clash Verge", - "Install Service": "Установить службу", - "Reset to Default": "Сбросить настройки", - "Tun Mode Info": "Режим Tun: захватывает весь системный трафик, при включении нет необходимости включать системный прокси-сервер.", - "System Proxy Enabled": "Системный прокси включен, ваши приложения будут получать доступ к сети через него", - "System Proxy Disabled": "Системный прокси отключен, большинству пользователей рекомендуется включить эту опцию", - "TUN Mode Enabled": "Режим TUN включен, приложения будут получать доступ к сети через виртуальную сетевую карту", - "TUN Mode Disabled": "Режим TUN отключен", - "TUN Mode Service Required": "Режим TUN требует установленную службу Clash Verge", - "TUN Mode Intercept Info": "Режим TUN может перехватить трафик всех приложений, подходит для приложений, которые не работают в режиме системного прокси.", - "Rule Mode Description": "Направляет трафик в соответствии с предустановленными правилами", - "Global Mode Description": "Направляет весь трафик через прокси-серверы", - "Direct Mode Description": "Весь трафик обходит прокси, но передается ядром Clash для целевых серверов, подходит для конкретных сценариев, требующих распределения трафика ядра", - "Stack": "Стек", - "System and Mixed Can Only be Used in Service Mode": "Стэк System и Mixed могут использоваться только в режиме системной службы", - "Device": "Имя устройства", - "Auto Route": "Автоматическая маршрутизация", - "Strict Route": "Строгая маршрутизация", - "Auto Detect Interface": "Автоопределение интерфейса", - "DNS Hijack": "DNS-перехват", - "MTU": "MTU", - "Service Mode": "Режим системной службы", - "Service Mode Info": "Установите режим системной службы перед включением режима TUN. Процесс ядра, запущенный службой, может получить разрешение на установку виртуальной сетевой карты (режим TUN).", - "Current State": "Текущее состояние", - "pending": "Ожидающий", - "installed": "Установленный", - "uninstall": "Не установленный", - "active": "Активированный", - "unknown": "неизвестный", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "Информация: Пожалуйста, убедитесь, что сервис Clash Verge Service установлен и включен", - "Install": "Установить", - "Uninstall": "Удалить", - "Disable Service Mode": "Отключить режим системной службы", - "System Proxy": "Системный прокси", - "System Proxy Info": "Разрешить изменение настроек прокси-сервера операционной системы. Если разрешение не удастся, измените настройки прокси-сервера операционной системы вручную", - "System Proxy Setting": "Настройка системного прокси", - "Current System Proxy": "Текущий системный прокси", - "Enable status": "Статус включения", - "Enabled": "Включено", - "Disabled": "Отключено", - "Server Addr": "Адрес сервера: ", - "Proxy Host": "Хост прокси", - "Invalid Proxy Host Format": "Неверный формат хоста прокси", - "Not available": "Недоступно", - "Proxy Guard": "Proxy Guard", - "Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО", - "Guard Duration": "Период защиты", - "Always use Default Bypass": "Всегда использовать стандартное обходное решение", - "Use Bypass Check": "Используйте проверку обхода", - "Proxy Bypass": "Игнорируемые адреса: ", - "Bypass": "Игнорируемые адреса: ", - "Use PAC Mode": "Используйте режим PAC", - "PAC Script Content": "Содержание сценария PAC", - "PAC URL": "Адрес PAC: ", - "Auto Launch": "Автозапуск", - "Silent Start": "Тихий запуск", - "Silent Start Info": "Запускать программу в фоновом режиме без отображения панели", - "TG Channel": "Telegram-канал", - "Manual": "Документация", - "Github Repo": "GitHub репозиторий", - "Clash Setting": "Настройки Clash", - "Allow Lan": "Разрешить доступ из локальной сети", - "Network Interface": "Сетевой интерфейс", - "Ip Address": "IP адрес", - "Mac Address": "MAC адрес", - "IPv6": "IPv6", - "Unified Delay": "Точная задержка", - "Unified Delay Info": "Когда унифицированная(точная) задержка включена, будут выполнены два теста задержки, чтобы устранить различия в задержке между разными типами узлов, вызванные подтверждением соединения и т. д", - "Log Level": "Уровень логов", - "Log Level Info": "Это действует только на файлы журнала ядра в служебном файле в каталоге журналов.", - "Port Config": "Настройка порта", - "Random Port": "Случайный порт", - "Mixed Port": "Смешанный прокси-порт", - "Socks Port": "Порт Socks-прокси", - "Http Port": "Порт Http(s)-прокси", - "Redir Port": "Порт прозрачного прокси Redir", - "Tproxy Port": "Порт прозрачного прокси Tproxy", - "External": "Внешний контроллер", - "External Controller": "Адрес прослушивания внешнего контроллера", - "Core Secret": "Секрет", - "Recommended": "Рекомендуется", - "Open URL": "Перейти по адресу", - "Replace host, port, secret with %host, %port, %secret": "Замените хост, порт и секрет на %host, %port, %secret", - "Support %host, %port, %secret": "Поддерживаются %host, %port, %secret", - "Clash Core": "Ядро Clash", - "Upgrade": "Обновить", - "Restart": "Перезапустить", - "Release Version": "Официальная версия", - "Alpha Version": "Альфа-версия", - "Please Enable Service Mode": "Пожалуйста, сначала установите и включите режим системной службы", - "Please enter your root password": "Пожалуйста, введите ваш пароль root", - "Grant": "Предоставить", - "Open UWP tool": "Открыть UWP инструмент", - "Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение", - "Update GeoData": "Обновить GeoData", - "Verge Basic Setting": "Основные настройки Verge", - "Verge Advanced Setting": "Расширенные настройки Verge", - "Language": "Язык", - "Theme Mode": "Цветовая тема", - "theme.light": "Светлая", - "theme.dark": "Тёмная", - "theme.system": "Системная", - "Tray Click Event": "Событие при щелчке по иконке в трее", - "Show Main Window": "Показать главное окно", - "Show Tray Menu": "Показать меню в трее", - "Copy Env Type": "Скопировать тип Env", - "Copy Success": "Скопировано", - "Start Page": "Главная страница", - "Startup Script": "Скрипт запуска", - "Browse": "Просмотреть", - "Theme Setting": "Настройки темы", - "Primary Color": "Основной цвет", - "Secondary Color": "Вторичный цвет", - "Primary Text": "Первичный текст", - "Secondary Text": "Вторичный текст", - "Info Color": "Информационный цвет", - "Warning Color": "Цвет предупреждения", - "Error Color": "Цвет ошибки", - "Success Color": "Цвет успеха", - "Font Family": "Семейство шрифтов", - "CSS Injection": "Внедрение CSS", - "Layout Setting": "Настройки раскладки", - "Traffic Graph": "График трафика", - "Memory Usage": "Использование памяти", - "Memory Cleanup": "Нажмите, чтобы очистить память", - "Proxy Group Icon": "Иконка Группы прокси", - "Nav Icon": "Иконки навигации", - "Monochrome": "Монохромные", - "Colorful": "Цветные", - "Tray Icon": "Иконка в трее", - "Common Tray Icon": "Общий значок в трее", - "System Proxy Tray Icon": "Значок системного прокси в трее", - "Tun Tray Icon": "Значок TUN в трее", - "Miscellaneous": "Расширенные настройки", - "App Log Level": "Уровень журнала приложения", - "Auto Close Connections": "Автоматическое закрытие соединений", - "Auto Close Connections Info": "Закрыть установленные соединения при изменении выбора группы прокси или режима прокси", - "Auto Check Update": "Автоматическая проверка обновлений", - "Enable Builtin Enhanced": "Включить встроенные улучшения", - "Enable Builtin Enhanced Info": "Обработка совместимости для файла конфигурации", - "Proxy Layout Columns": "Количество столбцов в макете прокси", - "Auto Columns": "Авто колонки", - "Auto Log Clean": "Автоматическая очистка логов", - "Never Clean": "Никогда не очищать", - "Retain _n Days": "Сохранять {{n}} дней", - "Auto Delay Detection": "Автоматическое измерение задержки", - "Auto Delay Detection Info": "Периодически проверяет задержку текущего узла в фоновом режиме", - "Default Latency Test": "Ссылка на тест задержки", - "Default Latency Test Info": "Используется только для тестирования HTTP-запросов клиента и не влияет на файл конфигурации", - "Default Latency Timeout": "Таймаут задержки по умолчанию", - "Hotkey Setting": "Настройки сочетаний клавиш", - "Enable Global Hotkey": "Включить глобальную горячую клавишу", - "open_or_close_dashboard": "Открыть/Закрыть панель управления", - "clash_mode_rule": "Режим правил", - "clash_mode_global": "Глобальный режим", - "clash_mode_direct": "Прямой режим", - "toggle_system_proxy": "Включить/Отключить системный прокси", - "toggle_tun_mode": "Включить/Отключить режим TUN", - "entry_lightweight_mode": "Вход в LightWeight Mode", - "Backup Setting": "Настройки резервного копирования", - "Backup Setting Info": "Поддерживает файлы конфигурации резервного копирования WebDAV", - "Runtime Config": "Используемый конфиг", - "Open Conf Dir": "Открыть папку приложения", - "Open Conf Dir Info": "Если программное обеспечение работает неправильно, сделайте резервную копию и удалите все файлы в этой папке, а затем перезапустите ПО", - "Open Core Dir": "Открыть папку ядра", - "Open Logs Dir": "Открыть папку логов", - "Check for Updates": "Проверить обновления", - "Go to Release Page": "Перейти на страницу релизов", - "Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените файлы вручную", - "Break Change Update Error": "Это крупное обновление, которое не поддерживает обновление внутри приложения. Пожалуйста, удалите его и загрузите установочный файл вручную.", - "Open Dev Tools": "Открыть Dev Tools", - "Export Diagnostic Info": "Экспорт диагностической информации", - "Export Diagnostic Info For Issue Reporting": "Экспорт диагностической информации для отчета об ошибке", - "Exit": "Выход", - "Verge Version": "Версия Clash Verge Rev", - "ReadOnly": "Только для чтения", - "ReadOnlyMessage": "Невозможно редактировать в режиме только для чтения", - "Filter": "Фильтр", - "Filter conditions": "Условия фильтрации", - "Match Case": "Учитывать регистр", - "Match Whole Word": "Полное совпадение слова", - "Use Regular Expression": "Использовать регулярные выражения", - "Profile Imported Successfully": "Профиль успешно импортирован", - "Profile Switched": "Профиль изменен", - "Profile Reactivated": "Профиль перезапущен", - "Only YAML Files Supported": "Поддерживаются только файлы YAML", - "Settings Applied": "Настройки применены", - "Installing Service...": "Установка службы...", - "Service Installed Successfully": "Служба успешно установлена", - "Service Uninstalled Successfully": "Служба успешно удалена", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Продолжительность работы прокси-демона не может быть меньше 1 секунды", - "Invalid Bypass Format": "Неверный формат обхода", - "Clash Port Modified": "Порт Clash изменен", - "Port Conflict": "Конфликт портов", - "Restart Application to Apply Modifications": "Чтобы изменения вступили в силу, необходимо перезапустить приложение", - "External Controller Address Modified": "Настройки внешнего контроллера изменены", - "Permissions Granted Successfully for _clash Core": "Разрешения успешно предоставлены для ядра {{core}}", - "Core Version Updated": "Ядро обновлено до последней версии", - "Clash Core Restarted": "Ядро перезапущено", - "GeoData Updated": "Файлы GeoData обновлены", - "Currently on the Latest Version": "Обновление не требуется", - "Import Subscription Successful": "Подписка успешно импортирована", - "WebDAV Server URL": "URL-адрес сервера WebDAV http(s)://", - "Username": "Имя пользователя", - "Password": "Пароль", - "Backup": "Резервное копирование", - "Filename": "Имя файла", - "Actions": "Действия", - "Restore": "Восстановить", - "No Backups": "Нет доступных резервных копий", - "WebDAV URL Required": "URL-адрес WebDAV не может быть пустым", - "Invalid WebDAV URL": "Неверный формат URL-адреса WebDAV", - "Username Required": "Имя пользователя не может быть пустым", - "Password Required": "Пароль не может быть пустым", - "Failed to Fetch Backups": "Не удалось получить файлы резервных копий", - "WebDAV Config Saved": "Конфигурация WebDAV успешно сохранена", - "WebDAV Config Save Failed": "Не удалось сохранить конфигурацию WebDAV: {{error}}", - "Backup Created": "Резервная копия успешно создана", - "Backup Failed": "Ошибка резервного копирования: {{error}}", - "Delete Backup": "Удалить резервную копию", - "Restore Backup": "Восстановить резервную копию", - "Backup Time": "Время резервного копирования", - "Confirm to delete this backup file?": "Вы уверены, что хотите удалить этот файл резервной копии?", - "Confirm to restore this backup file?": "Вы уверены, что хотите восстановить этот файл резервной копии?", - "Restore Success, App will restart in 1s": "Восстановление успешно выполнено, приложение перезапустится через 1 секунду", - "Failed to fetch backup files": "Не удалось получить файлы резервных копий", - "Profile": "Профиль", - "Help": "Помощь", - "About": "О программе", - "Theme": "Тема", - "Main Window": "Главное окно", - "Group Icon": "Иконка группы", - "Menu Icon": "Иконка меню", - "PAC File": "PAC файл", - "Web UI": "Веб-интерфейс", - "Hotkeys": "Горячие клавиши", - "Verge Mixed Port": "Mixed порт", - "Verge Socks Port": "Порт Socks", - "Verge Redir Port": "Порт Redir", - "Verge Tproxy Port": "Порт Tproxy", - "Verge Port": "Порт Verge", - "Verge HTTP Enabled": "HTTP включен", - "WebDAV URL": "URL WebDAV", - "WebDAV Username": "Имя пользователя WebDAV", - "WebDAV Password": "Пароль WebDAV", - "Dashboard": "Панель управления", - "Restart App": "Перезапустить приложение", - "Restart Clash Core": "Перезапустить ядро Clash", - "TUN Mode": "Режим TUN", - "Copy Env": "Копировать переменные окружения", - "Conf Dir": "Директория конфигурации", - "Core Dir": "Директория ядра", - "Logs Dir": "Директория логов", - "Open Dir": "Открыть директорию", - "More": "Ещё", - "Rule Mode": "Режим правил", - "Global Mode": "Глобальный режим", - "Direct Mode": "Прямой режим", - "Enable Tray Speed": "Показывать скорость в трее", - "Enable Tray Icon": "Показывать значок в трее", - "LightWeight Mode": "LightWeight Mode", - "LightWeight Mode Info": "Режим, в котором работает только ядро Clash, а графический интрефейс закрыт", - "LightWeight Mode Settings": "Настройки LightWeight Mode", - "Enter LightWeight Mode Now": "Войти в LightWeight Mode", - "Auto Enter LightWeight Mode": "Автоматический вход в LightWeight Mode", - "Auto Enter LightWeight Mode Info": "Автоматически включать LightWeight Mode, если окно закрыто определенное время", - "Auto Enter LightWeight Mode Delay": "Задержка включения LightWeight Mode", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "При закрытии окна LightWeight Mode будет автоматически активирован через {{n}} минут", - "Config Validation Failed": "Ошибка проверки конфигурации подписки, проверьте файл конфигурации, изменения отменены, ошибка:", - "Boot Config Validation Failed": "Ошибка проверки конфигурации при запуске, используется конфигурация по умолчанию, проверьте файл конфигурации, ошибка:", - "Core Change Config Validation Failed": "Ошибка проверки конфигурации при смене ядра, используется конфигурация по умолчанию, проверьте файл конфигурации, ошибка:", - "Config Validation Process Terminated": "Процесс проверки прерван", - "Script Syntax Error": "Ошибка синтаксиса скрипта, изменения отменены", - "Script Missing Main": "Ошибка скрипта, изменения отменены", - "File Not Found": "Файл не найден, изменения отменены", - "Script File Error": "Ошибка файла скрипта, изменения отменены", - "Core Changed Successfully": "Ядро успешно изменено", - "Failed to Change Core": "Не удалось сменить ядро", - "YAML Syntax Error": "Ошибка синтаксиса YAML, откат изменений", - "YAML Read Error": "Ошибка чтения YAML, откат изменений", - "YAML Mapping Error": "Ошибка YAML Mapping, откат изменений", - "YAML Key Error": "Ошибка ключа YAML, откат изменений", - "YAML Error": "Ошибка YAML, откат изменений", - "Merge File Syntax Error": "Ошибка синтаксиса Merge File, откат изменений", - "Merge File Mapping Error": "Ошибка сопоставления в Merge File, откат изменений", - "Merge File Key Error": "Ошибка ключа в Merge File, откат изменений", - "Merge File Error": "Ошибка Merge File, откат изменений", - "Validate YAML File": "Проверить YAML файл", - "Validate Merge File": "Проверить Merge File", - "Validation Success": "Файл успешно проверен", - "Validation Failed": "Проверка не удалась", - "Service Administrator Prompt": "Clash Verge требует прав администратора для переустановки системной службы", - "DNS Settings": "Настройки DNS", - "DNS Overwrite": "Переопределение настроек DNS", - "DNS Settings Warning": "Если вы не знакомы с этими настройками, пожалуйста, не изменяйте и не отключайте их", - "Enable DNS": "Включить DNS", - "DNS Listen": "Прослушивание DNS", - "Enhanced Mode": "Enhanced Mode", - "Fake IP Range": "Диапазон FakeIP", - "Fake IP Filter Mode": "FakeIP Filter Mode", - "Prefer H3": "Предпочитать H3", - "DNS DOH使用HTTP/3": "DNS DOH использует http/3", - "Respect Rules": "Приоритизировать правила", - "DNS connections follow routing rules": "Соединения DNS следуют правилам маршрутизации", - "Use Hosts": "Использовать файл Hosts", - "Enable to resolve hosts through hosts file": "Включить разрешение хостов через файл Hosts", - "Use System Hosts": "Использовать системный файл Hosts", - "Enable to resolve hosts through system hosts file": "Включить разрешение хостов через системный файл Hosts", - "Direct Nameserver Follow Policy": "Прямой сервер имен следует политике", - "Whether to follow nameserver policy": "Следовать ли политике DNS-серверов", - "Default Nameserver": "DNS-сервер по умолчанию", - "Default DNS servers used to resolve DNS servers": "DNS-серверы по умолчанию, используемые для разрешения адресов серверов DNS", - "Nameserver": "DNS-сервер", - "List of DNS servers": "Список DNS-серверов, разделенных запятой", - "Fallback": "Fallback", - "List of fallback DNS servers": "Список резервных DNS-серверов, разделенных запятой", - "Proxy Server Nameserver": "Proxy Server Nameserver", - "Proxy Node Nameserver": "DNS-серверы для разрешения домена прокси-узлов", - "Direct Nameserver": "DNS-сервер для прямых соединений", - "Direct outbound Nameserver": "Список DNS-серверов для прямых соединений, разделенных запятой", - "Fake IP Filter": "Фильтр FakeIP", - "Domains that skip fake IP resolution": "Домены, которые пропускают разрешение FakeIP, разделенные запятой", - "Nameserver Policy": "Политика серверов имен", - "Domain-specific DNS server": "DNS-сервер, специфичный для домена, несколько серверов разделяются знаком ';'", - "Fallback Filter Settings": "Настройки фильтра Fallback", - "GeoIP Filtering": "Фильтрация GeoIP", - "Enable GeoIP filtering for fallback": "Включить фильтрацию GeoIP", - "GeoIP Code": "Код GeoIP", - "Fallback IP CIDR": "Fallback IP CIDR", - "IP CIDRs not using fallback servers": "Диапазоны IP-адресов, не использующие резервные серверы, разделенные запятой", - "Fallback Domain": "Fallback домены", - "Domains using fallback servers": "Домены, использующие резервные серверы, разделенные запятой", - "Enable Alpha Channel": "Включить альфа-канал", - "Alpha versions may contain experimental features and bugs": "Альфа-версии могут содержать экспериментальные функции и ошибки", - "Home Settings": "Настройки главной страницы", - "Profile Card": "Карточка профиля", - "Current Proxy Card": "Карточка текущего прокси", - "Network Settings Card": "Карточка настроек сети", - "Proxy Mode Card": "Карточка режима работы", - "Clash Mode Card": "Карточка режима Clash", - "Traffic Stats Card": "Карточка статистики по трафику", - "Clash Info Cards": "Информация о Clash", - "System Info Cards": "Информация о системе", - "Website Tests Card": "Карточка тестов доступности веб-сайтов", - "Traffic Stats": "Статистика по трафику", - "Website Tests": "Проверка доступности веб-сайтов", - "Clash Info": "Информация о Clash", - "Core Version": "Версия ядра", - "System Proxy Address": "Адрес системного прокси", - "Uptime": "Время работы", - "Rules Count": "Количество правил", - "System Info": "Информация о системе", - "OS Info": "Версия ОС", - "Running Mode": "Режим работы", - "Sidecar Mode": "Пользовательский режим", - "Last Check Update": "Последняя проверка обновлений", - "Click to import subscription": "Нажмите, чтобы импортировать подписку", - "Update subscription successfully": "Подписка успешно обновлена", - "Current Node": "Текущий сервер", - "No active proxy node": "Нет активного прокси-узла", - "Network Settings": "Настройки сети", - "Proxy Mode": "Режим работы", - "Group": "Группа", - "Proxy": "Прокси", - "IP Information Card": "Информация об IP", - "IP Information": "Информация об IP", - "Failed to get IP info": "Не удалось получить информацию об IP", - "ISP": "ISP", - "ASN": "ASN", - "ORG": "ORG", - "Location": "Location", - "Timezone": "Timezone", - "Auto refresh": "Автоматическое обновление через", - "Unlock Test": "Тест доступности веб-сайтов", - "Pending": "В ожидании", - "Yes": "Да", - "No": "Нет", - "Failed": "Ошибка", - "Completed": "Завершено", - "Disallowed ISP": "ISP заблокирован", - "Originals Only": "Только Originals", - "No (IP Banned By Disney+)": "Нет (IP забанен Disney+)", - "Unsupported Country/Region": "Страна/регион не поддерживается", - "Failed (Network Connection)": "Ошибка подключения", - "Invalid Profile URL": "Недопустимая ссылка на профиль, введите адрес, начинающийся с http:// или https://", - "Batch Operations": "Пакетные операции", - "Delete Selected Profiles": "Удалить выбранные профили", - "Deselect All": "Отменить выбор всех", - "Done": "Готово", - "items": "элементы", - "Select All": "Выбрать все", - "Selected": "Выбрано", - "Selected profiles deleted successfully": "Выбранные профили успешно удалены" -} diff --git a/src/locales/ru/connections.json b/src/locales/ru/connections.json new file mode 100644 index 000000000..09d0caf92 --- /dev/null +++ b/src/locales/ru/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Соединения" + }, + "components": { + "fields": { + "host": "Хост", + "dlSpeed": "Скорость скачивания", + "ulSpeed": "Скорость загрузки", + "chains": "Цепочки", + "rule": "Правило", + "process": "Процесс", + "time": "Время подключения", + "source": "Исходный адрес", + "destination": "IP-адрес назначения", + "destinationPort": "Целевой порт", + "type": "Тип" + }, + "order": { + "default": "Default", + "uploadSpeed": "Скорость загрузки", + "downloadSpeed": "Скорость скачивания" + }, + "actions": { + "closeConnection": "Закрыть соединение" + } + } +} diff --git a/src/locales/ru/home.json b/src/locales/ru/home.json new file mode 100644 index 000000000..064192974 --- /dev/null +++ b/src/locales/ru/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "LightWeight Mode", + "manual": "Документация", + "settings": "Настройки главной страницы" + }, + "cards": { + "trafficStats": "Статистика по трафику", + "networkSettings": "Настройки сети", + "proxyMode": "Режим работы" + }, + "settings": { + "cards": { + "profile": "Карточка профиля", + "currentProxy": "Карточка текущего прокси", + "network": "Карточка настроек сети", + "proxyMode": "Карточка режима работы", + "traffic": "Карточка статистики по трафику", + "tests": "Карточка тестов доступности веб-сайтов", + "ip": "Информация об IP", + "clashInfo": "Информация о Clash", + "systemInfo": "Информация о системе" + }, + "title": "Настройки главной страницы" + }, + "title": "Главная" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "Системный прокси включен, ваши приложения будут получать доступ к сети через него", + "systemProxyDisabled": "Системный прокси отключен, большинству пользователей рекомендуется включить эту опцию", + "tunModeServiceRequired": "Режим TUN требует установленную службу Clash Verge", + "tunModeEnabled": "Режим TUN включен, приложения будут получать доступ к сети через виртуальную сетевую карту", + "tunModeDisabled": "Режим TUN отключен" + }, + "tooltips": { + "systemProxy": "Разрешить изменение настроек прокси-сервера операционной системы. Если разрешение не удастся, измените настройки прокси-сервера операционной системы вручную", + "tunMode": "Режим TUN может перехватить трафик всех приложений, подходит для приложений, которые не работают в режиме системного прокси." + } + }, + "clashInfo": { + "title": "Информация о Clash", + "fields": { + "coreVersion": "Версия ядра", + "systemProxyAddress": "Адрес системного прокси", + "mixedPort": "Mixed Port", + "uptime": "Время работы", + "rulesCount": "Количество правил" + } + }, + "systemInfo": { + "title": "Информация о системе", + "fields": { + "osInfo": "Версия ОС", + "autoLaunch": "Автозапуск", + "runningMode": "Режим работы", + "lastCheckUpdate": "Последняя проверка обновлений", + "vergeVersion": "Версия Clash Verge Rev" + }, + "actions": { + "settings": "Настройки" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "Режим системной службы", + "sidecarMode": "Пользовательский режим", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "Информация об IP", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Автоматическое обновление через", + "unknown": "Unknown" + }, + "errors": { + "load": "Не удалось получить данные IP" + } + }, + "currentProxy": { + "title": "Текущий сервер", + "actions": { + "refreshDelay": "Проверка задержки" + }, + "labels": { + "globalMode": "Глобальный режим", + "directMode": "Прямой режим", + "group": "Группа", + "proxy": "Прокси", + "noActiveNode": "Нет активного прокси-узла" + } + }, + "tests": { + "title": "Проверка доступности веб-сайтов" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Скорость загрузки", + "downloadSpeed": "Скорость скачивания", + "activeConnections": "Активные соединения", + "memoryUsage": "Использование памяти" + }, + "legends": { + "upload": "Загрузка", + "download": "Скачивание" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Режим правил", + "global": "Глобальный режим", + "direct": "Прямой режим" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/ru/index.ts b/src/locales/ru/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/ru/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/ru/layout.json b/src/locales/ru/layout.json new file mode 100644 index 000000000..ed99badae --- /dev/null +++ b/src/locales/ru/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Главная", + "proxies": "Прокси", + "profiles": "Профили", + "connections": "Соединения", + "rules": "Правила", + "logs": "Логи", + "unlock": "Тест", + "settings": "Настройки" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/ru/logs.json b/src/locales/ru/logs.json new file mode 100644 index 000000000..523666c1c --- /dev/null +++ b/src/locales/ru/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Логи" + } +} diff --git a/src/locales/ru/profiles.json b/src/locales/ru/profiles.json new file mode 100644 index 000000000..85c104a11 --- /dev/null +++ b/src/locales/ru/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Обновить все профили", + "viewRuntimeConfig": "Просмотреть используемый конфиг", + "reactivate": "Перезапустить профиль", + "import": "Импорт" + }, + "batch": { + "actions": { + "delete": "Удалить выбранные профили", + "selectAll": "Выбрать все", + "deselectAll": "Отменить выбор всех", + "done": "Готово" + }, + "summary": { + "selected": "Выбрано", + "items": "элементы" + }, + "title": "Пакетные операции" + }, + "importForm": { + "placeholder": "URL профиля", + "actions": { + "paste": "Вставить" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Недопустимая ссылка на профиль, введите адрес, начинающийся с http:// или https://", + "onlyYaml": "Поддерживаются только файлы YAML" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Профиль изменен", + "profileReactivated": "Профиль перезапущен", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Выбранные профили успешно удалены" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Профили" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Нажмите, чтобы импортировать подписку" + } + }, + "fileInput": { + "chooseFile": "Выбрать файл" + }, + "menu": { + "home": "Главная", + "select": "Выбрать", + "editInfo": "Изменить информацию", + "editFile": "Изменить файл", + "editRules": "Редактировать правила", + "editProxies": "Редактировать прокси", + "editGroups": "Редактировать группы прокси", + "extendConfig": "Изменить Merge", + "extendScript": "Изменить Script", + "openFile": "Открыть файл", + "update": "Обновить", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Создать профиль", + "edit": "Изменить профиль" + }, + "fields": { + "type": "Тип", + "description": "Описание", + "subscriptionUrl": "URL подписки", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Интервал обновления", + "useSystemProxy": "Использовать системный прокси для обновления", + "useClashProxy": "Использовать прокси Clash для обновления", + "acceptInvalidCerts": "Принимать недействительные сертификаты (ОПАСНО)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "Редактировать прокси", + "placeholders": { + "multiUri": "Используйте символы новой строки для нескольких URI (поддерживается кодировка Base64)" + }, + "actions": { + "prepend": "Добавить прокси в начало", + "append": "Добавить прокси в конец" + } + }, + "groupsEditor": { + "title": "Редактировать группы прокси", + "errors": { + "nameRequired": "Требуется имя группы", + "nameExists": "Имя группы уже существует" + }, + "fields": { + "type": "Тип группы", + "name": "Имя группы", + "icon": "Иконка Группы прокси", + "proxies": "Использовать прокси", + "provider": "Использовать провайдера", + "healthCheckUrl": "URL проверки здоровья", + "expectedStatus": "Ожидаемый статус", + "interval": "Интервал", + "maxFailedTimes": "Максимальное количество неудач", + "interfaceName": "Имя интерфейса", + "routingMark": "Марка маршрутизации", + "filter": "Фильтр", + "excludeFilter": "Исключить фильтр", + "excludeType": "Тип исключения", + "includeAll": "Включить все прокси и провайдеры", + "includeAllProxies": "Включить все прокси", + "includeAllProviders": "Включить всех провайдеров" + }, + "toggles": { + "lazy": "Ленивый", + "disableUdp": "Отключить UDP", + "hidden": "Скрытый" + }, + "actions": { + "prepend": "Добавить группу в начало", + "append": "Добавить группу в конец" + } + }, + "editor": { + "actions": { + "format": "Форматировать документ" + }, + "messages": { + "readOnly": "Невозможно редактировать в режиме только для чтения" + } + }, + "confirmDelete": { + "title": "Подтвердите удаление", + "message": "Эта операция необратима" + }, + "logViewer": { + "title": "Консоль скрипта" + } + } +} diff --git a/src/locales/ru/proxies.json b/src/locales/ru/proxies.json new file mode 100644 index 000000000..fca9ccf26 --- /dev/null +++ b/src/locales/ru/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Цепной прокси", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Провайдер прокси", + "actions": { + "updateAll": "Обновить все", + "update": "Обновить" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "Проверка задержки для отмены фиксированного" + }, + "tooltips": { + "locate": "Местоположение", + "delayCheck": "Проверка задержки", + "sortDefault": "Сортировать по умолчанию", + "sortDelay": "Сортировать по задержке", + "sortName": "Сортировать по названию", + "delayCheckUrl": "URL проверки задержки", + "showBasic": "Отображать меньше сведений о прокси", + "showDetail": "Отображать больше сведений о прокси", + "filter": "Фильтр" + }, + "placeholders": { + "delayCheckUrl": "URL проверки задержки" + }, + "chain": { + "header": "Конфигурация цепочки прокси", + "empty": "Цепочка прокси не настроена", + "instruction": "Нажимайте узлы по порядку, чтобы добавить в цепочку прокси", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Прямой режим" + }, + "title": { + "default": "Группы прокси", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Выбор прокси вручную", + "url-test": "Выбор прокси на основе задержки теста URL", + "fallback": "Переключение на другой прокси при ошибке", + "load-balance": "Распределение прокси на основе балансировки нагрузки", + "relay": "Передача через определенную цепочку прокси" + }, + "policies": { + "DIRECT": "Данные направляются напрямую наружу", + "REJECT": "Перехватывает запросы", + "REJECT-DROP": "Отклоняет запросы", + "PASS": "Пропускает это правило при совпадении" + } + } + } +} diff --git a/src/locales/ru/rules.json b/src/locales/ru/rules.json new file mode 100644 index 000000000..71b85ee0d --- /dev/null +++ b/src/locales/ru/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Провайдеры правил", + "dialogTitle": "Провайдеры правил", + "actions": { + "updateAll": "Обновить все", + "update": "Обновить" + } + }, + "title": "Правила" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Тип правила", + "content": "Содержимое правила", + "proxyPolicy": "Политика прокси" + }, + "toggles": { + "noResolve": "Без разрешения" + }, + "actions": { + "prependRule": "Добавить правило в начало", + "appendRule": "Добавить правило в конец" + }, + "validation": { + "conditionRequired": "Требуется условие правила", + "invalidRule": "Недействительное правило" + } + }, + "ruleTypes": { + "DOMAIN": "Соответствует полному доменному имени", + "DOMAIN-SUFFIX": "Соответствует суффиксу домена", + "DOMAIN-KEYWORD": "Соответствует ключевому слову домена", + "DOMAIN-REGEX": "Соответствует домену с использованием регулярных выражений", + "GEOSITE": "Соответствует доменам в Geosite", + "GEOIP": "Соответствует коду страны IP-адреса", + "SRC-GEOIP": "Соответствует коду страны исходного IP-адреса", + "IP-ASN": "Соответствует ASN IP-адреса", + "SRC-IP-ASN": "Соответствует ASN исходного IP-адреса", + "IP-CIDR": "Соответствует диапазону IP-адресов", + "IP-CIDR6": "Соответствует диапазону IPv6-адресов", + "SRC-IP-CIDR": "Соответствует диапазону исходных IP-адресов", + "IP-SUFFIX": "Соответствует диапазону суффиксов IP-адресов", + "SRC-IP-SUFFIX": "Соответствует диапазону суффиксов исходных IP-адресов", + "SRC-PORT": "Соответствует диапазону исходных портов", + "DST-PORT": "Соответствует диапазону целевых портов", + "IN-PORT": "Соответствует входящему порту", + "DSCP": "Маркировка DSCP (только для tproxy UDP входящего)", + "PROCESS-NAME": "Соответствует имени процесса (имя пакета Android)", + "PROCESS-PATH": "Соответствует полному пути процесса", + "PROCESS-NAME-REGEX": "Соответствует имени процесса с использованием регулярных выражений (имя пакета Android)", + "PROCESS-PATH-REGEX": "Соответствует полному пути процесса с использованием регулярных выражений", + "NETWORK": "Соответствует транспортному протоколу (tcp/udp)", + "UID": "Соответствует USER ID в Linux", + "IN-TYPE": "Соответствует типу входящего соединения", + "IN-USER": "Соответствует имени пользователя входящего соединения", + "IN-NAME": "Соответствует имени входящего соединения", + "SUB-RULE": "Подправило", + "RULE-SET": "Соответствует набору правил", + "AND": "Логическое И", + "OR": "Логическое ИЛИ", + "NOT": "Логическое НЕ", + "MATCH": "Соответствует всем запросам" + }, + "title": "Редактировать правила" + } + } +} diff --git a/src/locales/ru/settings.json b/src/locales/ru/settings.json new file mode 100644 index 000000000..3b6551ea2 --- /dev/null +++ b/src/locales/ru/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Документация", + "telegram": "Telegram-канал", + "github": "GitHub репозиторий" + }, + "title": "Настройки" + }, + "sections": { + "system": { + "title": "Настройки системы", + "toggles": { + "tunMode": "Режим TUN", + "systemProxy": "Системный прокси" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "Запускать программу в фоновом режиме без отображения панели" + }, + "fields": { + "autoLaunch": "Автозапуск", + "silentStart": "Тихий запуск" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Разрешить изменение настроек прокси-сервера операционной системы. Если разрешение не удастся, измените настройки прокси-сервера операционной системы вручную", + "tunMode": "Режим Tun: захватывает весь системный трафик, при включении нет необходимости включать системный прокси-сервер.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "Установить службу", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "Системный прокси", + "tunMode": "Режим TUN" + } + }, + "externalController": { + "title": "Адрес прослушивания внешнего контроллера", + "fields": { + "enable": "Включить внешний контроллер", + "address": "Адрес прослушивания внешнего контроллера", + "secret": "Секрет" + }, + "placeholders": { + "address": "Обязательно", + "secret": "Рекомендуется" + }, + "tooltips": { + "copy": "Копировать в буфер обмена" + }, + "messages": { + "addressRequired": "Адрес контроллера не может быть пустым", + "secretRequired": "Секрет не может быть пустым", + "copyFailed": "Не удалось скопировать", + "controllerCopied": "Адрес контроллера скопирован в буфер обмена", + "secretCopied": "Секрет скопирован в буфер обмена" + } + }, + "externalCors": { + "title": "Конфигурация внешнего CORS", + "fields": { + "allowPrivateNetwork": "Разрешить доступ к частной сети", + "allowedOrigins": "Разрешённые источники" + }, + "placeholders": { + "origin": "Введите корректный URL" + }, + "actions": { + "add": "Добавить" + }, + "messages": { + "alwaysIncluded": "Всегда включаемые источники: {{urls}}" + }, + "tooltips": { + "open": "Настройки внешнего CORS" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Настройки Clash", + "form": { + "fields": { + "allowLan": "Разрешить доступ из локальной сети", + "dnsOverwrite": "Переопределение настроек DNS", + "ipv6": "IPv6", + "unifiedDelay": "Точная задержка", + "logLevel": "Уровень логов", + "portConfig": "Настройка порта", + "external": "Внешний контроллер", + "webUI": "Веб-интерфейс", + "clashCore": "Ядро Clash", + "openUwpTool": "Открыть UWP инструмент", + "updateGeoData": "Обновить GeoData" + }, + "tooltips": { + "networkInterface": "Сетевой интерфейс", + "unifiedDelay": "Когда унифицированная(точная) задержка включена, будут выполнены два теста задержки, чтобы устранить различия в задержке между разными типами узлов, вызванные подтверждением соединения и т. д", + "logLevel": "Это действует только на файлы журнала ядра в служебном файле в каталоге журналов.", + "openUwpTool": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Основные настройки Verge", + "actions": { + "browse": "Просмотреть" + }, + "trayOptions": { + "showMainWindow": "Показать главное окно", + "showTrayMenu": "Показать меню в трее", + "disable": "Отключить" + }, + "fields": { + "language": "Язык", + "themeMode": "Цветовая тема", + "trayClickEvent": "Событие при щелчке по иконке в трее", + "copyEnvType": "Скопировать тип Env", + "startPage": "Главная страница", + "startupScript": "Скрипт запуска", + "themeSetting": "Настройки темы", + "layoutSetting": "Настройки раскладки", + "misc": "Расширенные настройки", + "hotkeySetting": "Настройки сочетаний клавиш" + } + }, + "advanced": { + "title": "Расширенные настройки Verge", + "tooltips": { + "backupInfo": "Поддерживает файлы конфигурации резервного копирования WebDAV", + "openConfDir": "Если программное обеспечение работает неправильно, сделайте резервную копию и удалите все файлы в этой папке, а затем перезапустите ПО", + "liteMode": "Режим, в котором работает только ядро Clash, а графический интрефейс закрыт" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Обновление не требуется", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Настройки резервного копирования", + "runtimeConfig": "Используемый конфиг", + "openConfDir": "Открыть папку приложения", + "openCoreDir": "Открыть папку ядра", + "openLogsDir": "Открыть папку логов", + "checkUpdates": "Проверить обновления", + "openDevTools": "Открыть Dev Tools", + "liteModeSettings": "Настройки LightWeight Mode", + "exit": "Выход", + "exportDiagnostics": "Экспорт диагностической информации", + "vergeVersion": "Версия Clash Verge Rev" + } + }, + "theme": { + "title": "Настройки темы", + "fields": { + "primaryColor": "Основной цвет", + "secondaryColor": "Вторичный цвет", + "primaryText": "Первичный текст", + "secondaryText": "Вторичный текст", + "infoColor": "Информационный цвет", + "warningColor": "Цвет предупреждения", + "errorColor": "Цвет ошибки", + "successColor": "Цвет успеха", + "fontFamily": "Семейство шрифтов", + "cssInjection": "Внедрение CSS" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Настройки раскладки", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "График трафика", + "memoryUsage": "Использование памяти", + "proxyGroupIcon": "Иконка Группы прокси", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Иконки навигации", + "trayIcon": "Иконка в трее", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Общий значок в трее", + "systemProxyTrayIcon": "Значок системного прокси в трее", + "tunTrayIcon": "Значок TUN в трее", + "enableTrayIcon": "Показывать значок в трее", + "enableTraySpeed": "Показывать скорость в трее" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Монохромные", + "colorful": "Цветные", + "disable": "Отключить" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Настройка порта", + "fields": { + "mixed": "Смешанный прокси-порт", + "socks": "Порт Socks-прокси", + "http": "Порт Http(s)-прокси", + "redir": "Порт прозрачного прокси Redir", + "tproxy": "Порт прозрачного прокси Tproxy" + }, + "actions": { + "random": "Случайный порт" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Официальная версия", + "alpha": "Альфа-версия" + } + }, + "liteMode": { + "title": "Настройки LightWeight Mode", + "actions": { + "enterNow": "Войти в LightWeight Mode" + }, + "toggles": { + "autoEnter": "Автоматический вход в LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Автоматически включать LightWeight Mode, если окно закрыто определенное время" + }, + "fields": { + "delay": "Задержка включения LightWeight Mode" + }, + "messages": { + "autoEnterHint": "При закрытии окна LightWeight Mode будет автоматически активирован через {{n}} минут" + } + }, + "backup": { + "title": "Настройки резервного копирования", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Резервное копирование", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Удалить резервную копию", + "restore": "Восстановить", + "restoreBackup": "Восстановить резервную копию" + }, + "fields": { + "webdavUrl": "URL-адрес сервера WebDAV http(s)://", + "username": "Имя пользователя", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "URL-адрес WebDAV не может быть пустым", + "invalidWebdavUrl": "Неверный формат URL-адреса WebDAV", + "usernameRequired": "Имя пользователя не может быть пустым", + "passwordRequired": "Пароль не может быть пустым", + "webdavConfigSaved": "Конфигурация WebDAV успешно сохранена", + "webdavConfigSaveFailed": "Не удалось сохранить конфигурацию WebDAV: {{error}}", + "backupCreated": "Резервная копия успешно создана", + "backupFailed": "Ошибка резервного копирования: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Восстановление успешно выполнено, приложение перезапустится через 1 секунду", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Вы уверены, что хотите удалить этот файл резервной копии?", + "confirmRestore": "Вы уверены, что хотите восстановить этот файл резервной копии?" + }, + "table": { + "filename": "Имя файла", + "backupTime": "Время резервного копирования", + "actions": "Действия", + "noBackups": "Нет доступных резервных копий", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Расширенные настройки", + "fields": { + "appLogLevel": "Уровень журнала приложения", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Автоматическое закрытие соединений", + "autoCheckUpdate": "Автоматическая проверка обновлений", + "enableBuiltinEnhanced": "Включить встроенные улучшения", + "proxyLayoutColumns": "Количество столбцов в макете прокси", + "autoLogClean": "Автоматическая очистка логов", + "autoDelayDetection": "Автоматическое измерение задержки", + "defaultLatencyTest": "Ссылка на тест задержки", + "defaultLatencyTimeout": "Таймаут задержки по умолчанию" + }, + "tooltips": { + "autoCloseConnections": "Закрыть установленные соединения при изменении выбора группы прокси или режима прокси", + "enableBuiltinEnhanced": "Обработка совместимости для файла конфигурации", + "autoDelayDetection": "Периодически проверяет задержку текущего узла в фоновом режиме", + "defaultLatencyTest": "Используется только для тестирования HTTP-запросов клиента и не влияет на файл конфигурации" + }, + "options": { + "proxyLayoutColumns": { + "auto": "Авто колонки" + }, + "autoLogClean": { + "never": "Никогда не очищать", + "retainDays": "Сохранять {{n}} дней" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Перейти на страницу релизов", + "update": "Обновить" + }, + "messages": { + "portableError": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените файлы вручную", + "breakChangeError": "Это крупное обновление, которое не поддерживает обновление внутри приложения. Пожалуйста, удалите его и загрузите установочный файл вручную." + } + }, + "sysproxy": { + "title": "Настройка системного прокси", + "fieldsets": { + "currentStatus": "Текущий системный прокси" + }, + "fields": { + "enableStatus": "Статус включения", + "serverAddr": "Адрес сервера: ", + "pacUrl": "Адрес PAC: ", + "proxyHost": "Хост прокси", + "usePacMode": "Используйте режим PAC", + "proxyGuard": "Proxy Guard", + "guardDuration": "Период защиты", + "alwaysUseDefaultBypass": "Всегда использовать стандартное обходное решение", + "proxyBypass": "Игнорируемые адреса: ", + "bypass": "Игнорируемые адреса: ", + "pacScriptContent": "Содержание сценария PAC" + }, + "tooltips": { + "proxyGuard": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО" + }, + "messages": { + "durationTooShort": "Продолжительность работы прокси-демона не может быть меньше 1 секунды", + "invalidBypass": "Неверный формат обхода", + "invalidProxyHost": "Неверный формат хоста прокси" + }, + "actions": { + "editPac": "Редактировать PAC" + } + }, + "tun": { + "title": "Режим TUN", + "fields": { + "stack": "Стек", + "device": "Device Name", + "autoRoute": "Автоматическая маршрутизация", + "strictRoute": "Строгая маршрутизация", + "autoDetectInterface": "Автоопределение интерфейса", + "dnsHijack": "DNS-перехват", + "mtu": "MTU" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Настройки применены" + } + }, + "dns": { + "dialog": { + "title": "Переопределение настроек DNS", + "warning": "Если вы не знакомы с этими настройками, пожалуйста, не изменяйте и не отключайте их" + }, + "sections": { + "general": "Настройки DNS", + "fallbackFilter": "Настройки фильтра Fallback", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Включить DNS", + "listen": "Прослушивание DNS", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Диапазон FakeIP", + "fakeIpFilterMode": "FakeIP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Предпочитать H3", + "description": "DNS DOH использует http/3" + }, + "respectRules": { + "label": "Приоритизировать правила", + "description": "Соединения DNS следуют правилам маршрутизации" + }, + "useHosts": { + "label": "Использовать файл Hosts", + "description": "Включить разрешение хостов через файл Hosts" + }, + "useSystemHosts": { + "label": "Использовать системный файл Hosts", + "description": "Включить разрешение хостов через системный файл Hosts" + }, + "directPolicy": { + "label": "Прямой сервер имен следует политике", + "description": "Следовать ли политике DNS-серверов" + }, + "defaultNameserver": { + "label": "DNS-сервер по умолчанию", + "description": "DNS-серверы по умолчанию, используемые для разрешения адресов серверов DNS" + }, + "nameserver": { + "label": "DNS-сервер", + "description": "Список DNS-серверов, разделенных запятой" + }, + "fallback": { + "label": "Fallback", + "description": "Список резервных DNS-серверов, разделенных запятой" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS-серверы для разрешения домена прокси-узлов" + }, + "directNameserver": { + "label": "DNS-сервер для прямых соединений", + "description": "Список DNS-серверов для прямых соединений, разделенных запятой" + }, + "fakeIpFilter": { + "label": "Фильтр FakeIP", + "description": "Домены, которые пропускают разрешение FakeIP, разделенные запятой" + }, + "nameserverPolicy": { + "label": "Политика серверов имен", + "description": "DNS-сервер, специфичный для домена, несколько серверов разделяются знаком ';'" + }, + "geoipFiltering": { + "label": "Фильтрация GeoIP", + "description": "Включить фильтрацию GeoIP" + }, + "geoipCode": "Код GeoIP", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "Диапазоны IP-адресов, не использующие резервные серверы, разделенные запятой" + }, + "fallbackDomain": { + "label": "Fallback домены", + "description": "Домены, использующие резервные серверы, разделенные запятой" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "Перейти по адресу" + }, + "title": "Веб-интерфейс", + "messages": { + "supportedPlaceholders": "Поддерживаются %host, %port, %secret", + "placeholderInstruction": "Замените хост, порт и секрет на %host, %port, %secret" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Включить глобальную горячую клавишу" + }, + "title": "Настройки сочетаний клавиш", + "functions": { + "rule": "Режим правил", + "global": "Глобальный режим", + "openOrCloseDashboard": "Открыть/Закрыть панель управления", + "toggleSystemProxy": "Включить/Отключить системный прокси", + "toggleTunMode": "Включить/Отключить режим TUN", + "entryLightweightMode": "Вход в LightWeight Mode", + "direct": "Прямой режим" + } + }, + "password": { + "prompts": { + "enterRoot": "Пожалуйста, введите ваш пароль root" + } + }, + "networkInterface": { + "title": "Сетевой интерфейс", + "fields": { + "ipAddress": "IP адрес", + "macAddress": "MAC адрес" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Ядро перезапущено", + "versionUpdated": "Ядро обновлено до последней версии", + "alreadyLatestVersion": "Вы уже используете последнюю версию ядра", + "changeSuccess": "Ядро успешно изменено", + "changeFailed": "Не удалось сменить ядро", + "geoDataUpdated": "Файлы GeoData обновлены" + }, + "clashService": { + "installSuccess": "Служба успешно установлена", + "uninstallSuccess": "Служба успешно удалена" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "Установка службы...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/ru/shared.json b/src/locales/ru/shared.json new file mode 100644 index 000000000..e7c5c8617 --- /dev/null +++ b/src/locales/ru/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Отмена", + "close": "Закрыть", + "confirm": "Подтвердить", + "save": "Сохранить", + "delete": "Удалить", + "edit": "Редактировать", + "new": "Новый", + "enable": "Включить", + "upgrade": "Обновить", + "restart": "Перезапустить", + "resetToDefault": "Сбросить настройки", + "refresh": "Обновить", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Отображать в виде списка", + "tableView": "Отображать в виде таблицы", + "pause": "Пауза", + "resume": "Возобновить", + "closeAll": "Закрыть всё", + "clear": "Очистить" + }, + "labels": { + "updateAt": "Обновлено в", + "timeout": "Тайм-аут", + "icon": "Иконка", + "name": "Название", + "readOnly": "Только для чтения", + "expireTime": "Время окончания", + "updateTime": "Время обновления", + "usedTotal": "Использовано / Всего", + "from": "От", + "password": "Пароль", + "retryAttempts": "Retry attempts", + "downloaded": "Скачано", + "uploaded": "Загружено" + }, + "statuses": { + "enabled": "Включено", + "disabled": "Отключено", + "saving": "Saving...", + "empty": "Пусто" + }, + "units": { + "milliseconds": "миллисекунды", + "seconds": "секунды", + "minutes": "минуты", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Условия фильтрации", + "matchCase": "Учитывать регистр", + "matchWholeWord": "Полное совпадение слова", + "useRegex": "Использовать регулярные выражения" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Развернуть", + "minimize": "Свернуть" + }, + "editorModes": { + "visualization": "Визуализация", + "advanced": "Дополнительно" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Профиль успешно импортирован", + "importSubscriptionSuccess": "Подписка успешно импортирована", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Скопировано", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Ошибка проверки конфигурации подписки, проверьте файл конфигурации, изменения отменены, ошибка:", + "bootFailed": "Ошибка проверки конфигурации при запуске, используется конфигурация по умолчанию, проверьте файл конфигурации, ошибка:", + "coreChangeFailed": "Ошибка проверки конфигурации при смене ядра, используется конфигурация по умолчанию, проверьте файл конфигурации, ошибка:", + "processTerminated": "Процесс проверки прерван" + }, + "script": { + "syntaxError": "Ошибка синтаксиса скрипта, изменения отменены", + "missingMain": "Ошибка скрипта, изменения отменены", + "fileNotFound": "Файл не найден, изменения отменены", + "fileError": "Ошибка файла скрипта, изменения отменены" + }, + "yaml": { + "syntaxError": "Ошибка синтаксиса YAML, откат изменений", + "readError": "Ошибка чтения YAML, откат изменений", + "mappingError": "Ошибка YAML Mapping, откат изменений", + "keyError": "Ошибка ключа YAML, откат изменений", + "generalError": "Ошибка YAML, откат изменений" + }, + "merge": { + "syntaxError": "Ошибка синтаксиса Merge File, откат изменений", + "mappingError": "Ошибка сопоставления в Merge File, откат изменений", + "keyError": "Ошибка ключа в Merge File, откат изменений", + "generalError": "Ошибка Merge File, откат изменений" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/ru/tests.json b/src/locales/ru/tests.json new file mode 100644 index 000000000..16b2a5e04 --- /dev/null +++ b/src/locales/ru/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Тестировать все" + }, + "title": "Тест" + }, + "components": { + "item": { + "actions": { + "test": "Тест" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Создать тест", + "edit": "Редактировать тест" + }, + "fields": { + "url": "URL проверка" + } + } + }, + "statuses": { + "test": { + "pending": "В ожидании", + "yes": "Да", + "no": "Нет", + "failed": "Ошибка", + "completed": "Завершено", + "disallowedIsp": "ISP заблокирован", + "originalsOnly": "Только Originals", + "noDisney": "Нет (IP забанен Disney+)", + "unsupportedRegion": "Страна/регион не поддерживается", + "failedNetwork": "Ошибка подключения" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Тестирование ..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "Не удалось обнаружить {{name}}", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Тест доступности веб-сайтов" + } + } +} diff --git a/src/locales/tr.json b/src/locales/tr.json deleted file mode 100644 index 0b4064882..000000000 --- a/src/locales/tr.json +++ /dev/null @@ -1,619 +0,0 @@ -{ - "millis": "ms", - "seconds": "saniye", - "mins": "dakika", - "Back": "Geri", - "Close": "Kapat", - "Cancel": "İptal", - "Confirm": "Onayla", - "Maximize": "Büyüt", - "Minimize": "Küçült", - "Format document": "Belgeyi biçimlendir", - "Empty": "Boş", - "New": "Yeni", - "Edit": "Düzenle", - "Save": "Kaydet", - "Delete": "Sil", - "Enable": "Etkinleştir", - "Disable": "Devre Dışı Bırak", - "Label-Home": "Ana Sayfa", - "Label-Proxies": "Vekil'ler", - "Label-Profiles": "Profiller", - "Label-Connections": "Bağlantılar", - "Label-Rules": "Kurallar", - "Label-Logs": "Günlükler", - "Label-Unlock": "Test", - "Label-Settings": "Ayarlar", - "Proxies": "Vekil'ler", - "Proxy Groups": "Vekil Grupları", - "Proxy Provider": "Vekil Sağlayıcısı", - "Proxy Count": "Vekil Sayısı", - "Update All": "Tümünü Güncelle", - "Update At": "Güncelleme Zamanı", - "rule": "kural", - "global": "küresel", - "direct": "doğrudan", - "Chain Proxy": "🔗 Zincir Proxy", - "script": "betik", - "locate": "konum", - "Delay check": "Gecikme kontrolü", - "Sort by default": "Varsayılana göre sırala", - "Sort by delay": "Gecikmeye göre sırala", - "Sort by name": "İsme göre sırala", - "Delay check URL": "Gecikme kontrol URL'si", - "Delay check to cancel fixed": "Sabit iptali için gecikme kontrolü", - "Proxy basic": "Temel Vekil", - "Proxy detail": "Vekil detayı", - "Profiles": "Profiller", - "Update All Profiles": "Tüm Profilleri Güncelle", - "View Runtime Config": "Çalışma Zamanı Yapılandırmasını Görüntüle", - "Reactivate Profiles": "Profilleri Yeniden Etkinleştir", - "Paste": "Yapıştır", - "Profile URL": "Profil URL'si", - "Import": "İçe Aktar", - "From": "Kaynak", - "Update Time": "Güncelleme Zamanı", - "Used / Total": "Kullanılan / Toplam", - "Expire Time": "Sona Erme Zamanı", - "Create Profile": "Profil Oluştur", - "Edit Profile": "Profili Düzenle", - "Edit Proxies": "Vekil'leri Düzenle", - "Use newlines for multiple uri": "Birden fazla URI için yeni satırlar kullanın (Base64 kodlaması desteklenir)", - "Edit Rules": "Kuralları Düzenle", - "Rule Type": "Kural Tipi", - "Rule Content": "Kural İçeriği", - "Proxy Policy": "Vekil Politikası", - "No Resolve": "Çözümleme Yok", - "Prepend Rule": "Kuralın Başına Ekle", - "Append Rule": "Kuralın Sonuna Ekle", - "Prepend Group": "Grubun Başına Ekle", - "Append Group": "Grubun Sonuna Ekle", - "Prepend Proxy": "Vekil'in Başına Ekle", - "Append Proxy": "Vekil'in Sonuna Ekle", - "Rule Condition Required": "Kural Koşulu Gerekli", - "Invalid Rule": "Geçersiz Kural", - "Advanced": "Gelişmiş", - "Visualization": "Görselleştirme", - "DOMAIN": "Tam alan adıyla eşleşir", - "DOMAIN-SUFFIX": "Alan adı sonekiyle eşleşir", - "DOMAIN-KEYWORD": "Alan adı anahtar kelimesiyle eşleşir", - "DOMAIN-REGEX": "Alan adını düzenli ifadeler kullanarak eşleştirir", - "GEOSITE": "Geosite içindeki alan adlarıyla eşleşir", - "GEOIP": "IP adresinin ülke koduyla eşleşir", - "SRC-GEOIP": "Kaynak IP adresinin ülke koduyla eşleşir", - "IP-ASN": "IP adresinin ASN'siyle eşleşir", - "SRC-IP-ASN": "Kaynak IP adresinin ASN'siyle eşleşir", - "IP-CIDR": "IP adresi aralığıyla eşleşir", - "IP-CIDR6": "IPv6 adresi aralığıyla eşleşir", - "SRC-IP-CIDR": "Kaynak IP adresi aralığıyla eşleşir", - "IP-SUFFIX": "IP adresi sonek aralığıyla eşleşir", - "SRC-IP-SUFFIX": "Kaynak IP adresi sonek aralığıyla eşleşir", - "SRC-PORT": "Kaynak port aralığıyla eşleşir", - "DST-PORT": "Hedef port aralığıyla eşleşir", - "IN-PORT": "Gelen port ile eşleşir", - "DSCP": "DSCP işaretlemesi (sadece tvekil UDP girişi için)", - "PROCESS-NAME": "İşlem adıyla eşleşir (Android paket adı)", - "PROCESS-PATH": "Tam işlem yoluyla eşleşir", - "PROCESS-NAME-REGEX": "Tam işlem adını düzenli ifadeler kullanarak eşleştirir (Android paket adı)", - "PROCESS-PATH-REGEX": "Tam işlem yolunu düzenli ifadeler kullanarak eşleştirir", - "NETWORK": "Taşıma protokolüyle eşleşir (tcp/udp)", - "UID": "Linux KULLANICI ID'siyle eşleşir", - "IN-TYPE": "Gelen bağlantı tipiyle eşleşir", - "IN-USER": "Gelen bağlantı kullanıcı adıyla eşleşir", - "IN-NAME": "Gelen bağlantı adıyla eşleşir", - "SUB-RULE": "Alt kural", - "RULE-SET": "Kural setiyle eşleşir", - "AND": "Mantıksal VE", - "OR": "Mantıksal VEYA", - "NOT": "Mantıksal DEĞİL", - "MATCH": "Tüm isteklerle eşleşir", - "DIRECT": "Veri doğrudan dışarı gider", - "REJECT": "İstekleri engeller", - "REJECT-DROP": "İstekleri atar", - "PASS": "Eşleştiğinde bu kuralı atlar", - "Edit Groups": "Vekil Gruplarını Düzenle", - "Group Type": "Grup Tipi", - "select": "Vekil'i manuel olarak seçin", - "url-test": "URL testi gecikmesine göre vekil seçin", - "fallback": "Hata durumunda başka bir vekil'e geçin", - "load-balance": "Yük dengelemeye göre vekil dağıtın", - "relay": "Tanımlanan vekil zincirinden geçirin", - "Group Name": "Grup Adı", - "Use Proxies": "Vekil'leri Kullan", - "Use Provider": "Sağlayıcı Kullan", - "Health Check Url": "Sağlık Kontrolü URL'si", - "Expected Status": "Beklenen Durum", - "Interval": "Aralık", - "Lazy": "Tembel", - "Timeout": "Zaman Aşımı", - "Max Failed Times": "Maksimum Başarısız Deneme", - "Interface Name": "Arayüz Adı", - "Routing Mark": "Yönlendirme İşareti", - "Include All": "Tüm Vekil'leri ve Sağlayıcıları Dahil Et", - "Include All Providers": "Tüm Sağlayıcıları Dahil Et", - "Include All Proxies": "Tüm Vekil'leri Dahil Et", - "Exclude Filter": "Hariç Tutma Filtresi", - "Exclude Type": "Hariç Tutma Tipi", - "Disable UDP": "UDP'yi Devre Dışı Bırak", - "Hidden": "Gizli", - "Group Name Required": "Grup Adı Gerekli", - "Group Name Already Exists": "Grup Adı Zaten Var", - "Extend Config": "Yapılandırma Genişletme", - "Extend Script": "Betik Genişletme", - "Global Merge": "Küresel Yapılandırma Genişletme", - "Global Script": "Küresel Betik Genişletme", - "Type": "Tip", - "Name": "İsim", - "Descriptions": "Açıklamalar", - "Subscription URL": "Abonelik URL'si", - "Update Interval": "Güncelleme Aralığı", - "Choose File": "Dosya Seç", - "Use System Proxy": "Sistem Vekil'ini Kullan", - "Use Clash Proxy": "Clash Vekil'ini Kullan", - "Accept Invalid Certs (Danger)": "Geçersiz Sertifikalara İzin Ver (Tehlikeli)", - "Refresh": "Yenile", - "Home": "Ana Sayfa", - "Select": "Seç", - "Edit Info": "Bilgileri Düzenle", - "Edit File": "Dosyayı Düzenle", - "Open File": "Dosyayı Aç", - "Update": "Güncelle", - "Update(Proxy)": "Güncelle(Vekil)", - "Confirm deletion": "Silmeyi Onayla", - "This operation is not reversible": "Bu işlem geri alınamaz", - "Script Console": "Betik Konsolu", - "To Top": "Başa Dön", - "To End": "Sona Git", - "Connections": "Bağlantılar", - "Table View": "Tablo Görünümü", - "List View": "Liste Görünümü", - "Close All": "Tümünü Kapat", - "Upload": "Yükleme", - "Download": "İndirme", - "Download Speed": "İndirme Hızı", - "Upload Speed": "Yükleme Hızı", - "Host": "Ana Bilgisayar", - "Downloaded": "İndirilen", - "Uploaded": "Yüklenen", - "DL Speed": "İndirme Hızı", - "UL Speed": "Yükleme Hızı", - "Active Connections": "Aktif Bağlantılar", - "Chains": "Zincirler", - "Rule": "Kural", - "Process": "İşlem", - "Time": "Zaman", - "Source": "Kaynak", - "Destination": "Hedef", - "DestinationPort": "Hedef Port", - "Close Connection": "Bağlantıyı Kapat", - "Rules": "Kurallar", - "Rule Provider": "Kural Sağlayıcısı", - "Logs": "Günlükler", - "Pause": "Duraklat", - "Resume": "Sürdür", - "Clear": "Temizle", - "Test": "Test", - "Test All": "Tümünü Test Et", - "Testing...": "Test Ediliyor...", - "Create Test": "Test Oluştur", - "Edit Test": "Testi Düzenle", - "Icon": "Simge", - "Test URL": "Test URL'si", - "Settings": "Ayarlar", - "System Setting": "Sistem Ayarları", - "Tun Mode": "Tun Modu", - "TUN requires Service Mode": "TUN modu hizmet kurulumu gerektirir", - "Install Service": "Hizmeti Kur", - "Install Service failed": "Hizmet kurulumu başarısız oldu", - "Restart Core failed": "Çekirdek yeniden başlatma başarısız oldu", - "Reset to Default": "Varsayılana Sıfırla", - "Tun Mode Info": "Tun (Sanal Ağ Kartı) modu: Tüm sistem trafiğini yakalar, etkinleştirildiğinde sistem vekil'ini etkinleştirmeye gerek yoktur.", - "System Proxy Enabled": "Sistem vekil'i etkinleştirildi, uygulamalarınız vekil üzerinden ağa erişecek", - "System Proxy Disabled": "Sistem vekil'i devre dışı, çoğu kullanıcı için bu seçeneği açmanız önerilir", - "TUN Mode Enabled": "TUN modu etkinleştirildi, uygulamalar sanal ağ kartı üzerinden ağa erişecek", - "TUN Mode Disabled": "TUN modu devre dışı, özel uygulamalar için uygundur", - "TUN Mode Service Required": "TUN modu hizmet modu gerektirir, lütfen önce hizmeti kurun", - "TUN Mode Intercept Info": "TUN modu tüm uygulama trafiğini ele alabilir, sistem vekil ayarlarını takip etmeyen özel uygulamalar için uygundur", - "Rule Mode Description": "Trafiği önceden ayarlanmış kurallara göre yönlendirir, esnek vekil stratejileri sağlar", - "Global Mode Description": "Tüm trafik vekil sunucuları üzerinden geçer, küresel internet erişimi gerektiren senaryolar için uygundur", - "Direct Mode Description": "Tüm trafik vekil düğümleri üzerinden geçmez, ancak Clash çekirdeği tarafından hedef sunuculara yönlendirilir, çekirdek trafik dağıtımı gerektiren özel senaryolar için uygundur", - "Stack": "Tun Yığını", - "System and Mixed Can Only be Used in Service Mode": "Sistem ve Karışık Modlar Sadece Hizmet Modunda Kullanılabilir", - "Device": "Cihaz Adı", - "Auto Route": "Otomatik Yönlendirme", - "Strict Route": "Katı Yönlendirme", - "Auto Detect Interface": "Arayüzü Otomatik Algıla", - "DNS Hijack": "DNS Ele Geçirme", - "MTU": "Maksimum İletim Birimi", - "Service Mode": "Hizmet Modu", - "Service Mode Info": "TUN modunu etkinleştirmeden önce lütfen hizmet modunu kurun. Hizmet tarafından başlatılan çekirdek işlemi, sanal ağ kartını (TUN modu) kurma iznini alabilir", - "Current State": "Mevcut Durum", - "pending": "bekliyor", - "installed": "kuruldu", - "uninstall": "kaldırıldı", - "active": "aktif", - "unknown": "bilinmiyor", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "Bilgi: Lütfen Clash Verge Hizmeti'nin kurulu ve etkin olduğundan emin olun", - "Install": "Kur", - "Uninstall": "Kaldır", - "Disable Service Mode": "Hizmet Modunu Devre Dışı Bırak", - "System Proxy": "Sistem Vekil'i", - "System Proxy Info": "İşletim sisteminin vekil ayarlarını değiştirmek için etkinleştirin. Etkinleştirme başarısız olursa, işletim sisteminin proxy ayarlarını manuel olarak değiştirin", - "System Proxy Setting": "Sistem Vekil Ayarı", - "Current System Proxy": "Geçerli Sistem Vekil'i", - "Enable status": "Etkinlik Durumu:", - "Enabled": "Etkin", - "Disabled": "Devre Dışı", - "Server Addr": "Sunucu Adresi: ", - "Proxy Host": "Vekil Sunucusu", - "Invalid Proxy Host Format": "Geçersiz Vekil Sunucusu Formatı", - "Not available": "Kullanılamıyor", - "Proxy Guard": "Vekil Koruyucusu", - "Proxy Guard Info": "Diğer yazılımların işletim sisteminin vekil ayarlarını değiştirmesini önlemek için etkinleştirin", - "Guard Duration": "Koruma Süresi", - "Always use Default Bypass": "Her Zaman Varsayılan Baypas Kullan", - "Use Bypass Check": "Baypas Kontrolü Kullan", - "Proxy Bypass": "Vekil Baypas Ayarları: ", - "Bypass": "Baypas: ", - "Use PAC Mode": "PAC Modunu Kullan", - "PAC Script Content": "PAC Betiği İçeriği", - "PAC URL": "PAC URL'si: ", - "Auto Launch": "Otomatik Başlatma", - "Administrator mode may not support auto launch": "Yönetici modu otomatik başlatmayı desteklemeyebilir", - "Silent Start": "Sessiz Başlatma", - "Silent Start Info": "Programı paneli görüntülemeden arka plan modunda başlatır", - "TG Channel": "Telegram Kanalı", - "Manual": "Kılavuz", - "Github Repo": "Github Repo", - "Clash Setting": "Clash Ayarı", - "Allow Lan": "LAN'a İzin Ver", - "Network Interface": "Ağ Arayüzü", - "Ip Address": "IP Adresi", - "Mac Address": "MAC Adresi", - "IPv6": "IPv6", - "Unified Delay": "Birleşik Gecikme", - "Unified Delay Info": "Birleşik gecikme açıldığında, bağlantı el sıkışmaları vb. nedeniyle farklı tür düğümler arasındaki gecikme farklarını ortadan kaldırmak için iki gecikme testi gerçekleştirilir", - "Log Level": "Günlük Seviyesi", - "Log Level Info": "Bu parametre yalnızca günlük dizini Hizmet klasöründeki çekirdek günlük dosyaları için geçerlidir", - "Port Config": "Port Yapılandırması", - "Random Port": "Rastgele Port", - "Mixed Port": "Karışık Port", - "Socks Port": "Socks Portu", - "Http Port": "Http(s) Portu", - "Redir Port": "Redir Portu", - "Tproxy Port": "Tvekil Portu", - "External": "Harici", - "External Controller": "Harici Denetleyici", - "Core Secret": "Çekirdek Sırrı", - "Recommended": "Önerilen", - "Open URL": "URL Aç", - "Replace host, port, secret with %host, %port, %secret": "Ana bilgisayar, port, sırrı %host, %port, %secret ile değiştirin", - "Support %host, %port, %secret": "%host, %port, %secret destekler", - "Clash Core": "Clash Çekirdeği", - "Upgrade": "Yükselt", - "Restart": "Yeniden Başlat", - "Release Version": "Sürüm Versiyonu", - "Alpha Version": "Alfa Versiyonu", - "Please Enable Service Mode": "Lütfen Önce Hizmet Modunu Kurun ve Etkinleştirin", - "Please enter your root password": "Lütfen root şifrenizi girin", - "Grant": "İzin Ver", - "Open UWP tool": "UWP Aracını Aç", - "Open UWP tool Info": "Windows 8'den beri, UWP uygulamaları (Microsoft Store gibi) yerel ana bilgisayar ağ hizmetlerine doğrudan erişmekten kısıtlanmıştır ve bu araç bu kısıtlamayı atlatmak için kullanılabilir", - "Update GeoData": "GeoData'yı Güncelle", - "Verge Basic Setting": "Verge Temel Ayarı", - "Verge Advanced Setting": "Verge Gelişmiş Ayarı", - "Language": "Dil", - "Theme Mode": "Tema Modu", - "theme.light": "Açık", - "theme.dark": "Koyu", - "theme.system": "Sistem", - "Tray Click Event": "Sistem Tepsisi Tıklama Olayı", - "Show Main Window": "Ana Pencereyi Göster", - "Show Tray Menu": "Tepsi Menüsünü Göster", - "Copy Env Type": "Env Tipini Kopyala", - "Copy Success": "Kopyalama Başarılı", - "Start Page": "Başlangıç Sayfası", - "Startup Script": "Başlangıç Betiği", - "Browse": "Gözat", - "Theme Setting": "Tema Ayarı", - "Primary Color": "Ana Renk", - "Secondary Color": "İkincil Renk", - "Primary Text": "Ana Metin", - "Secondary Text": "İkincil Metin", - "Info Color": "Bilgi Rengi", - "Warning Color": "Uyarı Rengi", - "Error Color": "Hata Rengi", - "Success Color": "Başarı Rengi", - "Font Family": "Yazı Tipi Ailesi", - "CSS Injection": "CSS Enjeksiyonu", - "Layout Setting": "Düzen Ayarı", - "Traffic Graph": "Trafik Grafiği", - "Memory Usage": "Çekirdek Kullanımı", - "Memory Cleanup": "Belleği temizlemek için dokunun", - "Proxy Group Icon": "Vekil Grup Simgesi", - "Nav Icon": "Gezinme Simgesi", - "Monochrome": "Tek Renkli", - "Colorful": "Renkli", - "Tray Icon": "Tepsi Simgesi", - "Common Tray Icon": "Genel Tepsi Simgesi", - "System Proxy Tray Icon": "Sistem Vekil Tepsi Simgesi", - "Tun Tray Icon": "Tun Tepsi Simgesi", - "Miscellaneous": "Çeşitli", - "App Log Level": "Uygulama Günlük Seviyesi", - "Auto Close Connections": "Bağlantıları Otomatik Kapat", - "Auto Close Connections Info": "Vekil grup seçimi veya vekil modu değiştiğinde kurulan bağlantıları sonlandır", - "Auto Check Update": "Otomatik Güncelleme Kontrolü", - "Enable Builtin Enhanced": "Yerleşik Geliştirilmiş Modu Etkinleştir", - "Enable Builtin Enhanced Info": "Yapılandırma dosyası için uyumluluk işleme", - "Proxy Layout Columns": "Vekil Düzeni Sütunları", - "Auto Columns": "Otomatik Sütunlar", - "Auto Log Clean": "Otomatik Günlük Temizleme", - "Never Clean": "Asla Temizleme", - "Retain _n Days": "{{n}} Gün Sakla", - "Auto Delay Detection": "Otomatik Gecikme Tespiti", - "Auto Delay Detection Info": "Arka planda mevcut düğümün gecikmesini periyodik olarak test eder", - "Default Latency Test": "Varsayılan Gecikme Testi", - "Default Latency Test Info": "Yalnızca HTTP istemci isteği testi için kullanılır ve yapılandırma dosyasında bir fark yaratmaz", - "Default Latency Timeout": "Varsayılan Gecikme Zaman Aşımı", - "Hotkey Setting": "Kısayol Tuşu Ayarı", - "Enable Global Hotkey": "Küresel Kısayol Tuşunu Etkinleştir", - "open_or_close_dashboard": "Kontrol Panelini Aç/Kapat", - "clash_mode_rule": "Kural Modu", - "clash_mode_global": "Küresel Mod", - "clash_mode_direct": "Doğrudan Mod", - "toggle_system_proxy": "Sistem Vekil'ini Etkinleştir/Devre Dışı Bırak", - "toggle_tun_mode": "Tun Modunu Etkinleştir/Devre Dışı Bırak", - "entry_lightweight_mode": "Hafif Moda Gir", - "Backup Setting": "Yedekleme Ayarı", - "Backup Setting Info": "WebDAV yedekleme yapılandırma dosyalarını destekler", - "Runtime Config": "Çalışma Zamanı Yapılandırması", - "Open Conf Dir": "Yapılandırma Dizinini Aç", - "Open Conf Dir Info": "Yazılım anormal çalışıyorsa, bu klasördeki tüm dosyaları YEDEKLEYİN ve silin, ardından yazılımı yeniden başlatın", - "Open Core Dir": "Çekirdek Dizinini Aç", - "Open Logs Dir": "Günlük Dizinini Aç", - "Check for Updates": "Güncellemeleri Kontrol Et", - "Go to Release Page": "Sürüm Sayfasına Git", - "Portable Updater Error": "Taşınabilir sürüm uygulama içi güncellemeleri desteklemez. Lütfen manuel olarak indirip değiştirin", - "Break Change Update Error": "Bu sürüm büyük bir güncellemedir ve uygulama içi güncellemeleri desteklemez. Lütfen kaldırın ve yeni sürümü manuel olarak indirip kurun", - "Open Dev Tools": "Geliştirici Araçları", - "Export Diagnostic Info": "Tanılama Bilgilerini Dışa Aktar", - "Export Diagnostic Info For Issue Reporting": "Sorun Bildirimi İçin Tanılama Bilgilerini Dışa Aktar", - "Exit": "Çıkış", - "Verge Version": "Verge Sürümü", - "ReadOnly": "Salt Okunur", - "ReadOnlyMessage": "Salt okunur düzenleyicide düzenlenemez", - "Filter": "Filtre", - "Filter conditions": "Filtre koşulları", - "Match Case": "Büyük/Küçük Harf Eşleştir", - "Match Whole Word": "Tam Kelime Eşleştir", - "Use Regular Expression": "Düzenli İfade Kullan", - "Profile Imported Successfully": "Profil Başarıyla İçe Aktarıldı", - "Profile Switched": "Profil Değiştirildi", - "Profile Reactivated": "Profil Yeniden Etkinleştirildi", - "Only YAML Files Supported": "Yalnızca YAML Dosyaları Desteklenir", - "Settings Applied": "Ayarlar Uygulandı", - "Installing Service...": "Hizmet Kuruluyor...", - "Service Installed Successfully": "Hizmet Başarıyla Kuruldu", - "Service Uninstalled Successfully": "Hizmet Başarıyla Kaldırıldı", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Vekil Koruyucu Süresi 1 Saniyeden Az Olamaz", - "Invalid Bypass Format": "Geçersiz Baypas Formatı", - "Clash Port Modified": "Clash Portu Değiştirildi", - "Port Conflict": "Port Çakışması", - "Restart Application to Apply Modifications": "Değişiklikleri Uygulamak İçin Uygulamayı Yeniden Başlatın", - "External Controller Address Modified": "Harici Denetleyici Adresi Değiştirildi", - "Permissions Granted Successfully for _clash Core": "{{core}} Çekirdeği İçin İzinler Başarıyla Verildi", - "Core Version Updated": "Çekirdek Sürümü Güncellendi", - "Clash Core Restarted": "Clash Çekirdeği Yeniden Başlatıldı", - "GeoData Updated": "GeoData Güncellendi", - "Currently on the Latest Version": "Şu Anda En Son Sürümdesiniz", - "Import Subscription Successful": "Abonelik içe aktarımı başarılı", - "WebDAV Server URL": "WebDAV Sunucu URL'si", - "Username": "Kullanıcı Adı", - "Password": "Şifre", - "Backup": "Yedekle", - "Filename": "Dosya Adı", - "Actions": "İşlemler", - "Restore": "Geri Yükle", - "No Backups": "Kullanılabilir yedek yok", - "WebDAV URL Required": "WebDAV URL'si boş olamaz", - "Invalid WebDAV URL": "Geçersiz WebDAV URL formatı", - "Username Required": "Kullanıcı adı boş olamaz", - "Password Required": "Şifre boş olamaz", - "Failed to Fetch Backups": "Yedek dosyaları alınamadı", - "WebDAV Config Saved": "WebDAV yapılandırması başarıyla kaydedildi", - "WebDAV Config Save Failed": "WebDAV yapılandırması kaydedilemedi: {{error}}", - "Backup Created": "Yedek başarıyla oluşturuldu", - "Backup Failed": "Yedekleme başarısız oldu: {{error}}", - "Delete Backup": "Yedeği Sil", - "Restore Backup": "Yedeği Geri Yükle", - "Backup Time": "Yedekleme Zamanı", - "Confirm to delete this backup file?": "Bu yedek dosyasını silmeyi onaylıyor musunuz?", - "Confirm to restore this backup file?": "Bu yedek dosyasını geri yüklemeyi onaylıyor musunuz?", - "Restore Success, App will restart in 1s": "Geri Yükleme Başarılı, Uygulama 1 saniye içinde yeniden başlatılacak", - "Failed to fetch backup files": "Yedek dosyaları alınamadı", - "Profile": "Profil", - "Help": "Yardım", - "About": "Hakkında", - "Theme": "Tema", - "Main Window": "Ana Pencere", - "Group Icon": "Grup Simgesi", - "Menu Icon": "Menü Simgesi", - "PAC File": "PAC Dosyası", - "Web UI": "Web Arayüzü", - "Hotkeys": "Kısayol Tuşları", - "Verge Mixed Port": "Verge Karışık Port", - "Verge Socks Port": "Verge Socks Portu", - "Verge Redir Port": "Verge Redir Portu", - "Verge Tproxy Port": "Verge Tvekil Portu", - "Verge Port": "Verge Portu", - "Verge HTTP Enabled": "Verge HTTP Etkin", - "WebDAV URL": "WebDAV URL'si", - "WebDAV Username": "WebDAV Kullanıcı Adı", - "WebDAV Password": "WebDAV Şifresi", - "Dashboard": "Kontrol Paneli", - "Restart App": "Uygulamayı Yeniden Başlat", - "Restart Clash Core": "Clash Çekirdeğini Yeniden Başlat", - "TUN Mode": "TUN Modu", - "Copy Env": "Env Kopyala", - "Conf Dir": "Yapılandırma Dizini", - "Core Dir": "Çekirdek Dizini", - "Logs Dir": "Günlük Dizini", - "Open Dir": "Dizin Aç", - "More": "Daha Fazla", - "Rule Mode": "Kural Modu", - "Global Mode": "Küresel Mod", - "Direct Mode": "Doğrudan Mod", - "Enable Tray Speed": "Tepsi Hızını Etkinleştir", - "Enable Tray Icon": "Tepsi Simgesini Etkinleştir", - "LightWeight Mode": "Hafif Mod", - "LightWeight Mode Info": "GUI'yi kapatın ve yalnızca çekirdeği çalışır durumda tutun", - "LightWeight Mode Settings": "Hafif Mod Ayarları", - "Enter LightWeight Mode Now": "Şimdi Hafif Moda Gir", - "Auto Enter LightWeight Mode": "Otomatik Hafif Moda Gir", - "Auto Enter LightWeight Mode Info": "Pencere belirli bir süre kapatıldıktan sonra Hafif Modun otomatik olarak etkinleştirilmesi için etkinleştirin", - "Auto Enter LightWeight Mode Delay": "Otomatik Hafif Mod Giriş Gecikmesi", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "Pencere kapatıldığında, Hafif Mod {{n}} dakika sonra otomatik olarak etkinleştirilecek", - "Config Validation Failed": "Abonelik yapılandırması doğrulaması başarısız oldu. Lütfen abonelik yapılandırma dosyasını kontrol edin; değişiklikler geri alındı.", - "Boot Config Validation Failed": "Başlangıç abonelik yapılandırması doğrulaması başarısız oldu. Varsayılan yapılandırma ile başlatıldı; lütfen abonelik yapılandırma dosyasını kontrol edin.", - "Core Change Config Validation Failed": "Çekirdek değiştirilirken yapılandırma doğrulaması başarısız oldu. Varsayılan yapılandırma ile başlatıldı; lütfen abonelik yapılandırma dosyasını kontrol edin.", - "Config Validation Process Terminated": "Doğrulama işlemi sonlandırıldı.", - "Script Syntax Error": "Betik sözdizimi hatası, değişiklikler geri alındı", - "Script Missing Main": "Betik hatası, değişiklikler geri alındı", - "File Not Found": "Dosya eksik, değişiklikler geri alındı", - "Script File Error": "Betik dosyası hatası, değişiklikler geri alındı", - "Core Changed Successfully": "Çekirdek başarıyla değiştirildi", - "Failed to Change Core": "Çekirdek değiştirilemedi", - "YAML Syntax Error": "YAML sözdizimi hatası, değişiklikler geri alındı", - "YAML Read Error": "YAML okuma hatası, değişiklikler geri alındı", - "YAML Mapping Error": "YAML eşleme hatası, değişiklikler geri alındı", - "YAML Key Error": "YAML anahtar hatası, değişiklikler geri alındı", - "YAML Error": "YAML hatası, değişiklikler geri alındı", - "Merge File Syntax Error": "Birleştirme dosyası sözdizimi hatası, değişiklikler geri alındı", - "Merge File Mapping Error": "Birleştirme dosyası eşleme hatası, değişiklikler geri alındı", - "Merge File Key Error": "Birleştirme dosyası anahtar hatası, değişiklikler geri alındı", - "Merge File Error": "Birleştirme dosyası hatası, değişiklikler geri alındı", - "Validate YAML File": "YAML Dosyasını Doğrula", - "Validate Merge File": "Birleştirme Dosyasını Doğrula", - "Validation Success": "Doğrulama Başarılı", - "Validation Failed": "Doğrulama Başarısız", - "Service Administrator Prompt": "Clash Verge sistem hizmetini yeniden kurmak için yönetici ayrıcalıkları gerektiriyor", - "DNS Settings": "DNS Ayarları", - "DNS settings saved": "DNS ayarları kaydedildi", - "DNS Overwrite": "DNS Üzerine Yazma", - "DNS Settings Warning": "Bu ayarlarla ilgili bilginiz yoksa, lütfen bunları değiştirmeyin ve DNS Üzerine Yazma'yı etkin tutun", - "Enable DNS": "DNS'i Etkinleştir", - "DNS Listen": "DNS Dinleme", - "Enhanced Mode": "Geliştirilmiş Mod", - "Fake IP Range": "Sahte IP Aralığı", - "Fake IP Filter Mode": "Sahte IP Filtre Modu", - "Enable IPv6 DNS resolution": "IPv6 DNS çözümlemesini etkinleştir", - "Prefer H3": "H3'ü Tercih Et", - "Respect Rules": "Kurallara Uy", - "DNS connections follow routing rules": "DNS bağlantıları yönlendirme kurallarını takip eder", - "Use Hosts": "Hosts Kullan", - "Enable to resolve hosts through hosts file": "Ana bilgisayarları hosts dosyası aracılığıyla çözümlemek için etkinleştirin", - "Use System Hosts": "Sistem Hosts Dosyasını Kullan", - "Enable to resolve hosts through system hosts file": "Ana bilgisayarları sistem hosts dosyası aracılığıyla çözümlemek için etkinleştirin", - "Direct Nameserver Follow Policy": "Doğrudan İsim Sunucusu Politikasını Takip Et", - "Whether to follow nameserver policy": "İsim sunucusu politikasının takip edilip edilmeyeceği", - "Default Nameserver": "Varsayılan İsim Sunucusu", - "Default DNS servers used to resolve DNS servers": "DNS sunucularını çözümlemek için kullanılan varsayılan DNS sunucuları", - "Nameserver": "İsim Sunucusu", - "List of DNS servers": "DNS sunucuları listesi, virgülle ayrılmış", - "Fallback": "Yedek", - "List of fallback DNS servers": "Yedek DNS sunucuları listesi, virgülle ayrılmış", - "Proxy Server Nameserver": "Vekil Sunucusu İsim Sunucusu", - "Proxy Node Nameserver": "Vekil düğümü alan adı çözümlemesi için DNS sunucuları", - "Direct Nameserver": "Doğrudan İsim Sunucusu", - "Direct outbound Nameserver": "Doğrudan çıkış alan adı çözümlemesi için DNS sunucuları, 'system' anahtar kelimesini destekler, virgülle ayrılmış", - "Fake IP Filter": "Sahte IP Filtresi", - "Domains that skip fake IP resolution": "Sahte IP çözümlemesini atlayan alan adları, virgülle ayrılmış", - "Nameserver Policy": "İsim Sunucusu Politikası", - "Domain-specific DNS server": "Alana özgü DNS sunucusu, birden çok sunucu noktalı virgülle ayrılır, format: domain=server1;server2", - "Fallback Filter Settings": "Yedek Filtre Ayarları", - "GeoIP Filtering": "GeoIP Filtreleme", - "Enable GeoIP filtering for fallback": "Yedek için GeoIP filtrelemeyi etkinleştir", - "GeoIP Code": "GeoIP Kodu", - "Fallback IP CIDR": "Yedek IP CIDR", - "IP CIDRs not using fallback servers": "Yedek sunucuları kullanmayan IP CIDR'ları, virgülle ayrılmış", - "Fallback Domain": "Yedek Alan Adı", - "Domains using fallback servers": "Yedek sunucuları kullanan alan adları, virgülle ayrılmış", - "Hosts Settings": "Hosts Ayarları", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "Özel alan adından IP'ye veya alan adına eşleme", - "Enable Alpha Channel": "Alfa Kanalını Etkinleştir", - "Alpha versions may contain experimental features and bugs": "Alfa sürümleri deneysel özellikler ve hatalar içerebilir", - "Home Settings": "Ana Sayfa Ayarları", - "Profile Card": "Profil Kartı", - "Current Proxy Card": "Geçerli Vekil Kartı", - "Network Settings Card": "Ağ Ayarları Kartı", - "Proxy Mode Card": "Vekil Modu Kartı", - "Clash Mode Card": "Clash Modu Kartı", - "Traffic Stats Card": "Trafik İstatistikleri Kartı", - "Clash Info Cards": "Clash Bilgi Kartları", - "System Info Cards": "Sistem Bilgi Kartları", - "Website Tests Card": "Web Sitesi Testleri Kartı", - "Traffic Stats": "Trafik İstatistikleri", - "Website Tests": "Web Sitesi Testleri", - "Clash Info": "Clash Bilgisi", - "Core Version": "Çekirdek Sürümü", - "System Proxy Address": "Sistem Vekil Adresi", - "Uptime": "Çalışma Süresi", - "Rules Count": "Kural Sayısı", - "System Info": "Sistem Bilgisi", - "OS Info": "İşletim Sistemi Bilgisi", - "Running Mode": "Çalışma Modu", - "Sidecar Mode": "Kullanıcı Modu", - "Administrator Mode": "Yönetici Modu", - "Administrator + Service Mode": "Yönetici + Hizmet Modu", - "Last Check Update": "Son Güncelleme Kontrolü", - "Click to import subscription": "Abonelik içe aktarmak için tıklayın", - "Last Update failed": "Son güncelleme başarısız oldu", - "Next Up": "Sıradaki", - "No schedule": "Program yok", - "Unknown": "Bilinmiyor", - "Auto update disabled": "Otomatik güncelleme devre dışı", - "Update subscription successfully": "Abonelik başarıyla güncellendi", - "Update with Clash proxy successfully": "Clash vekil ile güncelleme başarılı", - "Update failed even with Clash proxy": "Clash vekil ile bile güncelleme başarısız oldu", - "Profile creation failed, retrying with Clash proxy...": "Profil oluşturma başarısız oldu, Clash vekil ile yeniden deneniyor...", - "Profile creation succeeded with Clash proxy": "Clash vekil ile profil oluşturma başarılı oldu", - "Import failed, retrying with Clash proxy...": "İçe aktarma başarısız oldu, Clash vekil ile yeniden deneniyor...", - "Profile Imported with Clash proxy": "Profil Clash vekil ile içe aktarıldı", - "Import failed even with Clash proxy": "Clash vekil ile bile içe aktarma başarısız oldu", - "Current Node": "Geçerli Düğüm", - "No active proxy node": "Aktif vekil düğümü yok", - "Network Settings": "Ağ Ayarları", - "Proxy Mode": "Vekil Modu", - "Group": "Grup", - "Proxy": "Vekil", - "IP Information Card": "IP Bilgi Kartı", - "IP Information": "IP Bilgisi", - "Failed to get IP info": "IP bilgisi alınamadı", - "ISP": "ISP", - "ASN": "ASN", - "ORG": "Kuruluş", - "Location": "Konum", - "Timezone": "Saat Dilimi", - "Auto refresh": "Otomatik yenile", - "Unlock Test": "Kilit Açma Testi", - "Pending": "Beklemede", - "Yes": "Evet", - "No": "Hayır", - "Failed": "Başarısız", - "Completed": "Tamamlandı", - "Disallowed ISP": "İzin Verilmeyen ISP", - "Originals Only": "Yalnızca Orijinaller", - "No (IP Banned By Disney+)": "Hayır (IP Disney+ Tarafından Yasaklandı)", - "Unsupported Country/Region": "Desteklenmeyen Ülke/Bölge", - "Failed (Network Connection)": "Başarısız (Ağ Bağlantısı)", - "Batch Operations": "Toplu İşlemler", - "Delete Selected Profiles": "Seçili Profilleri Sil", - "Deselect All": "Tüm Seçimi Kaldır", - "Done": "Tamam", - "items": "öğeler", - "Select All": "Tümünü Seç", - "Selected": "Seçildi", - "Selected profiles deleted successfully": "Seçili profiller başarıyla silindi", - "DNS DOH uses HTTP/3": "DNS DOH HTTP/3 kullanır" -} diff --git a/src/locales/tr/connections.json b/src/locales/tr/connections.json new file mode 100644 index 000000000..e13e2bd18 --- /dev/null +++ b/src/locales/tr/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Bağlantılar" + }, + "components": { + "fields": { + "host": "Ana Bilgisayar", + "dlSpeed": "İndirme Hızı", + "ulSpeed": "Yükleme Hızı", + "chains": "Zincirler", + "rule": "Kural", + "process": "İşlem", + "time": "Zaman", + "source": "Kaynak", + "destination": "Hedef", + "destinationPort": "Hedef Port", + "type": "Tip" + }, + "order": { + "default": "Default", + "uploadSpeed": "Yükleme Hızı", + "downloadSpeed": "İndirme Hızı" + }, + "actions": { + "closeConnection": "Bağlantıyı Kapat" + } + } +} diff --git a/src/locales/tr/home.json b/src/locales/tr/home.json new file mode 100644 index 000000000..2bcf868c7 --- /dev/null +++ b/src/locales/tr/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Hafif Mod", + "manual": "Kılavuz", + "settings": "Ana Sayfa Ayarları" + }, + "cards": { + "trafficStats": "Trafik İstatistikleri", + "networkSettings": "Ağ Ayarları", + "proxyMode": "Vekil Modu" + }, + "settings": { + "cards": { + "profile": "Profil Kartı", + "currentProxy": "Geçerli Vekil Kartı", + "network": "Ağ Ayarları Kartı", + "proxyMode": "Vekil Modu Kartı", + "traffic": "Trafik İstatistikleri Kartı", + "tests": "Web Sitesi Testleri Kartı", + "ip": "IP Bilgi Kartı", + "clashInfo": "Clash Bilgi Kartları", + "systemInfo": "Sistem Bilgi Kartları" + }, + "title": "Ana Sayfa Ayarları" + }, + "title": "Ana Sayfa" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "Sistem vekil'i etkinleştirildi, uygulamalarınız vekil üzerinden ağa erişecek", + "systemProxyDisabled": "Sistem vekil'i devre dışı, çoğu kullanıcı için bu seçeneği açmanız önerilir", + "tunModeServiceRequired": "TUN modu hizmet modu gerektirir, lütfen önce hizmeti kurun", + "tunModeEnabled": "TUN modu etkinleştirildi, uygulamalar sanal ağ kartı üzerinden ağa erişecek", + "tunModeDisabled": "TUN modu devre dışı, özel uygulamalar için uygundur" + }, + "tooltips": { + "systemProxy": "İşletim sisteminin vekil ayarlarını değiştirmek için etkinleştirin. Etkinleştirme başarısız olursa, işletim sisteminin proxy ayarlarını manuel olarak değiştirin", + "tunMode": "TUN modu tüm uygulama trafiğini ele alabilir, sistem vekil ayarlarını takip etmeyen özel uygulamalar için uygundur" + } + }, + "clashInfo": { + "title": "Clash Bilgisi", + "fields": { + "coreVersion": "Çekirdek Sürümü", + "systemProxyAddress": "Sistem Vekil Adresi", + "mixedPort": "Mixed Port", + "uptime": "Çalışma Süresi", + "rulesCount": "Kural Sayısı" + } + }, + "systemInfo": { + "title": "Sistem Bilgisi", + "fields": { + "osInfo": "İşletim Sistemi Bilgisi", + "autoLaunch": "Otomatik Başlatma", + "runningMode": "Çalışma Modu", + "lastCheckUpdate": "Son Güncelleme Kontrolü", + "vergeVersion": "Verge Sürümü" + }, + "actions": { + "settings": "Ayarlar" + }, + "tooltips": { + "autoLaunchAdmin": "Yönetici modu otomatik başlatmayı desteklemeyebilir" + }, + "badges": { + "adminMode": "Yönetici Modu", + "serviceMode": "Hizmet Modu", + "sidecarMode": "Kullanıcı Modu", + "adminServiceMode": "Yönetici + Hizmet Modu" + } + }, + "ipInfo": { + "title": "IP Bilgisi", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "Kuruluş", + "location": "Konum", + "timezone": "Saat Dilimi", + "autoRefresh": "Otomatik yenile", + "unknown": "Bilinmiyor" + }, + "errors": { + "load": "IP bilgisi alınamadı" + } + }, + "currentProxy": { + "title": "Geçerli Düğüm", + "actions": { + "refreshDelay": "Gecikme kontrolü" + }, + "labels": { + "globalMode": "Küresel Mod", + "directMode": "Doğrudan Mod", + "group": "Grup", + "proxy": "Vekil", + "noActiveNode": "Aktif vekil düğümü yok" + } + }, + "tests": { + "title": "Web Sitesi Testleri" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Yükleme Hızı", + "downloadSpeed": "İndirme Hızı", + "activeConnections": "Aktif Bağlantılar", + "memoryUsage": "Çekirdek Kullanımı" + }, + "legends": { + "upload": "Yükleme", + "download": "İndirme" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Kural Modu", + "global": "Küresel Mod", + "direct": "Doğrudan Mod" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/tr/index.ts b/src/locales/tr/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/tr/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/tr/layout.json b/src/locales/tr/layout.json new file mode 100644 index 000000000..839bc6e83 --- /dev/null +++ b/src/locales/tr/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Ana Sayfa", + "proxies": "Vekil'ler", + "profiles": "Profiller", + "connections": "Bağlantılar", + "rules": "Kurallar", + "logs": "Günlükler", + "unlock": "Test", + "settings": "Ayarlar" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/tr/logs.json b/src/locales/tr/logs.json new file mode 100644 index 000000000..4fa81c059 --- /dev/null +++ b/src/locales/tr/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Günlükler" + } +} diff --git a/src/locales/tr/profiles.json b/src/locales/tr/profiles.json new file mode 100644 index 000000000..5a8ab7c58 --- /dev/null +++ b/src/locales/tr/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Tüm Profilleri Güncelle", + "viewRuntimeConfig": "Çalışma Zamanı Yapılandırmasını Görüntüle", + "reactivate": "Profilleri Yeniden Etkinleştir", + "import": "İçe Aktar" + }, + "batch": { + "actions": { + "delete": "Seçili Profilleri Sil", + "selectAll": "Tümünü Seç", + "deselectAll": "Tüm Seçimi Kaldır", + "done": "Tamam" + }, + "summary": { + "selected": "Seçildi", + "items": "öğeler" + }, + "title": "Toplu İşlemler" + }, + "importForm": { + "placeholder": "Profil URL'si", + "actions": { + "paste": "Yapıştır" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Yalnızca YAML Dosyaları Desteklenir" + }, + "notifications": { + "importRetry": "İçe aktarma başarısız oldu, Clash vekil ile yeniden deneniyor...", + "importFail": "Clash vekil ile bile içe aktarma başarısız oldu", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Profil Değiştirildi", + "profileReactivated": "Profil Yeniden Etkinleştirildi", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Seçili profiller başarıyla silindi" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Profiller" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Abonelik içe aktarmak için tıklayın" + } + }, + "fileInput": { + "chooseFile": "Dosya Seç" + }, + "menu": { + "home": "Ana Sayfa", + "select": "Seç", + "editInfo": "Bilgileri Düzenle", + "editFile": "Dosyayı Düzenle", + "editRules": "Kuralları Düzenle", + "editProxies": "Vekil'leri Düzenle", + "editGroups": "Vekil Gruplarını Düzenle", + "extendConfig": "Yapılandırma Genişletme", + "extendScript": "Betik Genişletme", + "openFile": "Dosyayı Aç", + "update": "Güncelle", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Son güncelleme başarısız oldu", + "nextUp": "Sıradaki", + "noSchedule": "Program yok", + "unknown": "Bilinmiyor", + "autoUpdateDisabled": "Otomatik güncelleme devre dışı" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Profil Oluştur", + "edit": "Profili Düzenle" + }, + "fields": { + "type": "Tip", + "description": "Açıklamalar", + "subscriptionUrl": "Abonelik URL'si", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Güncelleme Aralığı", + "useSystemProxy": "Sistem Vekil'ini Kullan", + "useClashProxy": "Clash Vekil'ini Kullan", + "acceptInvalidCerts": "Geçersiz Sertifikalara İzin Ver (Tehlikeli)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profil oluşturma başarısız oldu, Clash vekil ile yeniden deneniyor...", + "creationSuccess": "Clash vekil ile profil oluşturma başarılı oldu" + } + } + }, + "proxiesEditor": { + "title": "Vekil'leri Düzenle", + "placeholders": { + "multiUri": "Birden fazla URI için yeni satırlar kullanın (Base64 kodlaması desteklenir)" + }, + "actions": { + "prepend": "Vekil'in Başına Ekle", + "append": "Vekil'in Sonuna Ekle" + } + }, + "groupsEditor": { + "title": "Vekil Gruplarını Düzenle", + "errors": { + "nameRequired": "Grup Adı Gerekli", + "nameExists": "Grup Adı Zaten Var" + }, + "fields": { + "type": "Grup Tipi", + "name": "Grup Adı", + "icon": "Vekil Grup Simgesi", + "proxies": "Vekil'leri Kullan", + "provider": "Sağlayıcı Kullan", + "healthCheckUrl": "Sağlık Kontrolü URL'si", + "expectedStatus": "Beklenen Durum", + "interval": "Aralık", + "maxFailedTimes": "Maksimum Başarısız Deneme", + "interfaceName": "Arayüz Adı", + "routingMark": "Yönlendirme İşareti", + "filter": "Filtre", + "excludeFilter": "Hariç Tutma Filtresi", + "excludeType": "Hariç Tutma Tipi", + "includeAll": "Tüm Vekil'leri ve Sağlayıcıları Dahil Et", + "includeAllProxies": "Tüm Vekil'leri Dahil Et", + "includeAllProviders": "Tüm Sağlayıcıları Dahil Et" + }, + "toggles": { + "lazy": "Tembel", + "disableUdp": "UDP'yi Devre Dışı Bırak", + "hidden": "Gizli" + }, + "actions": { + "prepend": "Grubun Başına Ekle", + "append": "Grubun Sonuna Ekle" + } + }, + "editor": { + "actions": { + "format": "Belgeyi biçimlendir" + }, + "messages": { + "readOnly": "Salt okunur düzenleyicide düzenlenemez" + } + }, + "confirmDelete": { + "title": "Silmeyi Onayla", + "message": "Bu işlem geri alınamaz" + }, + "logViewer": { + "title": "Betik Konsolu" + } + } +} diff --git a/src/locales/tr/proxies.json b/src/locales/tr/proxies.json new file mode 100644 index 000000000..ac098259b --- /dev/null +++ b/src/locales/tr/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Zincir Proxy", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Vekil Sağlayıcısı", + "actions": { + "updateAll": "Tümünü Güncelle", + "update": "Güncelle" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Vekil Sayısı", + "delayCheckReset": "Sabit iptali için gecikme kontrolü" + }, + "tooltips": { + "locate": "konum", + "delayCheck": "Gecikme kontrolü", + "sortDefault": "Varsayılana göre sırala", + "sortDelay": "Gecikmeye göre sırala", + "sortName": "İsme göre sırala", + "delayCheckUrl": "Gecikme kontrol URL'si", + "showBasic": "Temel Vekil", + "showDetail": "Vekil detayı", + "filter": "Filtre" + }, + "placeholders": { + "delayCheckUrl": "Gecikme kontrol URL'si" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Doğrudan Mod" + }, + "title": { + "default": "Vekil Grupları", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Vekil'i manuel olarak seçin", + "url-test": "URL testi gecikmesine göre vekil seçin", + "fallback": "Hata durumunda başka bir vekil'e geçin", + "load-balance": "Yük dengelemeye göre vekil dağıtın", + "relay": "Tanımlanan vekil zincirinden geçirin" + }, + "policies": { + "DIRECT": "Veri doğrudan dışarı gider", + "REJECT": "İstekleri engeller", + "REJECT-DROP": "İstekleri atar", + "PASS": "Eşleştiğinde bu kuralı atlar" + } + } + } +} diff --git a/src/locales/tr/rules.json b/src/locales/tr/rules.json new file mode 100644 index 000000000..ac8ae0d81 --- /dev/null +++ b/src/locales/tr/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Kural Sağlayıcısı", + "dialogTitle": "Kural Sağlayıcısı", + "actions": { + "updateAll": "Tümünü Güncelle", + "update": "Güncelle" + } + }, + "title": "Kurallar" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Kural Tipi", + "content": "Kural İçeriği", + "proxyPolicy": "Vekil Politikası" + }, + "toggles": { + "noResolve": "Çözümleme Yok" + }, + "actions": { + "prependRule": "Kuralın Başına Ekle", + "appendRule": "Kuralın Sonuna Ekle" + }, + "validation": { + "conditionRequired": "Kural Koşulu Gerekli", + "invalidRule": "Geçersiz Kural" + } + }, + "ruleTypes": { + "DOMAIN": "Tam alan adıyla eşleşir", + "DOMAIN-SUFFIX": "Alan adı sonekiyle eşleşir", + "DOMAIN-KEYWORD": "Alan adı anahtar kelimesiyle eşleşir", + "DOMAIN-REGEX": "Alan adını düzenli ifadeler kullanarak eşleştirir", + "GEOSITE": "Geosite içindeki alan adlarıyla eşleşir", + "GEOIP": "IP adresinin ülke koduyla eşleşir", + "SRC-GEOIP": "Kaynak IP adresinin ülke koduyla eşleşir", + "IP-ASN": "IP adresinin ASN'siyle eşleşir", + "SRC-IP-ASN": "Kaynak IP adresinin ASN'siyle eşleşir", + "IP-CIDR": "IP adresi aralığıyla eşleşir", + "IP-CIDR6": "IPv6 adresi aralığıyla eşleşir", + "SRC-IP-CIDR": "Kaynak IP adresi aralığıyla eşleşir", + "IP-SUFFIX": "IP adresi sonek aralığıyla eşleşir", + "SRC-IP-SUFFIX": "Kaynak IP adresi sonek aralığıyla eşleşir", + "SRC-PORT": "Kaynak port aralığıyla eşleşir", + "DST-PORT": "Hedef port aralığıyla eşleşir", + "IN-PORT": "Gelen port ile eşleşir", + "DSCP": "DSCP işaretlemesi (sadece tvekil UDP girişi için)", + "PROCESS-NAME": "İşlem adıyla eşleşir (Android paket adı)", + "PROCESS-PATH": "Tam işlem yoluyla eşleşir", + "PROCESS-NAME-REGEX": "Tam işlem adını düzenli ifadeler kullanarak eşleştirir (Android paket adı)", + "PROCESS-PATH-REGEX": "Tam işlem yolunu düzenli ifadeler kullanarak eşleştirir", + "NETWORK": "Taşıma protokolüyle eşleşir (tcp/udp)", + "UID": "Linux KULLANICI ID'siyle eşleşir", + "IN-TYPE": "Gelen bağlantı tipiyle eşleşir", + "IN-USER": "Gelen bağlantı kullanıcı adıyla eşleşir", + "IN-NAME": "Gelen bağlantı adıyla eşleşir", + "SUB-RULE": "Alt kural", + "RULE-SET": "Kural setiyle eşleşir", + "AND": "Mantıksal VE", + "OR": "Mantıksal VEYA", + "NOT": "Mantıksal DEĞİL", + "MATCH": "Tüm isteklerle eşleşir" + }, + "title": "Kuralları Düzenle" + } + } +} diff --git a/src/locales/tr/settings.json b/src/locales/tr/settings.json new file mode 100644 index 000000000..6c0adc844 --- /dev/null +++ b/src/locales/tr/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Kılavuz", + "telegram": "Telegram Kanalı", + "github": "Github Repo" + }, + "title": "Ayarlar" + }, + "sections": { + "system": { + "title": "Sistem Ayarları", + "toggles": { + "tunMode": "Tun Modu", + "systemProxy": "Sistem Vekil'i" + }, + "tooltips": { + "autoLaunchAdmin": "Yönetici modu otomatik başlatmayı desteklemeyebilir", + "silentStart": "Programı paneli görüntülemeden arka plan modunda başlatır" + }, + "fields": { + "autoLaunch": "Otomatik Başlat", + "silentStart": "Sessiz Başlatma" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "İşletim sisteminin vekil ayarlarını değiştirmek için etkinleştirin. Etkinleştirme başarısız olursa, işletim sisteminin proxy ayarlarını manuel olarak değiştirin", + "tunMode": "Tun (Sanal Ağ Kartı) modu: Tüm sistem trafiğini yakalar, etkinleştirildiğinde sistem vekil'ini etkinleştirmeye gerek yoktur.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "Hizmeti Kur", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "Sistem Vekil'i", + "tunMode": "Tun Modu" + } + }, + "externalController": { + "title": "Harici Denetleyici", + "fields": { + "enable": "Harici denetleyiciyi etkinleştir", + "address": "Harici Denetleyici", + "secret": "Çekirdek Sırrı" + }, + "placeholders": { + "address": "Gerekli", + "secret": "Önerilen" + }, + "tooltips": { + "copy": "Panoya kopyala" + }, + "messages": { + "addressRequired": "Denetleyici adresi boş olamaz", + "secretRequired": "Gizli anahtar boş olamaz", + "copyFailed": "Kopyalama başarısız", + "controllerCopied": "Denetleyici adresi panoya kopyalandı", + "secretCopied": "Gizli anahtar panoya kopyalandı" + } + }, + "externalCors": { + "title": "Harici CORS yapılandırması", + "fields": { + "allowPrivateNetwork": "Özel ağ erişimine izin ver", + "allowedOrigins": "İzin verilen kökenler" + }, + "placeholders": { + "origin": "Geçerli bir URL girin" + }, + "actions": { + "add": "Ekle" + }, + "messages": { + "alwaysIncluded": "Her zaman dahil edilen kökenler: {{urls}}" + }, + "tooltips": { + "open": "Harici CORS ayarları" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Clash Ayarı", + "form": { + "fields": { + "allowLan": "LAN'a İzin Ver", + "dnsOverwrite": "DNS Üzerine Yazma", + "ipv6": "IPv6", + "unifiedDelay": "Birleşik Gecikme", + "logLevel": "Günlük Seviyesi", + "portConfig": "Port Yapılandırması", + "external": "Harici", + "webUI": "Web Arayüzü", + "clashCore": "Clash Çekirdeği", + "openUwpTool": "UWP Aracını Aç", + "updateGeoData": "GeoData'yı Güncelle" + }, + "tooltips": { + "networkInterface": "Ağ Arayüzü", + "unifiedDelay": "Birleşik gecikme açıldığında, bağlantı el sıkışmaları vb. nedeniyle farklı tür düğümler arasındaki gecikme farklarını ortadan kaldırmak için iki gecikme testi gerçekleştirilir", + "logLevel": "Bu parametre yalnızca günlük dizini Hizmet klasöründeki çekirdek günlük dosyaları için geçerlidir", + "openUwpTool": "Windows 8'den beri, UWP uygulamaları (Microsoft Store gibi) yerel ana bilgisayar ağ hizmetlerine doğrudan erişmekten kısıtlanmıştır ve bu araç bu kısıtlamayı atlatmak için kullanılabilir" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge Temel Ayarı", + "actions": { + "browse": "Gözat" + }, + "trayOptions": { + "showMainWindow": "Ana Pencereyi Göster", + "showTrayMenu": "Tepsi Menüsünü Göster", + "disable": "Devre Dışı Bırak" + }, + "fields": { + "language": "Dil", + "themeMode": "Tema Modu", + "trayClickEvent": "Sistem Tepsisi Tıklama Olayı", + "copyEnvType": "Env Tipini Kopyala", + "startPage": "Başlangıç Sayfası", + "startupScript": "Başlangıç Betiği", + "themeSetting": "Tema Ayarı", + "layoutSetting": "Düzen Ayarı", + "misc": "Çeşitli", + "hotkeySetting": "Kısayol Tuşu Ayarı" + } + }, + "advanced": { + "title": "Verge Gelişmiş Ayarı", + "tooltips": { + "backupInfo": "WebDAV yedekleme yapılandırma dosyalarını destekler", + "openConfDir": "Yazılım anormal çalışıyorsa, bu klasördeki tüm dosyaları YEDEKLEYİN ve silin, ardından yazılımı yeniden başlatın", + "liteMode": "GUI'yi kapatın ve yalnızca çekirdeği çalışır durumda tutun" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Şu Anda En Son Sürümdesiniz", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Yedekleme Ayarı", + "runtimeConfig": "Çalışma Zamanı Yapılandırması", + "openConfDir": "Yapılandırma Dizinini Aç", + "openCoreDir": "Çekirdek Dizinini Aç", + "openLogsDir": "Günlük Dizinini Aç", + "checkUpdates": "Güncellemeleri Kontrol Et", + "openDevTools": "Geliştirici Araçları", + "liteModeSettings": "Hafif Mod Ayarları", + "exit": "Çıkış", + "exportDiagnostics": "Tanılama Bilgilerini Dışa Aktar", + "vergeVersion": "Verge Sürümü" + } + }, + "theme": { + "title": "Tema Ayarı", + "fields": { + "primaryColor": "Ana Renk", + "secondaryColor": "İkincil Renk", + "primaryText": "Ana Metin", + "secondaryText": "İkincil Metin", + "infoColor": "Bilgi Rengi", + "warningColor": "Uyarı Rengi", + "errorColor": "Hata Rengi", + "successColor": "Başarı Rengi", + "fontFamily": "Yazı Tipi Ailesi", + "cssInjection": "CSS Enjeksiyonu" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Düzen Ayarı", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Trafik Grafiği", + "memoryUsage": "Çekirdek Kullanımı", + "proxyGroupIcon": "Vekil Grup Simgesi", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Gezinme Simgesi", + "trayIcon": "Tepsi Simgesi", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Genel Tepsi Simgesi", + "systemProxyTrayIcon": "Sistem Vekil Tepsi Simgesi", + "tunTrayIcon": "Tun Tepsi Simgesi", + "enableTrayIcon": "Tepsi Simgesini Etkinleştir", + "enableTraySpeed": "Tepsi Hızını Etkinleştir" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Tek Renkli", + "colorful": "Renkli", + "disable": "Devre Dışı Bırak" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Port Yapılandırması", + "fields": { + "mixed": "Karışık Port", + "socks": "Socks Portu", + "http": "Http(s) Portu", + "redir": "Redir Portu", + "tproxy": "Tvekil Portu" + }, + "actions": { + "random": "Rastgele Port" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Kararlı Sürüm", + "alpha": "Alfa Sürümü" + } + }, + "liteMode": { + "title": "Hafif Mod Ayarları", + "actions": { + "enterNow": "Şimdi Hafif Moda Gir" + }, + "toggles": { + "autoEnter": "Otomatik Hafif Moda Gir" + }, + "tooltips": { + "autoEnter": "Pencere belirli bir süre kapatıldıktan sonra Hafif Modun otomatik olarak etkinleştirilmesi için etkinleştirin" + }, + "fields": { + "delay": "Otomatik Hafif Mod Giriş Gecikmesi" + }, + "messages": { + "autoEnterHint": "Pencere kapatıldığında, Hafif Mod {{n}} dakika sonra otomatik olarak etkinleştirilecek" + } + }, + "backup": { + "title": "Yedekleme Ayarı", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Yedekle", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Yedeği Sil", + "restore": "Geri Yükle", + "restoreBackup": "Yedeği Geri Yükle" + }, + "fields": { + "webdavUrl": "WebDAV Sunucu URL'si", + "username": "Kullanıcı Adı", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "WebDAV URL'si boş olamaz", + "invalidWebdavUrl": "Geçersiz WebDAV URL formatı", + "usernameRequired": "Kullanıcı adı boş olamaz", + "passwordRequired": "Şifre boş olamaz", + "webdavConfigSaved": "WebDAV yapılandırması başarıyla kaydedildi", + "webdavConfigSaveFailed": "WebDAV yapılandırması kaydedilemedi: {{error}}", + "backupCreated": "Yedek başarıyla oluşturuldu", + "backupFailed": "Yedekleme başarısız oldu: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Geri Yükleme Başarılı, Uygulama 1 saniye içinde yeniden başlatılacak", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Bu yedek dosyasını silmeyi onaylıyor musunuz?", + "confirmRestore": "Bu yedek dosyasını geri yüklemeyi onaylıyor musunuz?" + }, + "table": { + "filename": "Dosya Adı", + "backupTime": "Yedekleme Zamanı", + "actions": "İşlemler", + "noBackups": "Kullanılabilir yedek yok", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Çeşitli", + "fields": { + "appLogLevel": "Uygulama Günlük Seviyesi", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Bağlantıları Otomatik Kapat", + "autoCheckUpdate": "Otomatik Güncelleme Kontrolü", + "enableBuiltinEnhanced": "Yerleşik Geliştirilmiş Modu Etkinleştir", + "proxyLayoutColumns": "Vekil Düzeni Sütunları", + "autoLogClean": "Otomatik Günlük Temizleme", + "autoDelayDetection": "Otomatik Gecikme Tespiti", + "defaultLatencyTest": "Varsayılan Gecikme Testi", + "defaultLatencyTimeout": "Varsayılan Gecikme Zaman Aşımı" + }, + "tooltips": { + "autoCloseConnections": "Vekil grup seçimi veya vekil modu değiştiğinde kurulan bağlantıları sonlandır", + "enableBuiltinEnhanced": "Yapılandırma dosyası için uyumluluk işleme", + "autoDelayDetection": "Arka planda mevcut düğümün gecikmesini periyodik olarak test eder", + "defaultLatencyTest": "Yalnızca HTTP istemci isteği testi için kullanılır ve yapılandırma dosyasında bir fark yaratmaz" + }, + "options": { + "proxyLayoutColumns": { + "auto": "Otomatik Sütunlar" + }, + "autoLogClean": { + "never": "Asla Temizleme", + "retainDays": "{{n}} Gün Sakla" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Sürüm Sayfasına Git", + "update": "Güncelle" + }, + "messages": { + "portableError": "Taşınabilir sürüm uygulama içi güncellemeleri desteklemez. Lütfen manuel olarak indirip değiştirin", + "breakChangeError": "Bu sürüm büyük bir güncellemedir ve uygulama içi güncellemeleri desteklemez. Lütfen kaldırın ve yeni sürümü manuel olarak indirip kurun" + } + }, + "sysproxy": { + "title": "Sistem Vekil Ayarı", + "fieldsets": { + "currentStatus": "Geçerli Sistem Vekil'i" + }, + "fields": { + "enableStatus": "Etkinlik Durumu:", + "serverAddr": "Sunucu Adresi: ", + "pacUrl": "PAC URL'si: ", + "proxyHost": "Vekil Sunucusu", + "usePacMode": "PAC Modunu Kullan", + "proxyGuard": "Vekil Koruyucusu", + "guardDuration": "Koruma Süresi", + "alwaysUseDefaultBypass": "Her Zaman Varsayılan Baypas Kullan", + "proxyBypass": "Vekil Baypas Ayarları: ", + "bypass": "Baypas: ", + "pacScriptContent": "PAC Betiği İçeriği" + }, + "tooltips": { + "proxyGuard": "Diğer yazılımların işletim sisteminin vekil ayarlarını değiştirmesini önlemek için etkinleştirin" + }, + "messages": { + "durationTooShort": "Vekil Koruyucu Süresi 1 Saniyeden Az Olamaz", + "invalidBypass": "Geçersiz Baypas Formatı", + "invalidProxyHost": "Geçersiz Vekil Sunucusu Formatı" + }, + "actions": { + "editPac": "Düzenle PAC" + } + }, + "tun": { + "title": "Tun Modu", + "fields": { + "stack": "Tun Yığını", + "device": "Device Name", + "autoRoute": "Otomatik Yönlendirme", + "strictRoute": "Katı Yönlendirme", + "autoDetectInterface": "Arayüzü Otomatik Algıla", + "dnsHijack": "DNS Ele Geçirme", + "mtu": "Maksimum İletim Birimi" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Ayarlar Uygulandı" + } + }, + "dns": { + "dialog": { + "title": "DNS Üzerine Yazma", + "warning": "Bu ayarlarla ilgili bilginiz yoksa, lütfen bunları değiştirmeyin ve DNS Üzerine Yazma'yı etkin tutun" + }, + "sections": { + "general": "DNS Ayarları", + "fallbackFilter": "Yedek Filtre Ayarları", + "hosts": "Hosts Ayarları" + }, + "fields": { + "enable": "DNS'i Etkinleştir", + "listen": "DNS Dinleme", + "enhancedMode": "Geliştirilmiş Mod", + "fakeIpRange": "Sahte IP Aralığı", + "fakeIpFilterMode": "Sahte IP Filtre Modu", + "ipv6": { + "label": "IPv6", + "description": "IPv6 DNS çözümlemesini etkinleştir" + }, + "preferH3": { + "label": "H3'ü Tercih Et", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Kurallara Uy", + "description": "DNS bağlantıları yönlendirme kurallarını takip eder" + }, + "useHosts": { + "label": "Hosts Kullan", + "description": "Ana bilgisayarları hosts dosyası aracılığıyla çözümlemek için etkinleştirin" + }, + "useSystemHosts": { + "label": "Sistem Hosts Dosyasını Kullan", + "description": "Ana bilgisayarları sistem hosts dosyası aracılığıyla çözümlemek için etkinleştirin" + }, + "directPolicy": { + "label": "Doğrudan İsim Sunucusu Politikasını Takip Et", + "description": "İsim sunucusu politikasının takip edilip edilmeyeceği" + }, + "defaultNameserver": { + "label": "Varsayılan İsim Sunucusu", + "description": "DNS sunucularını çözümlemek için kullanılan varsayılan DNS sunucuları" + }, + "nameserver": { + "label": "İsim Sunucusu", + "description": "DNS sunucuları listesi, virgülle ayrılmış" + }, + "fallback": { + "label": "Yedek", + "description": "Yedek DNS sunucuları listesi, virgülle ayrılmış" + }, + "proxy": { + "label": "Vekil Sunucusu İsim Sunucusu", + "description": "Vekil düğümü alan adı çözümlemesi için DNS sunucuları" + }, + "directNameserver": { + "label": "Doğrudan İsim Sunucusu", + "description": "Doğrudan çıkış alan adı çözümlemesi için DNS sunucuları, 'system' anahtar kelimesini destekler, virgülle ayrılmış" + }, + "fakeIpFilter": { + "label": "Sahte IP Filtresi", + "description": "Sahte IP çözümlemesini atlayan alan adları, virgülle ayrılmış" + }, + "nameserverPolicy": { + "label": "İsim Sunucusu Politikası", + "description": "Alana özgü DNS sunucusu, birden çok sunucu noktalı virgülle ayrılır, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtreleme", + "description": "Yedek için GeoIP filtrelemeyi etkinleştir" + }, + "geoipCode": "GeoIP Kodu", + "fallbackIpCidr": { + "label": "Yedek IP CIDR", + "description": "Yedek sunucuları kullanmayan IP CIDR'ları, virgülle ayrılmış" + }, + "fallbackDomain": { + "label": "Yedek Alan Adı", + "description": "Yedek sunucuları kullanan alan adları, virgülle ayrılmış" + }, + "hosts": { + "label": "Hosts", + "description": "Özel alan adından IP'ye veya alan adına eşleme" + } + }, + "messages": { + "saved": "DNS ayarları kaydedildi", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "URL Aç" + }, + "title": "Web Arayüzü", + "messages": { + "supportedPlaceholders": "%host, %port, %secret destekler", + "placeholderInstruction": "Ana bilgisayar, port, sırrı %host, %port, %secret ile değiştirin" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Küresel Kısayol Tuşunu Etkinleştir" + }, + "title": "Kısayol Tuşu Ayarı", + "functions": { + "rule": "Kural Modu", + "global": "Küresel Mod", + "openOrCloseDashboard": "Kontrol Panelini Aç/Kapat", + "toggleSystemProxy": "Sistem Vekil'ini Etkinleştir/Devre Dışı Bırak", + "toggleTunMode": "Tun Modunu Etkinleştir/Devre Dışı Bırak", + "entryLightweightMode": "Hafif Moda Gir", + "direct": "Doğrudan Mod" + } + }, + "password": { + "prompts": { + "enterRoot": "Lütfen root şifrenizi girin" + } + }, + "networkInterface": { + "title": "Ağ Arayüzü", + "fields": { + "ipAddress": "IP Adresi", + "macAddress": "MAC Adresi" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clash Çekirdeği Yeniden Başlatıldı", + "versionUpdated": "Çekirdek Sürümü Güncellendi", + "alreadyLatestVersion": "Zaten en yeni çekirdek sürümünü kullanıyorsunuz", + "changeSuccess": "Çekirdek başarıyla değiştirildi", + "changeFailed": "Çekirdek değiştirilemedi", + "geoDataUpdated": "GeoData Güncellendi" + }, + "clashService": { + "installSuccess": "Hizmet Başarıyla Kuruldu", + "uninstallSuccess": "Hizmet Başarıyla Kaldırıldı" + }, + "updater": { + "withClashProxySuccess": "Clash vekil ile güncelleme başarılı", + "withClashProxyFailed": "Clash vekil ile bile güncelleme başarısız oldu" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "Hizmet Kuruluyor...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/tr/shared.json b/src/locales/tr/shared.json new file mode 100644 index 000000000..f1ce80268 --- /dev/null +++ b/src/locales/tr/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "İptal", + "close": "Kapat", + "confirm": "Onayla", + "save": "Kaydet", + "delete": "Sil", + "edit": "Düzenle", + "new": "Yeni", + "enable": "Etkinleştir", + "upgrade": "Yükselt", + "restart": "Yeniden Başlat", + "resetToDefault": "Varsayılana Sıfırla", + "refresh": "Yenile", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Liste Görünümü", + "tableView": "Tablo Görünümü", + "pause": "Duraklat", + "resume": "Sürdür", + "closeAll": "Tümünü Kapat", + "clear": "Temizle" + }, + "labels": { + "updateAt": "Güncelleme Zamanı", + "timeout": "Timeout", + "icon": "Simge", + "name": "İsim", + "readOnly": "Salt Okunur", + "expireTime": "Sona Erme Zamanı", + "updateTime": "Güncelleme Zamanı", + "usedTotal": "Kullanılan / Toplam", + "from": "Kaynak", + "password": "Şifre", + "retryAttempts": "Retry attempts", + "downloaded": "İndirilen", + "uploaded": "Yüklenen" + }, + "statuses": { + "enabled": "Etkin", + "disabled": "Devre Dışı", + "saving": "Saving...", + "empty": "Boş" + }, + "units": { + "milliseconds": "ms", + "seconds": "saniye", + "minutes": "dakika", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Filtre koşulları", + "matchCase": "Büyük/Küçük Harf Eşleştir", + "matchWholeWord": "Tam Kelime Eşleştir", + "useRegex": "Düzenli İfade Kullan" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Büyüt", + "minimize": "Küçült" + }, + "editorModes": { + "visualization": "Görselleştirme", + "advanced": "Gelişmiş" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Profil Başarıyla İçe Aktarıldı", + "importSubscriptionSuccess": "Abonelik içe aktarımı başarılı", + "importWithClashProxy": "Profil Clash vekil ile içe aktarıldı", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Kopyalama Başarılı", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Abonelik yapılandırması doğrulaması başarısız oldu. Lütfen abonelik yapılandırma dosyasını kontrol edin; değişiklikler geri alındı.", + "bootFailed": "Başlangıç abonelik yapılandırması doğrulaması başarısız oldu. Varsayılan yapılandırma ile başlatıldı; lütfen abonelik yapılandırma dosyasını kontrol edin.", + "coreChangeFailed": "Çekirdek değiştirilirken yapılandırma doğrulaması başarısız oldu. Varsayılan yapılandırma ile başlatıldı; lütfen abonelik yapılandırma dosyasını kontrol edin.", + "processTerminated": "Doğrulama işlemi sonlandırıldı." + }, + "script": { + "syntaxError": "Betik sözdizimi hatası, değişiklikler geri alındı", + "missingMain": "Betik hatası, değişiklikler geri alındı", + "fileNotFound": "Dosya eksik, değişiklikler geri alındı", + "fileError": "Betik dosyası hatası, değişiklikler geri alındı" + }, + "yaml": { + "syntaxError": "YAML sözdizimi hatası, değişiklikler geri alındı", + "readError": "YAML okuma hatası, değişiklikler geri alındı", + "mappingError": "YAML eşleme hatası, değişiklikler geri alındı", + "keyError": "YAML anahtar hatası, değişiklikler geri alındı", + "generalError": "YAML hatası, değişiklikler geri alındı" + }, + "merge": { + "syntaxError": "Birleştirme dosyası sözdizimi hatası, değişiklikler geri alındı", + "mappingError": "Birleştirme dosyası eşleme hatası, değişiklikler geri alındı", + "keyError": "Birleştirme dosyası anahtar hatası, değişiklikler geri alındı", + "generalError": "Birleştirme dosyası hatası, değişiklikler geri alındı" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/tr/tests.json b/src/locales/tr/tests.json new file mode 100644 index 000000000..41d0e3032 --- /dev/null +++ b/src/locales/tr/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Tümünü Test Et" + }, + "title": "Test" + }, + "components": { + "item": { + "actions": { + "test": "Test" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Test Oluştur", + "edit": "Testi Düzenle" + }, + "fields": { + "url": "Test URL'si" + } + } + }, + "statuses": { + "test": { + "pending": "Beklemede", + "yes": "Evet", + "no": "Hayır", + "failed": "Başarısız", + "completed": "Tamamlandı", + "disallowedIsp": "İzin Verilmeyen ISP", + "originalsOnly": "Yalnızca Orijinaller", + "noDisney": "Hayır (IP Disney+ Tarafından Yasaklandı)", + "unsupportedRegion": "Desteklenmeyen Ülke/Bölge", + "failedNetwork": "Başarısız (Ağ Bağlantısı)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Test Ediliyor..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "{{name}} için tespit başarısız oldu", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Kilit Açma Testi" + } + } +} diff --git a/src/locales/tt.json b/src/locales/tt.json deleted file mode 100644 index 2a4d153ff..000000000 --- a/src/locales/tt.json +++ /dev/null @@ -1,459 +0,0 @@ -{ - "millis": "Миллисекундлар", - "seconds": "Секундлар", - "mins": "Минутлар", - "Back": "Кире", - "Close": "Ябу", - "Cancel": "Баш тарту", - "Confirm": "Растау", - "Maximize": "Зурайту", - "Minimize": "Кечерәйтү", - "Format document": "Документны форматлау", - "Empty": "Буш", - "New": "Яңа", - "Edit": "Үзгәртү", - "Save": "Саклау", - "Delete": "Бетерү", - "Enable": "Кушу", - "Disable": "Сүндерү", - "Label-Proxies": "Прокси", - "Label-Profiles": "Профильләр", - "Label-Connections": "Тоташулар", - "Label-Rules": "Кагыйдәләр", - "Label-Logs": "Логлар", - "Label-Settings": "Көйләүләр", - "Proxies": "Прокси", - "Proxy Groups": "Прокси төркемнәре", - "Proxy Provider": "Прокси провайдеры", - "Update All": "Барысын да яңарту", - "Update At": "Яңартылган вакыт", - "rule": "кагыйдә", - "global": "глобаль", - "direct": "туры", - "Chain Proxy": "🔗 Чылбыр прокси", - "script": "скриптлы", - "locate": "Урын", - "Delay check": "Задержканы тикшерү", - "Sort by default": "Башлангыч итеп сортлау", - "Sort by delay": "Задержка буенча сортлау", - "Sort by name": "Исем буенча сортлау", - "Delay check URL": "Задержканы тикшерү URL-ы", - "Delay check to cancel fixed": "Беркетелгәнне гамәлдән чыгару өчен задержканы тикшерү", - "Proxy basic": "Прокси турында кыскача мәгълүмат", - "Proxy detail": "Прокси турында тулы мәгълүмат", - "Profiles": "Профильләр", - "Update All Profiles": "Барлык профильләрне яңарту", - "View Runtime Config": "Кулланылган конфигурацияне карау", - "Reactivate Profiles": "Профильләрне янәдән активлаштыру", - "Paste": "Кую", - "Profile URL": "Профиль URL-ы", - "Import": "Импорт", - "From": "Каян", - "Update Time": "Яңарту вакыты", - "Used / Total": "Кулланылган / Барлыгы", - "Expire Time": "Тамамлану вакыты", - "Create Profile": "Профиль булдыру", - "Edit Profile": "Профильне үзгәртү", - "Edit Proxies": "Проксины үзгәртү", - "Use newlines for multiple uri": "Берничә URI өчен яңа юл символын кулланыгыз (Base64 кодлавы ярдәм ителә)", - "Edit Rules": "Кагыйдәләрне үзгәртү", - "Rule Type": "Кагыйдә төре", - "Rule Content": "Кагыйдә эчтәлеге", - "Proxy Policy": "Прокси сәясәте", - "No Resolve": "Резолвсыз", - "Prepend Rule": "Кагыйдәне өскә өстәү", - "Append Rule": "Кагыйдәне аска өстәү", - "Prepend Group": "Төркемне өскә өстәү", - "Append Group": "Төркемне аска өстәү", - "Prepend Proxy": "Проксины өскә өстәү", - "Append Proxy": "Проксины аска өстәү", - "Rule Condition Required": "Кагыйдә шарты кирәк", - "Invalid Rule": "Яраксыз кагыйдә", - "Advanced": "Өстәмә", - "Visualization": "Визуализация", - "DOMAIN": "Домен исеменең тулы туры килүе", - "DOMAIN-SUFFIX": "Домен суффиксына туры килү", - "DOMAIN-KEYWORD": "Доменда төп сүзгә туры килү", - "DOMAIN-REGEX": "Доменны регекс аша туры китерү", - "GEOSITE": "Geosite исемлегендәге доменга туры килү", - "GEOIP": "IP-адресның ил коды буенча туры килү", - "SRC-GEOIP": "Чыганак IP-адресның ил коды буенча туры килү", - "IP-ASN": "IP-адрес ASN'ы буенча туры килү", - "SRC-IP-ASN": "Чыганак IP-адрес ASN'ы буенча туры килү", - "IP-CIDR": "IP-адреслар диапазонына туры килү", - "IP-CIDR6": "IPv6 адреслар диапазонына туры килү", - "SRC-IP-CIDR": "Чыганак IP-адреслар диапазонына туры килү", - "IP-SUFFIX": "IP-адрес суффиксына туры килү", - "SRC-IP-SUFFIX": "Чыганак IP-адрес суффиксына туры килү", - "SRC-PORT": "Чыганак портлар диапазонына туры килү", - "DST-PORT": "Максат портлар диапазонына туры килү", - "IN-PORT": "Керүче портка туры килү", - "DSCP": "DSCP тамгалавы (tproxy UDP өчен)", - "PROCESS-NAME": "Процесс исеменә туры килү (Android пакет исеме)", - "PROCESS-PATH": "Процесс юлына туры килү", - "PROCESS-NAME-REGEX": "Процесс исемен регекс белән туры китерү (Android пакет исеме)", - "PROCESS-PATH-REGEX": "Процесс юлын регекс белән туры китерү", - "NETWORK": "Транспорт протоколына (tcp/udp) туры килү", - "UID": "Linux USER ID'га туры килү", - "IN-TYPE": "Керүче тоташу төренә туры килү", - "IN-USER": "Керүче тоташу кулланучысына туры килү", - "IN-NAME": "Керүче тоташу исеменә туры килү", - "SUB-RULE": "Кушымча кагыйдә", - "RULE-SET": "Кагыйдәләр тупланмасына туры килү", - "AND": "Логик ҺӘМ", - "OR": "Логик ЯКИ", - "NOT": "Логик ТҮГЕЛ", - "MATCH": "Барлык сорауларга туры килә", - "DIRECT": "Туры чыгу", - "REJECT": "Сорауларны тоткарлау", - "REJECT-DROP": "Сорауларны кире кагу", - "PASS": "Туры килсә дә, бу кагыйдәне урап узу", - "Edit Groups": "Прокси төркемнәрен үзгәртү", - "Group Type": "Төркем төре", - "select": "Проксины кулдан сайлау", - "url-test": "URL-тест задержкасына карап прокси сайлау", - "fallback": "Хата булган очракта башка проксига күчү", - "load-balance": "Трафикны баланслау нигезендә прокси тарату", - "relay": "Билгеле прокси чылбыры аша тапшыру", - "Group Name": "Төркем исеме", - "Use Proxies": "Прокси куллану", - "Use Provider": "Провайдер куллану", - "Health Check Url": "Сәламәтлекне тикшерү URL-ы", - "Expected Status": "Көтелгән статус коды", - "Interval": "Интервал", - "Lazy": "Сак режим (lazy)", - "Timeout": "Таймаут", - "Max Failed Times": "Иң күп хаталы тикшерү саны", - "Interface Name": "Интерфейс исеме", - "Routing Mark": "Маршрут билгесе", - "Include All": "Барлык прокси һәм провайдерларны кертү", - "Include All Providers": "Барлык провайдерларны кертү", - "Include All Proxies": "Барлык проксины кертү", - "Exclude Filter": "Фильтр аша чыгару", - "Exclude Type": "Чыгару төре", - "Disable UDP": "UDP'ны сүндерү", - "Hidden": "Яшерен", - "Group Name Required": "Төркем исеме кирәк", - "Group Name Already Exists": "Әлеге төркем исеме бар инде", - "Extend Config": "Merge-ны үзгәртергә", - "Extend Script": "Script-ны үзгәртергә", - "Global Merge": "Гомумкеңәйтелгән көйләүләр", - "Global Script": "Гомумкеңәйтелгән скрипт", - "Type": "Төр", - "Name": "Исем", - "Descriptions": "Тасвирламалар", - "Subscription URL": "Подписка URL-ы", - "Update Interval": "Яңарту интервалы", - "Choose File": "Файл сайлау", - "Use System Proxy": "Системалы проксины кулланып яңарту", - "Use Clash Proxy": "Clash прокси кулланып яңарту", - "Accept Invalid Certs (Danger)": "Дөрес булмаган сертификатларны кабул итү (Куркыныч)", - "Refresh": "Яңарту", - "Home": "Баш бит", - "Select": "Сайлау", - "Edit Info": "Мәгълүматны үзгәртү", - "Edit File": "Файлны үзгәртү", - "Open File": "Файлны ачу", - "Update": "Яңарту", - "Update(Proxy)": "Яңарту (прокси аша)", - "Confirm deletion": "Бетерүне раслагыз", - "This operation is not reversible": "Бу гамәлне кире кайтарып булмый", - "Script Console": "Скрипт консоле", - "To Top": "Өскә", - "To End": "Аска", - "Connections": "Тоташулар", - "Table View": "Таблица күзаллау", - "List View": "Исемлек күзаллау", - "Close All": "Барысын да ябу", - "Download Speed": "Йөкләү тизлеге", - "Upload Speed": "Йөкләү (чыгару) тизлеге", - "Host": "Хост", - "Downloaded": "Йөкләнгән", - "Uploaded": "Чыгарылган", - "DL Speed": "Йөкләү тизл.", - "UL Speed": "Чыгару тизл.", - "Chains": "Чылбырлар", - "Rule": "Кагыйдә", - "Process": "Процесс", - "Time": "Тоташу вакыты", - "Source": "Чыганак адресы", - "Destination": "Максат IP-адресы", - "DestinationPort": "Барасы порты", - "Close Connection": "Тоташуны ябу", - "Rules": "Кагыйдәләр", - "Rule Provider": "Кагыйдә провайдеры", - "Logs": "Логлар", - "Pause": "Туктау", - "Resume": "Дәвам", - "Clear": "Чистарту", - "Test": "Тест", - "Test All": "Барчасын тестлау", - "Create Test": "Тест булдыру", - "Edit Test": "Тестны үзгәртү", - "Icon": "Иконка", - "Test URL": "Тест URL-ы", - "Settings": "Көйләүләр", - "System Setting": "Система көйләүләре", - "Tun Mode": "Tun режимы (виртуаль челтәр адаптеры)", - "TUN requires Service Mode": "TUN режимы хезмәт күрсәтүне таләп итә", - "Install Service": "Хезмәтне урнаштыру", - "Reset to Default": "Башлангычка кайтару", - "Tun Mode Info": "Tun режимы бөтен системаның трафигын тотып ала. Аны кабызган очракта системалы проксины аерым кабызу таләп ителми.", - "Stack": "Стек", - "System and Mixed Can Only be Used in Service Mode": "Система яки кушылган режимнар бары тик сервис режимында гына активлаштырыла ала", - "Device": "Җайланма исеме", - "Auto Route": "Авто-маршрутлау", - "Strict Route": "Катгый маршрутлау", - "Auto Detect Interface": "Интерфейсны автоматик ачыклау", - "DNS Hijack": "DNS'ны үзгәртеп тоту (hijack)", - "MTU": "MTU (макс. тапшыру берәмлеге)", - "Service Mode": "Сервис режимы", - "Service Mode Info": "Tun режимын кабызганчы сервис режимын урнаштыру сорала. Сервис буларак эшләтелгән Clash ядросына виртуаль челтәр адаптеры (TUN) куллану рөхсәт ителә.", - "Current State": "Агымдагы торыш", - "pending": "Көтә", - "installed": "Урнаштырылган", - "uninstall": "Урнаштырылмаган", - "active": "Актив", - "unknown": "Билгесез", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "Игътибар: Clash Verge сервисы урнаштырылган һәм активлаштырылган булырга тиеш", - "Install": "Урнаштыру", - "Uninstall": "Салдыру", - "Disable Service Mode": "Сервис режимын сүндерү", - "System Proxy": "Системалы прокси", - "System Proxy Info": "Системалы прокси көйләүләрен үзгәртү рөхсәтен бирегез. Әгәр рөхсәт алу мөмкин түгел икән, прокси көйләүләрен кулдан үзгәртегез", - "System Proxy Setting": "Системалы прокси көйләүләре", - "Current System Proxy": "Агымдагы системалы прокси", - "Enable status": "Активлаштыру статусы", - "Enabled": "Кушылган", - "Disabled": "Сүнгән", - "Server Addr": "Сервер адресы", - "Proxy Host": "Прокси хосты", - "Invalid Proxy Host Format": "Прокси хосты форматы дөрес түгел", - "Not available": "Мөмкин түгел", - "Proxy Guard": "Прокси саклаучы", - "Proxy Guard Info": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз", - "Guard Duration": "Саклау вакыты", - "Always use Default Bypass": "Һәрвакыт төп Bypass-ны куллану", - "Proxy Bypass": "Проксины әйләнеп узу:", - "Bypass": "Әйләнеп узу:", - "Use PAC Mode": "PAC режимын куллану", - "PAC Script Content": "PAC скрипты эчтәлеге", - "PAC URL": "PAC адресы", - "Auto Launch": "Автостарт", - "Silent Start": "Фон режимында башлау", - "Silent Start Info": "Программаны фоновый режимда, тәрәзәсез эшләтеп җибәрү", - "TG Channel": "Telegram каналы", - "Manual": "Документация", - "Github Repo": "GitHub репозиториясе", - "Clash Setting": "Clash көйләүләре", - "Allow Lan": "Локаль челтәргә рөхсәт", - "Network Interface": "Челтәр интерфейсы", - "Ip Address": "IP адресы", - "Mac Address": "MAC адресы", - "IPv6": "IPv6", - "Unified Delay": "Бердәм задержка", - "Unified Delay Info": "Бердәм задержка актив булганда, төрле типтагы узеллар өчен икеләтә тест башкарыла, TCP установканы раслау аермаларын тигезләү максатында", - "Log Level": "Лог дәрәҗәсе", - "Log Level Info": "Бу фәкать сервис режимында эшләгән вакытта системалы журнал файлларына кагыла", - "Port Config": "Порт көйләүләре", - "Random Port": "Очраклы порт", - "Mixed Port": "Катнаш прокси порты", - "Socks Port": "Socks прокси порты", - "Http Port": "HTTP(s) прокси порты", - "Redir Port": "Redir — үтә күренмәле прокси порты", - "Tproxy Port": "Tproxy — үтә күренмәле прокси порты", - "External": "Тышкы", - "External Controller": "Тышкы контроллер адресы", - "Core Secret": "Серсүз", - "Recommended": "Тавсия ителә", - "Open URL": "URL ачарга", - "Replace host, port, secret with %host, %port, %secret": "Хост, порт, серсүзне %host, %port, %secret белән алмаштырыгыз", - "Support %host, %port, %secret": "%host, %port, %secret макросларын хуплау", - "Clash Core": "Clash ядросы", - "Upgrade": "Яңарту", - "Restart": "Перезапуск", - "Release Version": "Рәсми версия", - "Alpha Version": "Альфа-версия", - "Please Enable Service Mode": "Башта сервис режимын кабызырга кирәк", - "Please enter your root password": "root паролен языгыз", - "Grant": "Рөхсәт бирү", - "Open UWP tool": "UWP инструментын ачу", - "Open UWP tool Info": "Windows 8'дән башлап UWP кушымталары (Microsoft Store кебек) локаль хосттагы челтәр хезмәтләренә турыдан-туры тоташа алмый. Бу инструмент әлеге чикләүне әйләнеп узарга ярдәм итә", - "Update GeoData": "GeoData яңарту", - "Verge Basic Setting": "Verge Төп көйләүләр", - "Verge Advanced Setting": "Verge Киңәйтелгән көйләүләр", - "Language": "Тел", - "Theme Mode": "Теманың режимы", - "theme.light": "Якты", - "theme.dark": "Караңгы", - "theme.system": "Система", - "Tray Click Event": "Трейдагы басу вакыйгасы", - "Show Main Window": "Төп тәрәзәне күрсәтү", - "Copy Env Type": "Env төрен күчереп алу", - "Copy Success": "Күчерелде", - "Start Page": "Баш бит", - "Startup Script": "Башлану скрипты", - "Browse": "Карау", - "Theme Setting": "Тема көйләүләре", - "Primary Color": "Төп төс", - "Secondary Color": "Икенче төс", - "Info Color": "Мәгълүмат төсе", - "Warning Color": "Кисәтү төсе", - "Error Color": "Хата төсе", - "Success Color": "Уңыш төсе", - "Font Family": "Шрифтлар гаиләсе", - "CSS Injection": "CSS кертү", - "Layout Setting": "Расположение көйләүләре", - "Traffic Graph": "Трафик графигы", - "Memory Usage": "Хәтер куллану", - "Memory Cleanup": "Хәтерне чистарту өчен басыгыз", - "Proxy Group Icon": "Прокси төркеме иконкасы", - "Nav Icon": "Навигация иконкасы", - "Monochrome": "Монохром", - "Colorful": "Төсле", - "Tray Icon": "Трей иконкасы", - "Common Tray Icon": "Гомуми трей иконкасы", - "System Proxy Tray Icon": "Системалы прокси иконкасы", - "Tun Tray Icon": "Tun (виртуаль адаптер) иконкасы", - "Miscellaneous": "Өстәмә көйләүләр", - "App Log Level": "Кушымта журналы дәрәҗәсе", - "Auto Close Connections": "Тоташуларны автоматик ябу", - "Auto Close Connections Info": "Прокси төркеме яисә режимын үзгәрткәндә актив тоташуларны өзү", - "Auto Check Update": "Яңартуларны автоматик тикшерү", - "Enable Builtin Enhanced": "Эчке камилләштерүне кабызу", - "Enable Builtin Enhanced Info": "Конфигурация файлы белән туры килә торган өстәмә оптимизация", - "Proxy Layout Columns": "Прокси күрсәтү баганалары саны", - "Auto Columns": "Авто баганалар", - "Auto Log Clean": "Логларны автоматик чистарту", - "Never Clean": "Беркайчан чистартмаска", - "Retain _n Days": "{{n}} көн саклау", - "Auto Delay Detection": "Автоматик тоткарлык ачыклау", - "Auto Delay Detection Info": "Фон режимында хәзерге төен тоткарлыгын периодик тикшерә", - "Default Latency Test": "Тоткарлануны тикшерү сылтамасы (defaults)", - "Default Latency Test Info": "Бу фәкать клиентның HTTP сораулары тесты өчен кулланыла, конфигурация файлына йогынты ясамый", - "Default Latency Timeout": "Тоткарлануның стандарт таймауты", - "Hotkey Setting": "Клавиатура төймәләре (hotkey) көйләүләре", - "Enable Global Hotkey": "Глобаль Хоткейны кушу", - "open_or_close_dashboard": "Панельне ачу/ябу", - "clash_mode_rule": "Кагыйдәләр режимы", - "clash_mode_global": "Глобаль режим", - "clash_mode_direct": "Туры режим", - "toggle_system_proxy": "Системалы проксины кабызу/сүндерү", - "toggle_tun_mode": "Tun режимын кабызу/сүндерү", - "Backup Setting": "Резерв копия көйләүләре", - "Backup Setting Info": "WebDAV аша конфигурация файлын саклауны хуплый", - "Runtime Config": "Агымдагы конфигурация", - "Open Conf Dir": "Кушымта папкасын ачу", - "Open Conf Dir Info": "Әгәр программада хаталар чыкса, бу папкадагы файлларны саклап калыгыз да, аннары барысын да бетереп, программаны яңадан башлагыз", - "Open Core Dir": "Ядро сакланган папканы ачу", - "Open Logs Dir": "Логлар папкасын ачу", - "Check for Updates": "Яңартуларны тикшерү", - "Go to Release Page": "Релизлар битенә күчү", - "Portable Updater Error": "Портатив версиядә кушымта эчендә яңарту хупланмый, кулдан төшереп алыгыз", - "Break Change Update Error": "Бу зур яңарту, ул кушымта эчендә яңартылмый. Борып алып ташлап, яңадан урнаштыру сорала.", - "Open Dev Tools": "Разработчик коралларын ачу", - "Exit": "Чыгу", - "Verge Version": "Verge версиясе", - "ReadOnly": "Уку режимы гына", - "ReadOnlyMessage": "Уку режимында үзгәртү мөмкин түгел", - "Filter": "Фильтр", - "Filter conditions": "Фильтр шартлары", - "Match Case": "Регистрны исәпкә алу", - "Match Whole Word": "Сүзнең тулы туры килүе", - "Use Regular Expression": "Регуляр выражениеләр куллану", - "Profile Imported Successfully": "Профиль уңышлы импортланды", - "Profile Switched": "Профиль алмаштырылды", - "Profile Reactivated": "Профиль яңадан активлаштырылды", - "Only YAML Files Supported": "Фәкать YAML-файллар гына хуплана", - "Settings Applied": "Көйләүләр кулланылды", - "Installing Service...": "Хезмәт урнаштырыла...", - "Service Installed Successfully": "Сервис уңышлы урнаштырылды", - "Service Uninstalled Successfully": "Сервис уңышлы салдырылды", - "Proxy Daemon Duration Cannot be Less than 1 Second": "Прокси-демон эш вакыты 1 секундтан ким була алмый", - "Invalid Bypass Format": "Дөрес булмаган Bypass форматы", - "Clash Port Modified": "Clash порты үзгәртелде", - "Port Conflict": "Порт конфликтлары", - "Restart Application to Apply Modifications": "Үзгәрешләрне куллану өчен кушымтаны яңадан ачарга кирәк", - "External Controller Address Modified": "Тышкы контроллер адресы үзгәртелде", - "Permissions Granted Successfully for _clash Core": "{{core}} ядросы өчен рөхсәтләр бирелде", - "Core Version Updated": "Ядро версиясе яңартылды", - "Clash Core Restarted": "Clash ядросы яңадан башланды", - "GeoData Updated": "GeoData яңартылды", - "Currently on the Latest Version": "Сездә иң соңгы версия урнаштырылган", - "WebDAV Server URL": "WebDAV сервер URL-ы (http(s)://)", - "Username": "Кулланучы исеме", - "Password": "Пароль", - "Backup": "Резерв копия", - "Filename": "Файл исеме", - "Actions": "Гамәлләр", - "Restore": "Кайтару", - "No Backups": "Резерв копияләр юк", - "WebDAV URL Required": "WebDAV адресы буш булырга тиеш түгел", - "Invalid WebDAV URL": "WebDAV адресы дөрес түгел", - "Username Required": "Кулланучы исеме буш булмаска тиеш", - "Password Required": "Пароль буш булмаска тиеш", - "Failed to Fetch Backups": "Резерв копия файлларын алуда хата", - "WebDAV Config Saved": "WebDAV көйләүләре сакланды", - "WebDAV Config Save Failed": "WebDAV көйләүләрен саклап булмады: {{error}}", - "Backup Created": "Резерв копия уңышлы ясалды", - "Backup Failed": "Резерв копия хата белән төгәлләнде: {{error}}", - "Delete Backup": "Резерв копияне бетерү", - "Restore Backup": "Резерв копияне кайтару", - "Backup Time": "Резерв копия вакыты", - "Confirm to delete this backup file?": "Бу резерв копия файлын бетерергә телисезме?", - "Confirm to restore this backup file?": "Бу резерв копия файлын кире кайтарырга телисезме?", - "Restore Success, App will restart in 1s": "Уңышлы кайтарылды, кушымта 1 секундтан яңадан башланачак", - "Failed to fetch backup files": "Резерв копия файлларын алуда хата", - "Profile": "Профиль", - "Help": "Ярдәм", - "About": "Турында", - "Theme": "Тема", - "Main Window": "Төп тәрәзә", - "Group Icon": "Төркем иконкасы", - "Menu Icon": "Меню иконкасы", - "PAC File": "PAC файлы", - "Web UI": "Веб-интерфейс", - "Hotkeys": "Кызу төймәләр", - "Verge Mixed Port": "Verge катнаш порты", - "Verge Socks Port": "Verge Socks порты", - "Verge Redir Port": "Verge кире юнәлтү порты", - "Verge Tproxy Port": "Verge Tproxy порты", - "Verge Port": "Verge порты", - "Verge HTTP Enabled": "Verge HTTP кушылган", - "WebDAV URL": "WebDAV URL", - "WebDAV Username": "WebDAV кулланучы исеме", - "WebDAV Password": "WebDAV серсүзе", - "Dashboard": "Панель", - "Restart App": "Кушымтаны яңадан ачу", - "Restart Clash Core": "Clash ядрони яңадан башлап ачу", - "TUN Mode": "TUN режимы", - "Copy Env": "Env күчереп алу", - "Conf Dir": "Кушымта папкасы", - "Core Dir": "Ядро папкасы", - "Logs Dir": "Логлар папкасы", - "Open Dir": "Папканы ачу", - "More": "Башҡа", - "Rule Mode": "Кагыйдә режимы", - "Global Mode": "Глобаль режим", - "Direct Mode": "Туры режим", - "Enable Tray Speed": "Трей скоростьне үстерү", - "LightWeight Mode": "Җиңел Режим", - "LightWeight Mode Info": "GUI-ны ябыгыз һәм бары тик төшне генә эшләтеп калдырыгыз", - "Config Validation Failed": "Язылу көйләү тикшерүе уңышсыз, көйләү файлын тикшерегез, үзгәрешләр кире кайтарылды, хата:", - "Boot Config Validation Failed": "Йөкләү вакытында көйләү тикшерүе уңышсыз, стандарт көйләү кулланылды, көйләү файлын тикшерегез, хата:", - "Core Change Config Validation Failed": "Ядро алыштырганда көйләү тикшерүе уңышсыз, стандарт көйләү кулланылды, көйләү файлын тикшерегез, хата:", - "Config Validation Process Terminated": "Тикшерү процессы туктатылды", - "Script Syntax Error": "Скрипт синтаксик хатасы, үзгәрешләр кире кайтарылды", - "Script Missing Main": "Скрипт хатасы, үзгәрешләр кире кайтарылды", - "File Not Found": "Файл табылмады, үзгәрешләр кире кайтарылды", - "Script File Error": "Скрипт файлы хатасы, үзгәрешләр кире кайтарылды", - "Core Changed Successfully": "Ядро уңышлы алыштырылды", - "Failed to Change Core": "Ядро алыштыру уңышсыз булды", - "Service Administrator Prompt": "Clash Verge система хезмәтен яңадан урнаштыру өчен администратор хокукларын таләп итә", - "Default": "Башлангыч", - "Import subscription successful": "Подписка уңышлы импортланды", - "Label-Test": "Тест", - "Primary Text Color": "Төп текст төсе", - "Secondary Text Color": "Икенче текст төсе", - "Verge Setting": "Verge көйләүләре" -} diff --git a/src/locales/tt/connections.json b/src/locales/tt/connections.json new file mode 100644 index 000000000..847a07f1e --- /dev/null +++ b/src/locales/tt/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "Тоташулар" + }, + "components": { + "fields": { + "host": "Хост", + "dlSpeed": "Йөкләү тизл.", + "ulSpeed": "Чыгару тизл.", + "chains": "Чылбырлар", + "rule": "Кагыйдә", + "process": "Процесс", + "time": "Тоташу вакыты", + "source": "Чыганак адресы", + "destination": "Максат IP-адресы", + "destinationPort": "Барасы порты", + "type": "Төр" + }, + "order": { + "default": "Default", + "uploadSpeed": "Йөкләү (чыгару) тизлеге", + "downloadSpeed": "Йөкләү тизлеге" + }, + "actions": { + "closeConnection": "Тоташуны ябу" + } + } +} diff --git a/src/locales/tt/home.json b/src/locales/tt/home.json new file mode 100644 index 000000000..1a92f39f4 --- /dev/null +++ b/src/locales/tt/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "Җиңел Режим", + "manual": "Документация", + "settings": "Home Settings" + }, + "cards": { + "trafficStats": "Traffic Stats", + "networkSettings": "Network Settings", + "proxyMode": "Proxy Mode" + }, + "settings": { + "cards": { + "profile": "Profile Card", + "currentProxy": "Current Proxy Card", + "network": "Network Settings Card", + "proxyMode": "Proxy Mode Card", + "traffic": "Traffic Stats Card", + "tests": "Website Tests Card", + "ip": "IP Information Card", + "clashInfo": "Clash Info Cards", + "systemInfo": "System Info Cards" + }, + "title": "Home Settings" + }, + "title": "Home" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "System proxy is enabled, your applications will access the network through the proxy", + "systemProxyDisabled": "System proxy is disabled, it is recommended for most users to turn on this option", + "tunModeServiceRequired": "TUN mode requires service mode, please install the service first", + "tunModeEnabled": "TUN mode is enabled, applications will access the network through the virtual network card", + "tunModeDisabled": "TUN mode is disabled, suitable for special applications" + }, + "tooltips": { + "systemProxy": "Системалы прокси көйләүләрен үзгәртү рөхсәтен бирегез. Әгәр рөхсәт алу мөмкин түгел икән, прокси көйләүләрен кулдан үзгәртегез", + "tunMode": "TUN mode can take over all application traffic, suitable for special applications that do not follow the system proxy settings" + } + }, + "clashInfo": { + "title": "Clash Info", + "fields": { + "coreVersion": "Core Version", + "systemProxyAddress": "System Proxy Address", + "mixedPort": "Mixed Port", + "uptime": "Uptime", + "rulesCount": "Rules Count" + } + }, + "systemInfo": { + "title": "System Info", + "fields": { + "osInfo": "OS Info", + "autoLaunch": "Автостарт", + "runningMode": "Running Mode", + "lastCheckUpdate": "Last Check Update", + "vergeVersion": "Verge версиясе" + }, + "actions": { + "settings": "Көйләүләр" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch" + }, + "badges": { + "adminMode": "Administrator Mode", + "serviceMode": "Сервис режимы", + "sidecarMode": "User Mode", + "adminServiceMode": "Admin + Service Mode" + } + }, + "ipInfo": { + "title": "IP Information", + "labels": { + "ip": "IP", + "asn": "ASN", + "isp": "ISP", + "org": "ORG", + "location": "Location", + "timezone": "Timezone", + "autoRefresh": "Auto refresh", + "unknown": "Unknown" + }, + "errors": { + "load": "IP мәгълүматын алу мөмкин булмады" + } + }, + "currentProxy": { + "title": "Current Node", + "actions": { + "refreshDelay": "Задержканы тикшерү" + }, + "labels": { + "globalMode": "Глобаль режим", + "directMode": "Туры режим", + "group": "Group", + "proxy": "Proxy", + "noActiveNode": "No active proxy node" + } + }, + "tests": { + "title": "Website Tests" + }, + "traffic": { + "metrics": { + "uploadSpeed": "Йөкләү (чыгару) тизлеге", + "downloadSpeed": "Йөкләү тизлеге", + "activeConnections": "Active Connections", + "memoryUsage": "Хәтер куллану" + }, + "legends": { + "upload": "Upload", + "download": "Download" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "Core communication error" + }, + "labels": { + "rule": "Кагыйдәләр режимы", + "global": "Глобаль режим", + "direct": "Туры режим" + }, + "descriptions": { + "rule": "Automatically choose proxies according to the rule set.", + "global": "Forward all network requests through the selected proxy.", + "direct": "Bypass the proxy and connect to the internet directly." + } + } + } +} diff --git a/src/locales/tt/index.ts b/src/locales/tt/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/tt/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/tt/layout.json b/src/locales/tt/layout.json new file mode 100644 index 000000000..140644bb8 --- /dev/null +++ b/src/locales/tt/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "Home", + "proxies": "Прокси", + "profiles": "Профильләр", + "connections": "Тоташулар", + "rules": "Кагыйдәләр", + "logs": "Логлар", + "unlock": "Test", + "settings": "Көйләүләр" + }, + "menu": { + "reorderMode": "Menu reorder mode", + "unlock": "Unlock menu order", + "lock": "Lock menu order" + } + } + } +} diff --git a/src/locales/tt/logs.json b/src/locales/tt/logs.json new file mode 100644 index 000000000..5e4931c77 --- /dev/null +++ b/src/locales/tt/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "Логлар" + } +} diff --git a/src/locales/tt/profiles.json b/src/locales/tt/profiles.json new file mode 100644 index 000000000..9c1697af0 --- /dev/null +++ b/src/locales/tt/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "Барлык профильләрне яңарту", + "viewRuntimeConfig": "Кулланылган конфигурацияне карау", + "reactivate": "Профильләрне янәдән активлаштыру", + "import": "Импорт" + }, + "batch": { + "actions": { + "delete": "Delete Selected Profiles", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "done": "Done" + }, + "summary": { + "selected": "Selected", + "items": "items" + }, + "title": "Batch Operations" + }, + "importForm": { + "placeholder": "Профиль URL-ы", + "actions": { + "paste": "Кую" + } + }, + "feedback": { + "errors": { + "invalidUrl": "Invalid profile URL. Please enter a URL starting with http:// or https://", + "onlyYaml": "Фәкать YAML-файллар гына хуплана" + }, + "notifications": { + "importRetry": "Import failed, retrying with Clash proxy...", + "importFail": "Import failed even with Clash proxy", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "Профиль алмаштырылды", + "profileReactivated": "Профиль яңадан активлаштырылды", + "switchInterrupted": "Profile switch interrupted by new selection", + "batchDeleted": "Selected profiles deleted successfully" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "Профильләр" + }, + "components": { + "card": { + "labels": { + "clickToImport": "Click to import subscription" + } + }, + "fileInput": { + "chooseFile": "Файл сайлау" + }, + "menu": { + "home": "Home", + "select": "Сайлау", + "editInfo": "Мәгълүматны үзгәртү", + "editFile": "Файлны үзгәртү", + "editRules": "Кагыйдәләрне үзгәртү", + "editProxies": "Проксины үзгәртү", + "editGroups": "Прокси төркемнәрен үзгәртү", + "extendConfig": "Merge-ны үзгәртергә", + "extendScript": "Script-ны үзгәртергә", + "openFile": "Файлны ачу", + "update": "Яңарту", + "updateViaProxy": "Update via proxy" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "Last Update failed", + "nextUp": "Next Up", + "noSchedule": "No schedule", + "unknown": "Unknown", + "autoUpdateDisabled": "Auto update disabled" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "Профиль булдыру", + "edit": "Профильне үзгәртү" + }, + "fields": { + "type": "Төр", + "description": "Тасвирламалар", + "subscriptionUrl": "Подписка URL-ы", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "Яңарту интервалы", + "useSystemProxy": "Системалы проксины кулланып яңарту", + "useClashProxy": "Clash прокси кулланып яңарту", + "acceptInvalidCerts": "Дөрес булмаган сертификатларны кабул итү (Куркыныч)", + "allowAutoUpdate": "Allow Auto Update" + }, + "feedback": { + "notifications": { + "creationRetry": "Profile creation failed, retrying with Clash proxy...", + "creationSuccess": "Profile creation succeeded with Clash proxy" + } + } + }, + "proxiesEditor": { + "title": "Проксины үзгәртү", + "placeholders": { + "multiUri": "Берничә URI өчен яңа юл символын кулланыгыз (Base64 кодлавы ярдәм ителә)" + }, + "actions": { + "prepend": "Проксины өскә өстәү", + "append": "Проксины аска өстәү" + } + }, + "groupsEditor": { + "title": "Прокси төркемнәрен үзгәртү", + "errors": { + "nameRequired": "Төркем исеме кирәк", + "nameExists": "Әлеге төркем исеме бар инде" + }, + "fields": { + "type": "Төркем төре", + "name": "Төркем исеме", + "icon": "Прокси төркеме иконкасы", + "proxies": "Прокси куллану", + "provider": "Провайдер куллану", + "healthCheckUrl": "Сәламәтлекне тикшерү URL-ы", + "expectedStatus": "Көтелгән статус коды", + "interval": "Интервал", + "maxFailedTimes": "Иң күп хаталы тикшерү саны", + "interfaceName": "Интерфейс исеме", + "routingMark": "Маршрут билгесе", + "filter": "Фильтр", + "excludeFilter": "Фильтр аша чыгару", + "excludeType": "Чыгару төре", + "includeAll": "Барлык прокси һәм провайдерларны кертү", + "includeAllProxies": "Барлык проксины кертү", + "includeAllProviders": "Барлык провайдерларны кертү" + }, + "toggles": { + "lazy": "Сак режим (lazy)", + "disableUdp": "UDP'ны сүндерү", + "hidden": "Яшерен" + }, + "actions": { + "prepend": "Төркемне өскә өстәү", + "append": "Төркемне аска өстәү" + } + }, + "editor": { + "actions": { + "format": "Документны форматлау" + }, + "messages": { + "readOnly": "Уку режимында үзгәртү мөмкин түгел" + } + }, + "confirmDelete": { + "title": "Бетерүне раслагыз", + "message": "Бу гамәлне кире кайтарып булмый" + }, + "logViewer": { + "title": "Скрипт консоле" + } + } +} diff --git a/src/locales/tt/proxies.json b/src/locales/tt/proxies.json new file mode 100644 index 000000000..202044318 --- /dev/null +++ b/src/locales/tt/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "Rule", + "global": "Global", + "direct": "Direct" + }, + "actions": { + "toggleChain": "🔗 Чылбыр прокси", + "connect": "Connect", + "disconnect": "Disconnect", + "connecting": "Connecting...", + "clearChainConfig": "Delete Chain Config" + }, + "provider": { + "title": "Прокси провайдеры", + "actions": { + "updateAll": "Барысын да яңарту", + "update": "Яңарту" + } + }, + "rules": { + "title": "Proxy Rules", + "select": "Select Rules" + }, + "labels": { + "proxyCount": "Proxy Count", + "delayCheckReset": "Беркетелгәнне гамәлдән чыгару өчен задержканы тикшерү" + }, + "tooltips": { + "locate": "Урын", + "delayCheck": "Задержканы тикшерү", + "sortDefault": "Башлангыч итеп сортлау", + "sortDelay": "Задержка буенча сортлау", + "sortName": "Исем буенча сортлау", + "delayCheckUrl": "Задержканы тикшерү URL-ы", + "showBasic": "Прокси турында кыскача мәгълүмат", + "showDetail": "Прокси турында тулы мәгълүмат", + "filter": "Фильтр" + }, + "placeholders": { + "delayCheckUrl": "Задержканы тикшерү URL-ы" + }, + "chain": { + "header": "Chain Proxy Config", + "empty": "No proxy chain configured", + "instruction": "Click nodes in order to add to proxy chain", + "minimumNodes": "Chain proxy requires at least 2 nodes", + "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", + "connectFailed": "Failed to connect to proxy chain", + "disconnectFailed": "Failed to disconnect from proxy chain", + "duplicateNode": "Proxy node already exists in chain" + }, + "messages": { + "directMode": "Туры режим" + }, + "title": { + "default": "Прокси төркемнәре", + "chainMode": "Proxy Chain Mode" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "Проксины кулдан сайлау", + "url-test": "URL-тест задержкасына карап прокси сайлау", + "fallback": "Хата булган очракта башка проксига күчү", + "load-balance": "Трафикны баланслау нигезендә прокси тарату", + "relay": "Билгеле прокси чылбыры аша тапшыру" + }, + "policies": { + "DIRECT": "Туры чыгу", + "REJECT": "Сорауларны тоткарлау", + "REJECT-DROP": "Сорауларны кире кагу", + "PASS": "Туры килсә дә, бу кагыйдәне урап узу" + } + } + } +} diff --git a/src/locales/tt/rules.json b/src/locales/tt/rules.json new file mode 100644 index 000000000..f35446df9 --- /dev/null +++ b/src/locales/tt/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "Кагыйдә провайдеры", + "dialogTitle": "Кагыйдә провайдеры", + "actions": { + "updateAll": "Барысын да яңарту", + "update": "Яңарту" + } + }, + "title": "Кагыйдәләр" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "Кагыйдә төре", + "content": "Кагыйдә эчтәлеге", + "proxyPolicy": "Прокси сәясәте" + }, + "toggles": { + "noResolve": "Резолвсыз" + }, + "actions": { + "prependRule": "Кагыйдәне өскә өстәү", + "appendRule": "Кагыйдәне аска өстәү" + }, + "validation": { + "conditionRequired": "Кагыйдә шарты кирәк", + "invalidRule": "Яраксыз кагыйдә" + } + }, + "ruleTypes": { + "DOMAIN": "Домен исеменең тулы туры килүе", + "DOMAIN-SUFFIX": "Домен суффиксына туры килү", + "DOMAIN-KEYWORD": "Доменда төп сүзгә туры килү", + "DOMAIN-REGEX": "Доменны регекс аша туры китерү", + "GEOSITE": "Geosite исемлегендәге доменга туры килү", + "GEOIP": "IP-адресның ил коды буенча туры килү", + "SRC-GEOIP": "Чыганак IP-адресның ил коды буенча туры килү", + "IP-ASN": "IP-адрес ASN'ы буенча туры килү", + "SRC-IP-ASN": "Чыганак IP-адрес ASN'ы буенча туры килү", + "IP-CIDR": "IP-адреслар диапазонына туры килү", + "IP-CIDR6": "IPv6 адреслар диапазонына туры килү", + "SRC-IP-CIDR": "Чыганак IP-адреслар диапазонына туры килү", + "IP-SUFFIX": "IP-адрес суффиксына туры килү", + "SRC-IP-SUFFIX": "Чыганак IP-адрес суффиксына туры килү", + "SRC-PORT": "Чыганак портлар диапазонына туры килү", + "DST-PORT": "Максат портлар диапазонына туры килү", + "IN-PORT": "Керүче портка туры килү", + "DSCP": "DSCP тамгалавы (tproxy UDP өчен)", + "PROCESS-NAME": "Процесс исеменә туры килү (Android пакет исеме)", + "PROCESS-PATH": "Процесс юлына туры килү", + "PROCESS-NAME-REGEX": "Процесс исемен регекс белән туры китерү (Android пакет исеме)", + "PROCESS-PATH-REGEX": "Процесс юлын регекс белән туры китерү", + "NETWORK": "Транспорт протоколына (tcp/udp) туры килү", + "UID": "Linux USER ID'га туры килү", + "IN-TYPE": "Керүче тоташу төренә туры килү", + "IN-USER": "Керүче тоташу кулланучысына туры килү", + "IN-NAME": "Керүче тоташу исеменә туры килү", + "SUB-RULE": "Кушымча кагыйдә", + "RULE-SET": "Кагыйдәләр тупланмасына туры килү", + "AND": "Логик ҺӘМ", + "OR": "Логик ЯКИ", + "NOT": "Логик ТҮГЕЛ", + "MATCH": "Барлык сорауларга туры килә" + }, + "title": "Кагыйдәләрне үзгәртү" + } + } +} diff --git a/src/locales/tt/settings.json b/src/locales/tt/settings.json new file mode 100644 index 000000000..692c0b550 --- /dev/null +++ b/src/locales/tt/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "Документация", + "telegram": "Telegram каналы", + "github": "GitHub репозиториясе" + }, + "title": "Көйләүләр" + }, + "sections": { + "system": { + "title": "Система көйләүләре", + "toggles": { + "tunMode": "Tun режимы (виртуаль челтәр адаптеры)", + "systemProxy": "Системалы прокси" + }, + "tooltips": { + "autoLaunchAdmin": "Administrator mode may not support auto launch", + "silentStart": "Программаны фоновый режимда, тәрәзәсез эшләтеп җибәрү" + }, + "fields": { + "autoLaunch": "Автоматик башлау", + "silentStart": "Тын башлау" + }, + "notifications": { + "tunMode": { + "autoDisabled": "TUN Mode automatically disabled due to service unavailable", + "autoDisableFailed": "Failed to disable TUN Mode automatically" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "Системалы прокси көйләүләрен үзгәртү рөхсәтен бирегез. Әгәр рөхсәт алу мөмкин түгел икән, прокси көйләүләрен кулдан үзгәртегез", + "tunMode": "Tun режимы бөтен системаның трафигын тотып ала. Аны кабызган очракта системалы проксины аерым кабызу таләп ителми.", + "tunUnavailable": "TUN requires Service Mode or Admin Mode" + }, + "actions": { + "installService": "Хезмәтне урнаштыру", + "uninstallService": "Uninstall Service" + }, + "fields": { + "systemProxy": "Системалы прокси", + "tunMode": "Tun режимы (виртуаль челтәр адаптеры)" + } + }, + "externalController": { + "title": "Тышкы контроллер адресы", + "fields": { + "enable": "Enable External Controller", + "address": "Тышкы контроллер адресы", + "secret": "Серсүз" + }, + "placeholders": { + "address": "Required", + "secret": "Тавсия ителә" + }, + "tooltips": { + "copy": "Copy to clipboard" + }, + "messages": { + "addressRequired": "Controller address cannot be empty", + "secretRequired": "Secret cannot be empty", + "copyFailed": "Failed to copy", + "controllerCopied": "Controller address copied to clipboard", + "secretCopied": "Secret copied to clipboard" + } + }, + "externalCors": { + "title": "External Cors Configuration", + "fields": { + "allowPrivateNetwork": "Allow private network access", + "allowedOrigins": "Allowed Origins" + }, + "placeholders": { + "origin": "Please enter a valid url" + }, + "actions": { + "add": "Add" + }, + "messages": { + "alwaysIncluded": "Always included origins: {{urls}}" + }, + "tooltips": { + "open": "External Cors Settings" + } + }, + "appearance": { + "light": "Light", + "dark": "Dark", + "system": "System" + }, + "clash": { + "title": "Clash көйләүләре", + "form": { + "fields": { + "allowLan": "Локаль челтәргә рөхсәт", + "dnsOverwrite": "DNS Overwrite", + "ipv6": "IPv6", + "unifiedDelay": "Бердәм задержка", + "logLevel": "Лог дәрәҗәсе", + "portConfig": "Порт көйләүләре", + "external": "Тышкы", + "webUI": "Веб-интерфейс", + "clashCore": "Clash ядросы", + "openUwpTool": "UWP инструментын ачу", + "updateGeoData": "GeoData яңарту" + }, + "tooltips": { + "networkInterface": "Челтәр интерфейсы", + "unifiedDelay": "Бердәм задержка актив булганда, төрле типтагы узеллар өчен икеләтә тест башкарыла, TCP установканы раслау аермаларын тигезләү максатында", + "logLevel": "Бу фәкать сервис режимында эшләгән вакытта системалы журнал файлларына кагыла", + "openUwpTool": "Windows 8'дән башлап UWP кушымталары (Microsoft Store кебек) локаль хосттагы челтәр хезмәтләренә турыдан-туры тоташа алмый. Бу инструмент әлеге чикләүне әйләнеп узарга ярдәм итә" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge Төп көйләүләр", + "actions": { + "browse": "Карау" + }, + "trayOptions": { + "showMainWindow": "Төп тәрәзәне күрсәтү", + "showTrayMenu": "Show Tray Menu", + "disable": "Сүндерү" + }, + "fields": { + "language": "Тел", + "themeMode": "Теманың режимы", + "trayClickEvent": "Трейдагы басу вакыйгасы", + "copyEnvType": "Env төрен күчереп алу", + "startPage": "Баш бит", + "startupScript": "Башлану скрипты", + "themeSetting": "Тема көйләүләре", + "layoutSetting": "Расположение көйләүләре", + "misc": "Өстәмә көйләүләр", + "hotkeySetting": "Клавиатура төймәләре (hotkey) көйләүләре" + } + }, + "advanced": { + "title": "Verge Киңәйтелгән көйләүләр", + "tooltips": { + "backupInfo": "WebDAV аша конфигурация файлын саклауны хуплый", + "openConfDir": "Әгәр программада хаталар чыкса, бу папкадагы файлларны саклап калыгыз да, аннары барысын да бетереп, программаны яңадан башлагыз", + "liteMode": "GUI-ны ябыгыз һәм бары тик төшне генә эшләтеп калдырыгыз" + }, + "actions": { + "copyVersion": "Copy Version" + }, + "notifications": { + "latestVersion": "Сездә иң соңгы версия урнаштырылган", + "versionCopied": "Version copied to clipboard" + }, + "fields": { + "backupSetting": "Резерв копия көйләүләре", + "runtimeConfig": "Агымдагы конфигурация", + "openConfDir": "Кушымта папкасын ачу", + "openCoreDir": "Ядро сакланган папканы ачу", + "openLogsDir": "Логлар папкасын ачу", + "checkUpdates": "Яңартуларны тикшерү", + "openDevTools": "Разработчик коралларын ачу", + "liteModeSettings": "LightWeight Mode Settings", + "exit": "Чыгу", + "exportDiagnostics": "Export Diagnostic Info", + "vergeVersion": "Verge версиясе" + } + }, + "theme": { + "title": "Тема көйләүләре", + "fields": { + "primaryColor": "Төп төс", + "secondaryColor": "Икенче төс", + "primaryText": "Primary Text", + "secondaryText": "Secondary Text", + "infoColor": "Мәгълүмат төсе", + "warningColor": "Кисәтү төсе", + "errorColor": "Хата төсе", + "successColor": "Уңыш төсе", + "fontFamily": "Шрифтлар гаиләсе", + "cssInjection": "CSS кертү" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "Расположение көйләүләре", + "fields": { + "preferSystemTitlebar": "Prefer System Titlebar", + "trafficGraph": "Трафик графигы", + "memoryUsage": "Хәтер куллану", + "proxyGroupIcon": "Прокси төркеме иконкасы", + "hoverNavigator": "Hover Jump Navigator", + "hoverNavigatorDelay": "Hover Jump Navigator Delay", + "navIcon": "Навигация иконкасы", + "trayIcon": "Трей иконкасы", + "showProxyGroupsInline": "Show Proxy Groups Inline", + "commonTrayIcon": "Гомуми трей иконкасы", + "systemProxyTrayIcon": "Системалы прокси иконкасы", + "tunTrayIcon": "Tun (виртуаль адаптер) иконкасы", + "enableTrayIcon": "Enable Tray Icon", + "enableTraySpeed": "Трей скоростьне үстерү" + }, + "tooltips": { + "hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters", + "hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds" + }, + "options": { + "icon": { + "monochrome": "Монохром", + "colorful": "Төсле", + "disable": "Сүндерү" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "Порт көйләүләре", + "fields": { + "mixed": "Катнаш прокси порты", + "socks": "Socks прокси порты", + "http": "HTTP(s) прокси порты", + "redir": "Redir — үтә күренмәле прокси порты", + "tproxy": "Tproxy — үтә күренмәле прокси порты" + }, + "actions": { + "random": "Очраклы порт" + }, + "messages": { + "saved": "Port settings saved", + "saveFailed": "Failed to save port settings" + } + }, + "clashCore": { + "variants": { + "release": "Рәсми версия", + "alpha": "Альфа-версия" + } + }, + "liteMode": { + "title": "LightWeight Mode Settings", + "actions": { + "enterNow": "Enter LightWeight Mode Now" + }, + "toggles": { + "autoEnter": "Auto Enter LightWeight Mode" + }, + "tooltips": { + "autoEnter": "Enable to automatically activate LightWeight Mode after the window is closed for a period of time" + }, + "fields": { + "delay": "Auto Enter LightWeight Mode Delay" + }, + "messages": { + "autoEnterHint": "When closing the window, LightWeight Mode will be automatically activated after {{n}} minutes" + } + }, + "backup": { + "title": "Резерв копия көйләүләре", + "tabs": { + "local": "Local backup", + "webdav": "WebDAV backup" + }, + "actions": { + "selectTarget": "Select backup target", + "backup": "Резерв копия", + "export": "Export", + "exportBackup": "Export Backup", + "deleteBackup": "Резерв копияне бетерү", + "restore": "Кайтару", + "restoreBackup": "Резерв копияне кайтару" + }, + "fields": { + "webdavUrl": "WebDAV сервер URL-ы (http(s)://)", + "username": "Кулланучы исеме", + "info": "Backups are stored locally in the application data directory. Use the list below to restore or delete backups." + }, + "messages": { + "webdavUrlRequired": "WebDAV адресы буш булырга тиеш түгел", + "invalidWebdavUrl": "WebDAV адресы дөрес түгел", + "usernameRequired": "Кулланучы исеме буш булмаска тиеш", + "passwordRequired": "Пароль буш булмаска тиеш", + "webdavConfigSaved": "WebDAV көйләүләре сакланды", + "webdavConfigSaveFailed": "WebDAV көйләүләрен саклап булмады: {{error}}", + "backupCreated": "Резерв копия уңышлы ясалды", + "backupFailed": "Резерв копия хата белән төгәлләнде: {{error}}", + "localBackupCreated": "Local backup created successfully", + "localBackupFailed": "Local backup failed", + "restoreSuccess": "Уңышлы кайтарылды, кушымта 1 секундтан яңадан башланачак", + "localBackupExported": "Local backup exported successfully", + "localBackupExportFailed": "Failed to export local backup", + "confirmDelete": "Бу резерв копия файлын бетерергә телисезме?", + "confirmRestore": "Бу резерв копия файлын кире кайтарырга телисезме?" + }, + "table": { + "filename": "Файл исеме", + "backupTime": "Резерв копия вакыты", + "actions": "Гамәлләр", + "noBackups": "Резерв копияләр юк", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "Өстәмә көйләүләр", + "fields": { + "appLogLevel": "Кушымта журналы дәрәҗәсе", + "appLogMaxSize": "App Log Max Size", + "appLogMaxCount": "App Log Max Count", + "autoCloseConnections": "Тоташуларны автоматик ябу", + "autoCheckUpdate": "Яңартуларны автоматик тикшерү", + "enableBuiltinEnhanced": "Эчке камилләштерүне кабызу", + "proxyLayoutColumns": "Прокси күрсәтү баганалары саны", + "autoLogClean": "Логларны автоматик чистарту", + "autoDelayDetection": "Автоматик тоткарлык ачыклау", + "defaultLatencyTest": "Тоткарлануны тикшерү сылтамасы (defaults)", + "defaultLatencyTimeout": "Тоткарлануның стандарт таймауты" + }, + "tooltips": { + "autoCloseConnections": "Прокси төркеме яисә режимын үзгәрткәндә актив тоташуларны өзү", + "enableBuiltinEnhanced": "Конфигурация файлы белән туры килә торган өстәмә оптимизация", + "autoDelayDetection": "Фон режимында хәзерге төен тоткарлыгын периодик тикшерә", + "defaultLatencyTest": "Бу фәкать клиентның HTTP сораулары тесты өчен кулланыла, конфигурация файлына йогынты ясамый" + }, + "options": { + "proxyLayoutColumns": { + "auto": "Авто баганалар" + }, + "autoLogClean": { + "never": "Беркайчан чистартмаска", + "retainDays": "{{n}} көн саклау" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "Релизлар битенә күчү", + "update": "Яңарту" + }, + "messages": { + "portableError": "Портатив версиядә кушымта эчендә яңарту хупланмый, кулдан төшереп алыгыз", + "breakChangeError": "Бу зур яңарту, ул кушымта эчендә яңартылмый. Борып алып ташлап, яңадан урнаштыру сорала." + } + }, + "sysproxy": { + "title": "Системалы прокси көйләүләре", + "fieldsets": { + "currentStatus": "Агымдагы системалы прокси" + }, + "fields": { + "enableStatus": "Активлаштыру статусы", + "serverAddr": "Сервер адресы", + "pacUrl": "PAC адресы", + "proxyHost": "Прокси хосты", + "usePacMode": "PAC режимын куллану", + "proxyGuard": "Прокси саклаучы", + "guardDuration": "Саклау вакыты", + "alwaysUseDefaultBypass": "Һәрвакыт төп Bypass-ны куллану", + "proxyBypass": "Проксины әйләнеп узу:", + "bypass": "Әйләнеп узу:", + "pacScriptContent": "PAC скрипты эчтәлеге" + }, + "tooltips": { + "proxyGuard": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз" + }, + "messages": { + "durationTooShort": "Прокси-демон эш вакыты 1 секундтан ким була алмый", + "invalidBypass": "Дөрес булмаган Bypass форматы", + "invalidProxyHost": "Прокси хосты форматы дөрес түгел" + }, + "actions": { + "editPac": "Үзгәртү PAC" + } + }, + "tun": { + "title": "Tun режимы (виртуаль челтәр адаптеры)", + "fields": { + "stack": "Стек", + "device": "Device Name", + "autoRoute": "Авто-маршрутлау", + "strictRoute": "Катгый маршрутлау", + "autoDetectInterface": "Интерфейсны автоматик ачыклау", + "dnsHijack": "DNS'ны үзгәртеп тоту (hijack)", + "mtu": "MTU (макс. тапшыру берәмлеге)" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "Көйләүләр кулланылды" + } + }, + "dns": { + "dialog": { + "title": "DNS Overwrite", + "warning": "If you are not familiar with these settings, please do not modify them and keep DNS Overwrite enabled" + }, + "sections": { + "general": "DNS Settings", + "fallbackFilter": "Fallback Filter Settings", + "hosts": "Hosts Settings" + }, + "fields": { + "enable": "Enable DNS", + "listen": "DNS Listen", + "enhancedMode": "Enhanced Mode", + "fakeIpRange": "Fake IP Range", + "fakeIpFilterMode": "Fake IP Filter Mode", + "ipv6": { + "label": "IPv6", + "description": "Enable IPv6 DNS resolution" + }, + "preferH3": { + "label": "Prefer H3", + "description": "DNS DOH uses HTTP/3" + }, + "respectRules": { + "label": "Respect Rules", + "description": "DNS connections follow routing rules" + }, + "useHosts": { + "label": "Use Hosts", + "description": "Enable to resolve hosts through hosts file" + }, + "useSystemHosts": { + "label": "Use System Hosts", + "description": "Enable to resolve hosts through system hosts file" + }, + "directPolicy": { + "label": "Direct Nameserver Follow Policy", + "description": "Whether to follow nameserver policy" + }, + "defaultNameserver": { + "label": "Default Nameserver", + "description": "Default DNS servers used to resolve DNS servers" + }, + "nameserver": { + "label": "Nameserver", + "description": "List of DNS servers, comma separated" + }, + "fallback": { + "label": "Fallback", + "description": "List of fallback DNS servers, comma separated" + }, + "proxy": { + "label": "Proxy Server Nameserver", + "description": "DNS servers for proxy node domain resolution" + }, + "directNameserver": { + "label": "Direct Nameserver", + "description": "DNS servers for direct exit domain resolution, supports 'system' keyword, comma separated" + }, + "fakeIpFilter": { + "label": "Fake IP Filter", + "description": "Domains that skip fake IP resolution, comma separated" + }, + "nameserverPolicy": { + "label": "Nameserver Policy", + "description": "Domain-specific DNS server, multiple servers separated by semicolons, format: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP Filtering", + "description": "Enable GeoIP filtering for fallback" + }, + "geoipCode": "GeoIP Code", + "fallbackIpCidr": { + "label": "Fallback IP CIDR", + "description": "IP CIDRs not using fallback servers, comma separated" + }, + "fallbackDomain": { + "label": "Fallback Domain", + "description": "Domains using fallback servers, comma separated" + }, + "hosts": { + "label": "Hosts", + "description": "Custom domain to IP or domain mapping" + } + }, + "messages": { + "saved": "DNS settings saved", + "configError": "DNS configuration error:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "Invalid YAML format" + } + }, + "webUI": { + "actions": { + "openUrl": "URL ачарга" + }, + "title": "Веб-интерфейс", + "messages": { + "supportedPlaceholders": "%host, %port, %secret макросларын хуплау", + "placeholderInstruction": "Хост, порт, серсүзне %host, %port, %secret белән алмаштырыгыз" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "Глобаль Хоткейны кушу" + }, + "title": "Клавиатура төймәләре (hotkey) көйләүләре", + "functions": { + "rule": "Кагыйдәләр режимы", + "global": "Глобаль режим", + "openOrCloseDashboard": "Панельне ачу/ябу", + "toggleSystemProxy": "Системалы проксины кабызу/сүндерү", + "toggleTunMode": "Tun режимын кабызу/сүндерү", + "entryLightweightMode": "Entry Lightweight Mode", + "direct": "Туры режим" + } + }, + "password": { + "prompts": { + "enterRoot": "root паролен языгыз" + } + }, + "networkInterface": { + "title": "Челтәр интерфейсы", + "fields": { + "ipAddress": "IP адресы", + "macAddress": "MAC адресы" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "Clash ядросы яңадан башланды", + "versionUpdated": "Ядро версиясе яңартылды", + "alreadyLatestVersion": "Сез инде ядроның соңгы версиясен кулланасыз", + "changeSuccess": "Ядро уңышлы алыштырылды", + "changeFailed": "Ядро алыштыру уңышсыз булды", + "geoDataUpdated": "GeoData яңартылды" + }, + "clashService": { + "installSuccess": "Сервис уңышлы урнаштырылды", + "uninstallSuccess": "Сервис уңышлы салдырылды" + }, + "updater": { + "withClashProxySuccess": "Update with Clash proxy successfully", + "withClashProxyFailed": "Update failed even with Clash proxy" + } + } + }, + "statuses": { + "clash": { + "stopping": "Stopping Core...", + "restarting": "Restarting Core..." + }, + "clashService": { + "installing": "Хезмәт урнаштырыла...", + "uninstalling": "Uninstalling Service..." + } + } +} diff --git a/src/locales/tt/shared.json b/src/locales/tt/shared.json new file mode 100644 index 000000000..88199bd5f --- /dev/null +++ b/src/locales/tt/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "Баш тарту", + "close": "Ябу", + "confirm": "Растау", + "save": "Саклау", + "delete": "Бетерү", + "edit": "Үзгәртү", + "new": "Яңа", + "enable": "Кушу", + "upgrade": "Яңарту", + "restart": "Перезапуск", + "resetToDefault": "Башлангычка кайтару", + "refresh": "Яңарту", + "retry": "Retry", + "refreshPage": "Refresh Page", + "showDetails": "Show Details", + "hideDetails": "Hide Details", + "listView": "Исемлек күзаллау", + "tableView": "Таблица күзаллау", + "pause": "Туктау", + "resume": "Дәвам", + "closeAll": "Барысын да ябу", + "clear": "Чистарту" + }, + "labels": { + "updateAt": "Яңартылган вакыт", + "timeout": "Timeout", + "icon": "Иконка", + "name": "Исем", + "readOnly": "Уку режимы гына", + "expireTime": "Тамамлану вакыты", + "updateTime": "Яңарту вакыты", + "usedTotal": "Кулланылган / Барлыгы", + "from": "Каян", + "password": "Пароль", + "retryAttempts": "Retry attempts", + "downloaded": "Йөкләнгән", + "uploaded": "Чыгарылган" + }, + "statuses": { + "enabled": "Кушылган", + "disabled": "Сүнгән", + "saving": "Saving...", + "empty": "Буш" + }, + "units": { + "milliseconds": "Миллисекундлар", + "seconds": "Секундлар", + "minutes": "Минутлар", + "kilobytes": "KB", + "files": "Files" + }, + "placeholders": { + "filter": "Фильтр шартлары", + "matchCase": "Регистрны исәпкә алу", + "matchWholeWord": "Сүзнең тулы туры килүе", + "useRegex": "Регуляр выражениеләр куллану" + }, + "validation": { + "invalidRegex": "Invalid regular expression" + }, + "window": { + "maximize": "Зурайту", + "minimize": "Кечерәйтү" + }, + "editorModes": { + "visualization": "Визуализация", + "advanced": "Өстәмә" + }, + "feedback": { + "errors": { + "trafficStats": "Traffic Statistics Error", + "trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes." + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "Профиль уңышлы импортланды", + "importSubscriptionSuccess": "Import subscription successful", + "importWithClashProxy": "Profile Imported with Clash proxy", + "updateAvailable": "Update Available", + "saved": "Saved successfully", + "common": { + "copySuccess": "Күчерелде", + "saveSuccess": "Configuration saved successfully", + "saveFailed": "Failed to save configuration" + } + }, + "validation": { + "config": { + "failed": "Язылу көйләү тикшерүе уңышсыз, көйләү файлын тикшерегез, үзгәрешләр кире кайтарылды, хата:", + "bootFailed": "Йөкләү вакытында көйләү тикшерүе уңышсыз, стандарт көйләү кулланылды, көйләү файлын тикшерегез, хата:", + "coreChangeFailed": "Ядро алыштырганда көйләү тикшерүе уңышсыз, стандарт көйләү кулланылды, көйләү файлын тикшерегез, хата:", + "processTerminated": "Тикшерү процессы туктатылды" + }, + "script": { + "syntaxError": "Скрипт синтаксик хатасы, үзгәрешләр кире кайтарылды", + "missingMain": "Скрипт хатасы, үзгәрешләр кире кайтарылды", + "fileNotFound": "Файл табылмады, үзгәрешләр кире кайтарылды", + "fileError": "Скрипт файлы хатасы, үзгәрешләр кире кайтарылды" + }, + "yaml": { + "syntaxError": "YAML syntax error, changes reverted", + "readError": "YAML read error, changes reverted", + "mappingError": "YAML mapping error, changes reverted", + "keyError": "YAML key error, changes reverted", + "generalError": "YAML error, changes reverted" + }, + "merge": { + "syntaxError": "Merge file syntax error, changes reverted", + "mappingError": "Merge file mapping error, changes reverted", + "keyError": "Merge file key error, changes reverted", + "generalError": "Merge file error, changes reverted" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/tt/tests.json b/src/locales/tt/tests.json new file mode 100644 index 000000000..efc03a9ad --- /dev/null +++ b/src/locales/tt/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "Барчасын тестлау" + }, + "title": "Тест" + }, + "components": { + "item": { + "actions": { + "test": "Тест" + } + } + }, + "modals": { + "test": { + "title": { + "create": "Тест булдыру", + "edit": "Тестны үзгәртү" + }, + "fields": { + "url": "Тест URL-ы" + } + } + }, + "statuses": { + "test": { + "pending": "Pending", + "yes": "Yes", + "no": "No", + "failed": "Failed", + "completed": "Completed", + "disallowedIsp": "Disallowed ISP", + "originalsOnly": "Originals Only", + "noDisney": "No (IP Banned By Disney+)", + "unsupportedRegion": "Unsupported Country/Region", + "failedNetwork": "Failed (Network Connection)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "Testing..." + }, + "empty": "No unlock test items", + "messages": { + "detectionFailedWithName": "{{name}} өчен ачыклау уңышсыз булды", + "detectionTimeout": "Detection timeout or failed" + }, + "title": "Unlock Test" + } + } +} diff --git a/src/locales/zh.json b/src/locales/zh.json deleted file mode 100644 index f8b161d75..000000000 --- a/src/locales/zh.json +++ /dev/null @@ -1,719 +0,0 @@ -{ - "millis": "毫秒", - "seconds": "秒", - "mins": "分钟", - "Back": "返回", - "Close": "关闭", - "Cancel": "取消", - "Confirm": "确认", - "Maximize": "最大化", - "Minimize": "最小化", - "Format document": "格式化文档", - "Empty": "空空如也", - "New": "新建", - "Edit": "编辑", - "Save": "保存", - "Delete": "删除", - "Enable": "启用", - "Disable": "禁用", - "Label-Home": "首 页", - "Label-Proxies": "代 理", - "Label-Profiles": "订 阅", - "Label-Connections": "连 接", - "Label-Rules": "规 则", - "Label-Logs": "日 志", - "Label-Unlock": "测 试", - "Label-Settings": "设 置", - "Proxies": "代理", - "Proxy Groups": "代理组", - "Proxy Chain Mode": "链式代理模式", - "Connect": "连接", - "Connecting...": "连接中...", - "Disconnect": "断开", - "Failed to connect to proxy chain": "连接链式代理失败", - "Proxy Provider": "代理集合", - "Proxy Count": "节点数量", - "Update All": "更新全部", - "Update At": "更新于", - "rule": "规则", - "global": "全局", - "direct": "直连", - "Chain Proxy": "🔗 链式代理", - "Chain Proxy Config": "代理链配置", - "Proxy Rules": "代理规则", - "Select Rules": "选择规则", - "Click nodes in order to add to proxy chain": "顺序点击节点添加到代理链中", - "No proxy chain configured": "暂无代理链配置", - "Proxy Order": "代理顺序", - "timeout": "超时", - "Clear All": "清除全部", - "script": "脚本", - "locate": "当前节点", - "Delay check": "延迟测试", - "Sort by default": "默认排序", - "Sort by delay": "按延迟排序", - "Sort by name": "按名称排序", - "Delay check URL": "延迟测试链接", - "Delay check to cancel fixed": "进行延迟测试,以取消固定", - "Proxy basic": "隐藏节点细节", - "Proxy detail": "展示节点细节", - "Profiles": "订阅", - "Update All Profiles": "更新所有订阅", - "View Runtime Config": "查看运行时订阅", - "Reactivate Profiles": "重新激活订阅", - "Paste": "粘贴", - "Profile URL": "订阅文件链接", - "Import": "导入", - "From": "来自", - "Update Time": "更新时间", - "Used / Total": "已使用 / 总量", - "Expire Time": "到期时间", - "Create Profile": "新建配置", - "Edit Profile": "编辑配置", - "Edit Proxies": "编辑节点", - "Use newlines for multiple uri": "多条 URI 请使用换行分隔(支持 Base64 编码)", - "Edit Rules": "编辑规则", - "Rule Type": "规则类型", - "Rule Content": "规则内容", - "Proxy Policy": "代理策略", - "No Resolve": "跳过 DNS 解析", - "Prepend Rule": "添加前置规则", - "Append Rule": "添加后置规则", - "Prepend Group": "添加前置代理组", - "Append Group": "添加后置代理组", - "Prepend Proxy": "添加前置代理节点", - "Append Proxy": "添加后置代理节点", - "Rule Condition Required": "规则条件缺失", - "Invalid Rule": "无效规则", - "Advanced": "高级", - "Visualization": "可视化", - "DOMAIN": "匹配完整域名", - "DOMAIN-SUFFIX": "匹配域名后缀", - "DOMAIN-KEYWORD": "匹配域名关键字", - "DOMAIN-REGEX": "匹配域名正则表达式", - "GEOSITE": "匹配 Geosite 内的域名", - "GEOIP": "匹配 IP 所属国家代码", - "SRC-GEOIP": "匹配来源 IP 所属国家代码", - "IP-ASN": "匹配 IP 所属 ASN", - "SRC-IP-ASN": "匹配来源 IP 所属 ASN", - "IP-CIDR": "匹配 IP 地址范围", - "IP-CIDR6": "匹配 IP 地址范围", - "SRC-IP-CIDR": "匹配来源 IP 地址范围", - "IP-SUFFIX": "匹配 IP 后缀范围", - "SRC-IP-SUFFIX": "匹配来源 IP 后缀范围", - "SRC-PORT": "匹配请求来源端口范围", - "DST-PORT": "匹配请求目标端口范围", - "IN-PORT": "匹配入站端口", - "DSCP": "DSCP标记(仅限 TPROXY UDP 入站)", - "PROCESS-NAME": "匹配进程名称(Android 包名)", - "PROCESS-PATH": "匹配完整进程路径", - "PROCESS-NAME-REGEX": "正则匹配完整进程名称(Android 包名)", - "PROCESS-PATH-REGEX": "正则匹配完整进程路径", - "NETWORK": "匹配传输协议 (TCP/UDP)", - "UID": "匹配 Linux USER ID", - "IN-TYPE": "匹配入站类型", - "IN-USER": "匹配入站用户名", - "IN-NAME": "匹配入站名称", - "SUB-RULE": "子规则", - "RULE-SET": "匹配规则集", - "AND": "逻辑和", - "OR": "逻辑或", - "NOT": "逻辑非", - "MATCH": "匹配所有请求", - "DIRECT": "直连", - "REJECT": "拦截请求", - "REJECT-DROP": "抛弃请求", - "PASS": "跳过此规则", - "Edit Groups": "编辑代理组", - "Group Type": "代理组类型", - "select": "手动选择代理", - "url-test": "根据URL测试延迟选择代理", - "fallback": "不可用时切换到另一个代理", - "load-balance": "根据负载均衡分配代理", - "relay": "根据定义的代理链传递", - "Group Name": "代理组组名", - "Use Proxies": "引入代理", - "Use Provider": "引入代理集合", - "Health Check Url": "健康检查测试地址", - "Expected Status": "期望状态码", - "Interval": "检查间隔", - "Lazy": "懒惰状态", - "Timeout": "超时时间", - "Max Failed Times": "最大失败次数", - "Interface Name": "出站接口", - "Routing Mark": "路由标记", - "Include All": "引入所有出站代理、代理集合", - "Include All Providers": "引入所有代理集合", - "Include All Proxies": "引入所有出站代理", - "Exclude Filter": "排除节点", - "Exclude Type": "排除节点类型", - "Disable UDP": "禁用 UDP", - "Hidden": "隐藏代理组", - "Group Name Required": "代理组名称不能为空", - "Group Name Already Exists": "代理组名称已存在", - "Extend Config": "扩展覆写配置", - "Extend Script": "扩展脚本", - "Global Merge": "全局扩展覆写配置", - "Global Script": "全局扩展脚本", - "Type": "类型", - "Name": "名称", - "Descriptions": "描述", - "Subscription URL": "订阅链接", - "Update Interval": "更新间隔", - "Choose File": "选择文件", - "Use System Proxy": "使用系统代理更新", - "Use Clash Proxy": "使用内核代理更新", - "Accept Invalid Certs (Danger)": "允许无效证书(危险)", - "Refresh": "刷新", - "Home": "首页", - "Select": "使用", - "Edit Info": "编辑信息", - "Edit File": "编辑文件", - "Open File": "打开文件", - "Update": "更新", - "Update via proxy": "更新(代理)", - "Update(Proxy)": "更新(代理)", - "Confirm deletion": "确认删除", - "This operation is not reversible": "此操作不可逆", - "Script Console": "脚本控制台输出", - "To Top": "移到最前", - "To End": "移到末尾", - "Connections": "连接", - "Table View": "表格视图", - "List View": "列表视图", - "Close All": "关闭全部", - "Close All Connections": "关闭所有连接", - "Upload": "上传", - "Download": "下载", - "Download Speed": "下载速度", - "Upload Speed": "上传速度", - "Host": "主机", - "Downloaded": "下载量", - "Uploaded": "上传量", - "DL Speed": "下载速度", - "UL Speed": "上传速度", - "Active Connections": "活跃连接", - "Chains": "链路", - "Rule": "规则", - "Process": "进程", - "Time": "连接时间", - "Source": "源地址", - "Destination": "目标地址", - "DestinationPort": "目标端口", - "Close Connection": "关闭连接", - "Rules": "规则", - "Rule Provider": "规则集合", - "Logs": "日志", - "Pause": "暂停", - "Resume": "继续", - "Clear": "清除", - "Test": "测试", - "Test All": "测试全部", - "Testing...": "测试中...", - "Create Test": "新建测试", - "Edit Test": "编辑测试", - "Icon": "图标", - "Test URL": "测试地址", - "Settings": "设置", - "System Setting": "系统设置", - "Tun Mode": "虚拟网卡模式", - "TUN requires Service Mode": "TUN 模式需要安装服务", - "Install Service": "安装服务", - "Install Service failed": "安装服务失败", - "Uninstall Service": "卸载服务", - "Restart Core failed": "重启核心失败", - "Reset to Default": "重置为默认值", - "Tun Mode Info": "TUN(虚拟网卡)模式接管系统所有流量,启用时无须打开系统代理", - "TUN requires Service Mode or Admin Mode": "TUN 模式需要安装服务模式或管理员模式", - "TUN Mode automatically disabled due to service unavailable": "由于服务不可用,TUN 模式已自动关闭", - "Failed to disable TUN Mode automatically": "自动关闭 TUN 模式失败", - "System Proxy Enabled": "系统代理已启用,您的应用将通过代理访问网络", - "System Proxy Disabled": "系统代理已关闭,建议大多数用户打开此选项", - "TUN Mode Enabled": "TUN 模式已启用,应用将通过虚拟网卡访问网络", - "TUN Mode Disabled": "TUN 模式已关闭,适用于特殊应用", - "TUN Mode Service Required": "TUN模式需要服务模式,请先安装服务", - "TUN Mode Intercept Info": "TUN模式可以接管所有应用流量,适用于特殊不遵循系统代理设置的应用", - "Core communication error": "内核通信错误", - "Rule Mode Description": "基于预设规则智能判断流量走向,提供灵活的代理策略", - "Global Mode Description": "所有流量均通过代理服务器,适用于需要全局科学上网的场景", - "Direct Mode Description": "所有流量不经过代理节点,但经过Clash内核转发连接目标服务器,适用于需要通过内核进行分流的特定场景", - "Stack": "TUN 模式堆栈", - "System and Mixed Can Only be Used in Service Mode": "System 和 Mixed 只能在服务模式下使用", - "Device": "TUN 网卡名称", - "Auto Route": "自动设置全局路由", - "Strict Route": "严格路由", - "Auto Detect Interface": "自动选择流量出口接口", - "DNS Hijack": "DNS 劫持", - "MTU": "最大传输单元", - "Service Mode": "服务模式", - "Service Mode Info": "启用 TUN 模式前请安装服务模式,该服务启动的内核进程可获得安装虚拟网卡(TUN 模式)的权限", - "Current State": "当前状态", - "pending": "等待中", - "installed": "已安装", - "uninstall": "未安装", - "active": "已激活", - "unknown": "未知", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "提示信息: 请确保 Clash Verge Service 已安装并启用", - "Install": "安装", - "Uninstall": "卸载", - "Disable Service Mode": "禁用服务模式", - "System Proxy": "系统代理", - "System Proxy Info": "修改操作系统的代理设置,如果开启失败,可手动修改操作系统的代理设置", - "System Proxy Setting": "系统代理设置", - "Current System Proxy": "当前系统代理", - "Enable status": "开启状态:", - "Enabled": "已启用", - "Disabled": "未启用", - "Server Addr": "服务地址:", - "Proxy Host": "代理主机", - "Invalid Proxy Host Format": "代理主机格式无效", - "Not available": "不可用", - "Proxy Guard": "系统代理守卫", - "Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置", - "Guard Duration": "代理守卫间隔", - "Always use Default Bypass": "始终使用默认绕过", - "Use Bypass Check": "启用代理绕过检查", - "Proxy Bypass": "代理绕过设置:", - "Bypass": "当前绕过:", - "Use PAC Mode": "使用 PAC 模式", - "PAC Script Content": "PAC 脚本内容", - "PAC URL": "PAC 地址:", - "Auto Launch": "开机自启", - "Administrator mode may not support auto launch": "管理员模式可能不支持开机自启", - "Silent Start": "静默启动", - "Silent Start Info": "程序启动时以后台模式运行,不显示程序面板", - "Hover Jump Navigator": "悬浮跳转导航", - "Hover Jump Navigator Info": "鼠标悬停在字母上时自动滚动到对应代理组", - "Hover Jump Navigator Delay": "悬浮跳转导航延迟", - "Hover Jump Navigator Delay Info": "鼠标悬停后触发自动跳转前等待的毫秒数", - "TG Channel": "Telegram 频道", - "Manual": "使用手册", - "Github Repo": "GitHub 项目地址", - "Clash Setting": "Clash 设置", - "Allow Lan": "局域网连接", - "Network Interface": "网络接口", - "Ip Address": "IP 地址", - "Mac Address": "MAC 地址", - "IPv6": "IPv6", - "Unified Delay": "统一延迟", - "Unified Delay Info": "开启统一延迟时,会进行两次延迟测试,以消除连接握手等带来的不同类型节点的延迟差异", - "Log Level": "日志等级", - "Log Level Info": "仅对日志目录 Service 文件夹下的内核日志文件生效", - "Port Config": "端口设置", - "Random Port": "随机端口", - "Mixed Port": "混合代理端口", - "Socks Port": "SOCKS 代理端口", - "Http Port": "HTTP(S) 代理端口", - "Redir Port": "Redir 透明代理端口", - "Tproxy Port": "Tproxy 透明代理端口", - "Port settings saved": "端口设置已保存", - "Failed to save port settings": "端口设置保存失败", - "External": "外部控制", - "Enable External Controller": "启用外部控制器", - "External Controller": "外部控制器监听地址", - "Core Secret": "API 访问密钥", - "Recommended": "建议设置", - "Open URL": "打开链接", - "Replace host, port, secret with %host, %port, %secret": "使用 %host, %port, %secret 表示 主机, 端口, 访问密钥", - "Support %host, %port, %secret": "支持 %host, %port, %secret", - "Clash Core": "Clash 内核", - "Upgrade": "升级内核", - "Restart": "重启内核", - "Release Version": "正式版", - "Alpha Version": "预览版", - "Please Enable Service Mode": "请先安装并启用服务模式", - "Please enter your root password": "请输入您的 root 密码", - "Grant": "授权", - "Open UWP tool": "UWP 工具", - "Open UWP tool Info": "Windows 8 开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制", - "Update GeoData": "更新 GeoData", - "Verge Basic Setting": "Verge 基础设置", - "Verge Advanced Setting": "Verge 高级设置", - "Language": "语言设置", - "Theme Mode": "主题模式", - "theme.light": "浅色", - "theme.dark": "深色", - "theme.system": "系统", - "Tray Click Event": "托盘点击事件", - "Show Main Window": "显示主窗口", - "Show Tray Menu": "显示托盘菜单", - "Copy Env Type": "复制环境变量类型", - "Copy Success": "复制成功", - "Start Page": "启动页面", - "Startup Script": "启动脚本", - "Browse": "浏览", - "Theme Setting": "主题设置", - "Primary Color": "主要颜色", - "Secondary Color": "次要颜色", - "Primary Text": "文本主要颜色", - "Secondary Text": "文本次要颜色", - "Info Color": "信息颜色", - "Warning Color": "警告颜色", - "Error Color": "错误颜色", - "Success Color": "成功颜色", - "Font Family": "字体系列", - "CSS Injection": "CSS 注入", - "Layout Setting": "界面设置", - "Traffic Graph": "流量图显", - "Memory Usage": "内核占用", - "Memory Cleanup": "点击清理内存", - "Proxy Group Icon": "代理组图标", - "Nav Icon": "导航栏图标", - "Monochrome": "单色图标", - "Colorful": "彩色图标", - "Tray Icon": "托盘图标", - "Common Tray Icon": "常规托盘图标", - "System Proxy Tray Icon": "系统代理托盘图标", - "Tun Tray Icon": "TUN 模式托盘图标", - "Miscellaneous": "杂项设置", - "App Log Level": "应用日志等级", - "Auto Close Connections": "自动关闭连接", - "Auto Close Connections Info": "当代理组选中节点或代理模式变动时,关闭已建立的连接", - "Auto Check Update": "自动检查更新", - "Enable Builtin Enhanced": "内置增强功能", - "Enable Builtin Enhanced Info": "配置文件的兼容性处理", - "Proxy Layout Columns": "代理页布局列数", - "Auto Columns": "自动列数", - "Auto Log Clean": "自动清理日志", - "Never Clean": "不清理", - "Retain _n Days": "保留 {{n}} 天", - "Auto Delay Detection": "自动延迟检测", - "Auto Delay Detection Info": "后台定时检测当前节点延迟", - "Default Latency Test": "默认测试链接", - "Default Latency Test Info": "仅用于 HTTP 客户端请求测试,不会对配置文件产生影响", - "Default Latency Timeout": "测试超时时间", - "Hotkey Setting": "热键设置", - "Enable Global Hotkey": "启用全局热键", - "open_or_close_dashboard": "打开/关闭面板", - "clash_mode_rule": "规则模式", - "clash_mode_global": "全局模式", - "clash_mode_direct": "直连模式", - "toggle_system_proxy": "打开/关闭系统代理", - "toggle_tun_mode": "打开/关闭 TUN 模式", - "entry_lightweight_mode": "进入轻量模式", - "Backup Setting": "备份设置", - "Backup Setting Info": "支持本地或 WebDAV 方式备份配置文件", - "Runtime Config": "当前配置", - "Open Conf Dir": "配置目录", - "Open Conf Dir Info": "如果软件运行异常,!备份!并删除此文件夹下的所有文件,重启软件", - "Open Core Dir": "内核目录", - "Open Logs Dir": "日志目录", - "Check for Updates": "检查更新", - "Go to Release Page": "前往发布页", - "Portable Updater Error": "便携版不支持应用内更新,请手动下载替换", - "Break Change Update Error": "此版本为重大更新,不支持应用内更新,请卸载后手动下载安装", - "Open Dev Tools": "开发者工具", - "Export Diagnostic Info": "导出诊断信息", - "Export Diagnostic Info For Issue Reporting": "导出诊断信息用于问题报告", - "Exit": "退出", - "Verge Version": "Verge 版本", - "ReadOnly": "只读", - "ReadOnlyMessage": "无法在只读模式下编辑", - "Filter": "过滤节点", - "Filter conditions": "过滤条件", - "Match Case": "区分大小写", - "Match Whole Word": "全字匹配", - "Use Regular Expression": "使用正则表达式", - "Profile Imported Successfully": "导入订阅成功", - "Profile Switched": "订阅已切换", - "Profile Reactivated": "订阅已激活", - "Profile switch interrupted by new selection": "配置切换被新选择中断", - "Only YAML Files Supported": "仅支持 YAML 文件", - "Settings Applied": "设置已应用", - "Stopping Core...": "停止内核中...", - "Restarting Core...": "重启内核中...", - "Installing Service...": "安装服务中...", - "Uninstalling Service...": "卸载服务中...", - "Service Installed Successfully": "已成功安装服务", - "Service Uninstalled Successfully": "已成功卸载服务", - "Proxy Daemon Duration Cannot be Less than 1 Second": "代理守护间隔时间不得低于 1 秒", - "Invalid Bypass Format": "无效的代理绕过格式", - "Waiting for service to be ready...": "等待服务准备就绪...", - "Service not ready, retrying attempt {count}/{total}...": "服务未就绪,正在重试 {{count}}/{{total}} 次...", - "Failed to check service status, retrying attempt {count}/{total}...": "检查服务状态失败,正在重试 {{count}}/{{total}} 次...", - "Service did not become ready after attempts. Proceeding with core restart.": "服务在尝试后仍未就绪。正在重启内核。", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "服务已就绪,但内核重启可能存在问题或服务变得不可用。请检查。", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "服务安装或内核重启遇到问题。服务可能不可用。请检查系统日志。", - "Attempting to restart core as a fallback...": "尝试重启内核作为后备方案...", - "Fallback core restart also failed: {message}": "后备内核重启也失败了: {{message}}", - "Service is ready and core restarted": "服务已就绪,内核已重启", - "Core restarted. Service is now available.": "内核已重启,服务现已可用", - "Clash Port Modified": "Clash 端口已修改", - "Port Conflict": "端口冲突", - "Restart Application to Apply Modifications": "重启 Verge 以应用修改", - "External Controller Address Modified": "外部控制器监听地址已修改", - "Permissions Granted Successfully for _clash Core": "{{core}} 内核授权成功", - "Core Version Updated": "内核版本已更新", - "Clash Core Restarted": "已重启 Clash 内核", - "GeoData Updated": "已更新 GeoData", - "Currently on the Latest Version": "当前已是最新版本", - "Already Using Latest Core": "已是最新内核版本", - "Import Subscription Successful": "导入订阅成功", - "WebDAV Server URL": "WebDAV 服务器地址 http(s)://", - "Username": "用户名", - "Password": "密码", - "Backup": "备份", - "Local Backup": "本地备份", - "WebDAV Backup": "WebDAV 备份", - "Select Backup Target": "选择备份目标", - "Filename": "文件名称", - "Actions": "操作", - "Restore": "恢复", - "Export": "导出", - "No Backups": "暂无备份", - "WebDAV URL Required": "WebDAV 服务器地址不能为空", - "Invalid WebDAV URL": "无效的 WebDAV 服务器地址格式", - "Username Required": "用户名不能为空", - "Password Required": "密码不能为空", - "Failed to Fetch Backups": "获取备份文件失败", - "WebDAV Config Saved": "WebDAV 配置保存成功", - "WebDAV Config Save Failed": "保存 WebDAV 配置失败: {{error}}", - "Backup Created": "备份创建成功", - "Backup Failed": "备份失败: {{error}}", - "Local Backup Created": "本地备份创建成功", - "Local Backup Failed": "本地备份失败", - "Local Backup Exported": "本地备份导出成功", - "Local Backup Export Failed": "本地备份导出失败", - "Local Backup Info": "在应用数据目录中创建本地备份,您可以通过下方列表进行恢复或删除。", - "Delete Backup": "删除备份", - "Export Backup": "导出备份", - "Restore Backup": "恢复备份", - "Backup Time": "备份时间", - "Confirm to delete this backup file?": "确认删除此备份文件吗?", - "Confirm to restore this backup file?": "确认恢复此份文件吗?", - "Restore Success, App will restart in 1s": "恢复成功,应用将在 1 秒后重启", - "Failed to fetch backup files": "获取备份文件失败", - "Profile": "配置", - "Help": "帮助", - "About": "关于", - "Theme": "主题", - "Main Window": "主窗口", - "Group Icon": "分组图标", - "Menu Icon": "菜单图标", - "PAC File": "PAC 文件", - "Web UI": "网页界面", - "Hotkeys": "快捷键", - "Verge Mixed Port": "Verge 混合端口", - "Verge Socks Port": "Verge SOCKS 端口", - "Verge Redir Port": "Verge 重定向端口", - "Verge Tproxy Port": "Verge 透明代理端口", - "Verge Port": "Verge 端口", - "Verge HTTP Enabled": "Verge HTTP 已启用", - "WebDAV URL": "WebDAV 地址", - "WebDAV Username": "WebDAV 用户名", - "WebDAV Password": "WebDAV 密码", - "Dashboard": "仪表板", - "Restart App": "重启应用", - "Restart Clash Core": "重启 Clash 核心", - "TUN Mode": "TUN 模式", - "Copy Env": "复制环境变量", - "Conf Dir": "配置目录", - "Core Dir": "核心目录", - "Logs Dir": "日志目录", - "Open Dir": "打开目录", - "More": "更多", - "Rule Mode": "规则模式", - "Global Mode": "全局模式", - "Direct Mode": "直连模式", - "Enable Tray Speed": "启用托盘速率", - "Enable Tray Icon": "启用托盘图标", - "Show Proxy Groups Inline": "将代理组显示在托盘一级菜单", - "LightWeight Mode": "轻量模式", - "LightWeight Mode Info": "关闭GUI界面,仅保留内核运行", - "LightWeight Mode Settings": "轻量模式设置", - "Enter LightWeight Mode Now": "立即进入轻量模式", - "Auto Enter LightWeight Mode": "自动进入轻量模式", - "Auto Enter LightWeight Mode Info": "启用后,将在窗口关闭一段时间后自动激活轻量模式", - "Auto Enter LightWeight Mode Delay": "自动进入轻量模式延迟", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "关闭窗口后,轻量模式将在 {{n}} 分钟后自动激活", - "Config Validation Failed": "订阅配置校验失败,请检查订阅配置文件,变更已撤销,错误详情:", - "Boot Config Validation Failed": "启动订阅配置校验失败,已使用默认配置启动;请检查订阅配置文件,错误详情:", - "Core Change Config Validation Failed": "切换内核时配置校验失败,已使用默认配置启动;请检查订阅配置文件,错误详情:", - "Config Validation Process Terminated": "验证进程被终止", - "Script Syntax Error": "脚本语法错误,变更已撤销", - "Script Missing Main": "脚本错误,变更已撤销", - "File Not Found": "文件丢失,变更已撤销", - "Script File Error": "脚本文件错误,变更已撤销", - "Core Changed Successfully": "内核切换成功", - "Failed to Change Core": "无法切换内核", - "YAML Syntax Error": "YAML语法错误,变更已撤销", - "YAML Read Error": "YAML读取错误,变更已撤销", - "YAML Mapping Error": "YAML映射错误,变更已撤销", - "YAML Key Error": "YAML键错误,变更已撤销", - "YAML Error": "YAML错误,变更已撤销", - "Merge File Syntax Error": "覆写文件语法错误,变更已撤销", - "Merge File Mapping Error": "覆写文件映射错误,变更已撤销", - "Merge File Key Error": "覆写文件键错误,变更已撤销", - "Merge File Error": "覆写文件错误,变更已撤销", - "Validate YAML File": "验证YAML文件", - "Validate Merge File": "验证覆写文件", - "Validation Success": "验证成功", - "Validation Failed": "验证失败", - "Service Administrator Prompt": "Clash Verge 需要管理员权限安装系统服务", - "DNS Settings": "DNS 设置", - "DNS settings saved": "DNS 设置已保存", - "DNS Overwrite": "DNS 覆写", - "DNS Settings Warning": "如果你不清楚这里的设置请不要修改,并保持 DNS 覆写开启", - "Enable DNS": "启用 DNS", - "DNS Listen": "DNS 监听地址", - "Enhanced Mode": "增强模式", - "Fake IP Range": "Fake IP 范围", - "Fake IP Filter Mode": "Fake IP 过滤模式", - "Enable IPv6 DNS resolution": "启用 IPv6 DNS 解析", - "Prefer H3": "优先使用 HTTP/3", - "DNS DOH使用HTTP/3": "DNS DOH 使用 HTTP/3 协议", - "Respect Rules": "遵循路由规则", - "DNS connections follow routing rules": "DNS 连接遵循路由规则", - "Use Hosts": "使用 Hosts", - "Enable to resolve hosts through hosts file": "启用通过 hosts 文件解析域名", - "Use System Hosts": "使用系统 Hosts", - "Enable to resolve hosts through system hosts file": "启用通过系统 hosts 文件解析域名", - "Direct Nameserver Follow Policy": "直连域名服务器遵循策略", - "Whether to follow nameserver policy": "是否遵循 nameserver-policy 设置", - "Default Nameserver": "默认域名服务器", - "Default DNS servers used to resolve DNS servers": "用于解析 DNS 服务器的默认 DNS 服务器", - "Nameserver": "域名服务器", - "List of DNS servers": "DNS 服务器列表,用逗号分隔", - "Fallback": "回退服务器", - "List of fallback DNS servers": "回退 DNS 服务器列表,用逗号分隔", - "Proxy Server Nameserver": "代理节点DNS", - "Proxy Node Nameserver": "代理节点域名解析服务器,仅用于解析代理节点的域名,用逗号分隔", - "Direct Nameserver": "直连域名服务器", - "Direct outbound Nameserver": "直连出口域名解析服务器,支持 system 关键字,用逗号分隔", - "Fake IP Filter": "Fake IP 过滤", - "Domains that skip fake IP resolution": "跳过 Fake IP 解析的域名,用逗号分隔", - "Nameserver Policy": "域名服务器策略", - "Domain-specific DNS server": "特定域名的 DNS 服务器,多个服务器使用分号分隔,格式: domain=server1;server2", - "Fallback Filter Settings": "回退过滤设置", - "GeoIP Filtering": "GeoIP 过滤", - "Enable GeoIP filtering for fallback": "启用 GeoIP 回退过滤", - "GeoIP Code": "GeoIP 国家代码", - "Fallback IP CIDR": "回退 IP CIDR", - "IP CIDRs not using fallback servers": "不使用回退服务器的 IP CIDR,用逗号分隔", - "Fallback Domain": "回退域名", - "Domains using fallback servers": "使用回退服务器的域名,用逗号分隔", - "Hosts Settings": "Hosts 设置", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "自定义域名到 IP 或域名的映射,用逗号分隔", - "Enable Alpha Channel": "启用 Alpha 通道", - "Alpha versions may contain experimental features and bugs": "Alpha 版本可能包含实验性功能和已知问题", - "Home Settings": "首页设置", - "Profile Card": "订阅卡", - "Current Proxy Card": "当前代理卡", - "Network Settings Card": "网络设置卡", - "Proxy Mode Card": "代理模式卡", - "Clash Mode Card": "Clash 模式卡", - "Traffic Stats Card": "流量统计卡", - "Clash Info Cards": "Clash 信息卡", - "System Info Cards": "系统信息卡", - "Website Tests Card": "网站测试卡", - "Traffic Stats": "流量统计", - "Website Tests": "网站测试", - "Clash Info": "Clash 信息", - "Core Version": "内核版本", - "System Proxy Address": "系统代理地址", - "Uptime": "运行时间", - "Rules Count": "规则数量", - "System Info": "系统信息", - "OS Info": "操作系统信息", - "Running Mode": "运行模式", - "Sidecar Mode": "用户模式", - "Administrator Mode": "管理员模式", - "Administrator + Service Mode": "管理员 + 服务模式", - "Last Check Update": "最后检查更新", - "Click to import subscription": "点击导入订阅", - "Last Update failed": "上次更新失败", - "Next Up": "下次更新", - "No schedule": "没有计划", - "Unknown": "未知", - "Auto update disabled": "自动更新已禁用", - "Update subscription successfully": "订阅更新成功", - "Update with Clash proxy successfully": "使用 Clash 代理更新成功", - "Update failed even with Clash proxy": "使用 Clash 代理更新也失败", - "Profile creation failed, retrying with Clash proxy...": "订阅创建失败,尝试使用 Clash 代理创建", - "Profile creation succeeded with Clash proxy": "使用 Clash 代理创建订阅成功", - "Import failed, retrying with Clash proxy...": "订阅导入失败,尝试使用 Clash 代理导入", - "Profile Imported with Clash proxy": "使用 Clash 代理导入订阅成功", - "Import failed even with Clash proxy": "使用 Clash 代理导入订阅也失败", - "Current Node": "当前节点", - "No active proxy node": "暂无激活的代理节点", - "Network Settings": "网络设置", - "Proxy Mode": "代理模式", - "Group": "代理组", - "Proxy": "节点", - "IP Information Card": "IP 信息卡", - "IP Information": "IP 信息", - "Failed to get IP info": "获取IP信息失败", - "ISP": "服务商", - "ASN": "自治域", - "ORG": "组织", - "Location": "位置", - "Timezone": "时区", - "Auto refresh": "自动刷新", - "Unlock Test": "解锁测试", - "Pending": "待检测", - "Yes": "支持", - "No": "不支持", - "Failed": "测试失败", - "Completed": "检测完成", - "Disallowed ISP": "不允许的 ISP", - "Originals Only": "仅限原创", - "No (IP Banned By Disney+)": "不支持(IP被Disney+禁止)", - "Unsupported Country/Region": "不支持的国家/地区", - "Failed (Network Connection)": "测试失败(网络连接问题)", - "DashboardToggledTitle": "仪表盘已切换", - "DashboardToggledBody": "已通过快捷键切换仪表盘显示状态", - "ClashModeChangedTitle": "Clash 模式切换", - "ClashModeChangedBody": "已切换为 {mode} 模式", - "SystemProxyToggledTitle": "系统代理切换", - "SystemProxyToggledBody": "已通过快捷键切换系统代理状态", - "TunModeToggledTitle": "TUN 模式切换", - "TunModeToggledBody": "已通过快捷键切换 TUN 模式", - "LightweightModeEnteredTitle": "轻量模式", - "LightweightModeEnteredBody": "已通过快捷键进入轻量模式", - "AppQuitTitle": "应用退出", - "AppQuitBody": "已通过快捷键退出应用", - "AppHiddenTitle": "应用隐藏", - "AppHiddenBody": "已通过快捷键隐藏应用窗口", - "Invalid Profile URL": "无效的订阅链接,请输入以 http:// 或 https:// 开头的地址", - "Saved Successfully": "保存成功", - "External Cors": "外部控制跨域", - "Enable one-click CORS for external API. Click to toggle CORS": "设置内核跨域访问,点击切换 CORS是否启用", - "External Cors Settings": "外部控制跨域设置", - "External Cors Configuration": "外部控制跨域配置", - "Allow private network access": "允许专用网络访问", - "Allowed Origins": "允许的来源", - "Please enter a valid url": "请输入有效的网址", - "Add": "添加", - "Always included origins: {{urls}}": "始终包含来源:{{urls}}", - "Invalid regular expression": "无效的正则表达式", - "Copy Version": "复制Verge版本号", - "Version copied to clipboard": "Verge版本已复制到剪贴板", - "Controller address cannot be empty": "控制器地址不能为空", - "Secret cannot be empty": "访问密钥不能为空", - "Configuration saved successfully": "配置保存成功", - "Failed to save configuration": "配置保存失败", - "Controller address copied to clipboard": "控制器地址已复制到剪贴板", - "Secret copied to clipboard": "访问密钥已复制到剪贴板", - "Saving...": "保存中...", - "Proxy node already exists in chain": "该节点已在链式代理表中", - "Detection timeout or failed": "检测超时或失败", - "Batch Operations": "批量操作", - "Delete Selected Profiles": "删除选中订阅", - "Deselect All": "取消全选", - "Done": "完成", - "items": "项目", - "Select All": "全选", - "Selected": "已选中", - "Selected profiles deleted successfully": "选中的订阅已成功删除", - "Prefer System Titlebar": "优先使用系统标题栏", - "App Log Max Size": "应用日志最大大小", - "App Log Max Count": "应用日志最大数量", - "Allow Auto Update": "允许自动更新", - "Menu reorder mode": "菜单排序模式", - "Unlock menu order": "解锁菜单排序", - "Lock menu order": "锁定菜单排序", - "Open App Log": "应用日志", - "Open Core Log": "内核日志", - "TPROXY Port": "TPROXY 透明代理端口" -} diff --git a/src/locales/zh/connections.json b/src/locales/zh/connections.json new file mode 100644 index 000000000..3b4a4ddd2 --- /dev/null +++ b/src/locales/zh/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "连接" + }, + "components": { + "fields": { + "host": "主机", + "dlSpeed": "下载速度", + "ulSpeed": "上传速度", + "chains": "链路", + "rule": "规则", + "process": "进程", + "time": "连接时间", + "source": "源地址", + "destination": "目标地址", + "destinationPort": "目标端口", + "type": "类型" + }, + "order": { + "default": "默认", + "uploadSpeed": "上传速度", + "downloadSpeed": "下载速度" + }, + "actions": { + "closeConnection": "关闭连接" + } + } +} diff --git a/src/locales/zh/home.json b/src/locales/zh/home.json new file mode 100644 index 000000000..7b11ef2f9 --- /dev/null +++ b/src/locales/zh/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "轻量模式", + "manual": "使用手册", + "settings": "首页设置" + }, + "cards": { + "trafficStats": "流量统计", + "networkSettings": "网络设置", + "proxyMode": "代理模式" + }, + "settings": { + "cards": { + "profile": "订阅卡", + "currentProxy": "当前代理卡", + "network": "网络设置卡", + "proxyMode": "代理模式卡", + "traffic": "流量统计卡", + "tests": "网站测试卡", + "ip": "IP 信息卡", + "clashInfo": "Clash 信息卡", + "systemInfo": "系统信息卡" + }, + "title": "首页设置" + }, + "title": "首页" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "系统代理已启用,您的应用将通过代理访问网络", + "systemProxyDisabled": "系统代理已关闭,建议大多数用户打开此选项", + "tunModeServiceRequired": "TUN模式需要服务模式,请先安装服务", + "tunModeEnabled": "TUN 模式已启用,应用将通过虚拟网卡访问网络", + "tunModeDisabled": "TUN 模式已关闭,适用于特殊应用" + }, + "tooltips": { + "systemProxy": "修改操作系统的代理设置,如果开启失败,可手动修改操作系统的代理设置", + "tunMode": "TUN模式可以接管所有应用流量,适用于特殊不遵循系统代理设置的应用" + } + }, + "clashInfo": { + "title": "Clash 信息", + "fields": { + "coreVersion": "内核版本", + "systemProxyAddress": "系统代理地址", + "mixedPort": "混合代理端口", + "uptime": "运行时间", + "rulesCount": "规则数量" + } + }, + "systemInfo": { + "title": "系统信息", + "fields": { + "osInfo": "操作系统信息", + "autoLaunch": "开机自启", + "runningMode": "运行模式", + "lastCheckUpdate": "最后检查更新", + "vergeVersion": "Verge 版本" + }, + "actions": { + "settings": "设置" + }, + "tooltips": { + "autoLaunchAdmin": "管理员模式可能不支持开机自启" + }, + "badges": { + "adminMode": "管理员模式", + "serviceMode": "服务模式", + "sidecarMode": "用户模式", + "adminServiceMode": "管理员 + 服务模式" + } + }, + "ipInfo": { + "title": "IP 信息", + "labels": { + "ip": "IP", + "asn": "自治域", + "isp": "服务商", + "org": "组织", + "location": "位置", + "timezone": "时区", + "autoRefresh": "自动刷新", + "unknown": "未知" + }, + "errors": { + "load": "获取 IP 信息失败" + } + }, + "currentProxy": { + "title": "当前节点", + "actions": { + "refreshDelay": "延迟测试" + }, + "labels": { + "globalMode": "全局模式", + "directMode": "直连模式", + "group": "代理组", + "proxy": "节点", + "noActiveNode": "暂无激活的代理节点" + } + }, + "tests": { + "title": "网站测试" + }, + "traffic": { + "metrics": { + "uploadSpeed": "上传速度", + "downloadSpeed": "下载速度", + "activeConnections": "活跃连接", + "memoryUsage": "内核占用" + }, + "legends": { + "upload": "上传", + "download": "下载" + }, + "patterns": { + "minutes": "{{time}} 分钟" + } + }, + "clashMode": { + "errors": { + "communication": "内核通信错误" + }, + "labels": { + "rule": "规则", + "global": "全局", + "direct": "直连" + }, + "descriptions": { + "rule": "基于预设规则智能判断流量走向,提供灵活的代理策略", + "global": "所有流量均通过代理服务器,适用于需要全局科学上网的场景", + "direct": "所有流量不经过代理节点,但经过Clash内核转发连接目标服务器,适用于需要通过内核进行分流的特定场景" + } + } + } +} diff --git a/src/locales/zh/index.ts b/src/locales/zh/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/zh/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/zh/layout.json b/src/locales/zh/layout.json new file mode 100644 index 000000000..4ecfb4c4f --- /dev/null +++ b/src/locales/zh/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "首 页", + "proxies": "代 理", + "profiles": "订 阅", + "connections": "连 接", + "rules": "规 则", + "logs": "日 志", + "unlock": "测 试", + "settings": "设 置" + }, + "menu": { + "reorderMode": "菜单排序模式", + "unlock": "解锁菜单排序", + "lock": "锁定菜单排序" + } + } + } +} diff --git a/src/locales/zh/logs.json b/src/locales/zh/logs.json new file mode 100644 index 000000000..1e38a12ce --- /dev/null +++ b/src/locales/zh/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "日志" + } +} diff --git a/src/locales/zh/profiles.json b/src/locales/zh/profiles.json new file mode 100644 index 000000000..1173c58a2 --- /dev/null +++ b/src/locales/zh/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "更新所有订阅", + "viewRuntimeConfig": "查看运行时订阅", + "reactivate": "重新激活订阅", + "import": "导入" + }, + "batch": { + "actions": { + "delete": "删除选中订阅", + "selectAll": "全选", + "deselectAll": "取消全选", + "done": "完成" + }, + "summary": { + "selected": "已选中", + "items": "项目" + }, + "title": "批量操作" + }, + "importForm": { + "placeholder": "订阅文件链接", + "actions": { + "paste": "粘贴" + } + }, + "feedback": { + "errors": { + "invalidUrl": "无效的订阅链接,请输入以 http:// 或 https:// 开头的地址", + "onlyYaml": "仅支持 YAML 文件" + }, + "notifications": { + "importRetry": "订阅导入失败,尝试使用 Clash 代理导入", + "importFail": "使用 Clash 代理导入订阅也失败", + "importNeedsRefresh": "订阅已导入,但可能需要手动刷新", + "importSuccess": "订阅已成功导入,如未显示请重启应用", + "profileSwitched": "订阅已切换", + "profileReactivated": "订阅已激活", + "switchInterrupted": "订阅切换被新选择中断", + "batchDeleted": "选中的订阅已成功删除" + }, + "notices": { + "forceRefreshCompleted": "数据已强制刷新", + "emergencyRefreshFailed": "紧急刷新失败: {{message}}" + } + }, + "title": "订阅" + }, + "components": { + "card": { + "labels": { + "clickToImport": "点击导入订阅" + } + }, + "fileInput": { + "chooseFile": "选择文件" + }, + "menu": { + "home": "首 页", + "select": "使用", + "editInfo": "编辑信息", + "editFile": "编辑文件", + "editRules": "编辑规则", + "editProxies": "编辑节点", + "editGroups": "编辑代理组", + "extendConfig": "扩展覆写配置", + "extendScript": "扩展脚本", + "openFile": "打开文件", + "update": "更新", + "updateViaProxy": "更新(代理)" + }, + "more": { + "global": { + "merge": "全局扩展覆写配置", + "script": "全局扩展脚本" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "点击查看上次更新时间", + "showNext": "点击查看下一次更新" + }, + "status": { + "lastUpdateFailed": "上次更新失败", + "nextUp": "下次更新", + "noSchedule": "没有计划", + "unknown": "未知", + "autoUpdateDisabled": "自动更新已禁用" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "新建配置", + "edit": "编辑配置" + }, + "fields": { + "type": "类型", + "description": "描述", + "subscriptionUrl": "订阅链接", + "httpTimeout": "HTTP 请求超时", + "updateInterval": "更新间隔", + "useSystemProxy": "使用系统代理更新", + "useClashProxy": "使用内核代理更新", + "acceptInvalidCerts": "允许无效证书(危险)", + "allowAutoUpdate": "允许自动更新" + }, + "feedback": { + "notifications": { + "creationRetry": "订阅创建失败,尝试使用 Clash 代理创建", + "creationSuccess": "使用 Clash 代理创建订阅成功" + } + } + }, + "proxiesEditor": { + "title": "编辑节点", + "placeholders": { + "multiUri": "多条 URI 请使用换行分隔(支持 Base64 编码)" + }, + "actions": { + "prepend": "添加前置代理节点", + "append": "添加后置代理节点" + } + }, + "groupsEditor": { + "title": "编辑代理组", + "errors": { + "nameRequired": "代理组名称不能为空", + "nameExists": "代理组名称已存在" + }, + "fields": { + "type": "代理组类型", + "name": "代理组组名", + "icon": "代理组图标", + "proxies": "引入代理", + "provider": "引入代理集合", + "healthCheckUrl": "健康检查测试地址", + "expectedStatus": "期望状态码", + "interval": "检查间隔", + "maxFailedTimes": "最大失败次数", + "interfaceName": "出站接口", + "routingMark": "路由标记", + "filter": "过滤节点", + "excludeFilter": "排除节点", + "excludeType": "排除节点类型", + "includeAll": "引入所有出站代理、代理集合", + "includeAllProxies": "引入所有出站代理", + "includeAllProviders": "引入所有代理集合" + }, + "toggles": { + "lazy": "懒惰状态", + "disableUdp": "禁用 UDP", + "hidden": "隐藏代理组" + }, + "actions": { + "prepend": "添加前置代理组", + "append": "添加后置代理组" + } + }, + "editor": { + "actions": { + "format": "格式化文档" + }, + "messages": { + "readOnly": "无法在只读模式下编辑" + } + }, + "confirmDelete": { + "title": "确认删除", + "message": "此操作不可逆" + }, + "logViewer": { + "title": "脚本控制台输出" + } + } +} diff --git a/src/locales/zh/proxies.json b/src/locales/zh/proxies.json new file mode 100644 index 000000000..dbcfdc607 --- /dev/null +++ b/src/locales/zh/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "规则", + "global": "全局", + "direct": "直连" + }, + "actions": { + "toggleChain": "🔗 链式代理", + "connect": "连接", + "disconnect": "断开", + "connecting": "连接中...", + "clearChainConfig": "删除链式配置" + }, + "provider": { + "title": "代理集合", + "actions": { + "updateAll": "更新全部", + "update": "更新" + } + }, + "rules": { + "title": "代理规则", + "select": "选择规则" + }, + "labels": { + "proxyCount": "节点数量", + "delayCheckReset": "进行延迟测试,以取消固定" + }, + "tooltips": { + "locate": "当前节点", + "delayCheck": "延迟测试", + "sortDefault": "默认排序", + "sortDelay": "按延迟排序", + "sortName": "按名称排序", + "delayCheckUrl": "延迟测试链接", + "showBasic": "隐藏节点细节", + "showDetail": "展示节点细节", + "filter": "过滤节点" + }, + "placeholders": { + "delayCheckUrl": "延迟测试链接" + }, + "chain": { + "header": "代理链配置", + "empty": "暂无代理链配置", + "instruction": "顺序点击节点添加到代理链中", + "minimumNodes": "链式代理至少需要 2 个节点", + "minimumNodesHint": "链式代理至少需要 2 个节点,请再添加一个节点。", + "connectFailed": "连接链式代理失败", + "disconnectFailed": "断开链式代理失败", + "duplicateNode": "该节点已在链式代理表中" + }, + "messages": { + "directMode": "直连模式" + }, + "title": { + "default": "代理组", + "chainMode": "链式代理模式" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} 更新成功", + "updateFailed": "{{name}} 更新失败: {{message}}", + "genericError": "更新失败: {{message}}", + "none": "没有可更新的 provider", + "allUpdated": "所有 provider 均已更新" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "手动选择代理", + "url-test": "根据 URL 测试延迟选择代理", + "fallback": "不可用时切换到另一个代理", + "load-balance": "根据负载均衡分配代理", + "relay": "根据定义的代理链传递" + }, + "policies": { + "DIRECT": "直连 (DIRECT)", + "REJECT": "拦截请求 (REJECT)", + "REJECT-DROP": "抛弃请求 (REJECT-DROP)", + "PASS": "跳过此规则 (PASS)" + } + } + } +} diff --git a/src/locales/zh/rules.json b/src/locales/zh/rules.json new file mode 100644 index 000000000..15596df30 --- /dev/null +++ b/src/locales/zh/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "规则集合", + "dialogTitle": "规则集合", + "actions": { + "updateAll": "更新全部", + "update": "更新" + } + }, + "title": "规则" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} 更新成功", + "updateFailed": "{{name}} 更新失败: {{message}}", + "genericError": "更新失败: {{message}}", + "none": "没有可更新的 provider", + "allUpdated": "所有 provider 均已更新" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "规则类型", + "content": "规则内容", + "proxyPolicy": "代理策略" + }, + "toggles": { + "noResolve": "跳过 DNS 解析" + }, + "actions": { + "prependRule": "添加前置规则", + "appendRule": "添加后置规则" + }, + "validation": { + "conditionRequired": "规则条件缺失", + "invalidRule": "无效规则" + } + }, + "ruleTypes": { + "DOMAIN": "匹配完整域名 (DOMAIN)", + "DOMAIN-SUFFIX": "匹配域名后缀 (DOMAIN-SUFFIX)", + "DOMAIN-KEYWORD": "匹配域名关键字 (DOMAIN-KEYWORD)", + "DOMAIN-REGEX": "匹配域名正则表达式 (DOMAIN-REGEX)", + "GEOSITE": "匹配 Geosite 内的域名 (GEOSITE)", + "GEOIP": "匹配 IP 所属国家代码 (GEOIP)", + "SRC-GEOIP": "匹配来源 IP 所属国家代码 (SRC-GEOIP)", + "IP-ASN": "匹配 IP 所属 ASN (IP-ASN)", + "SRC-IP-ASN": "匹配来源 IP 所属 ASN (SRC-IP-ASN)", + "IP-CIDR": "匹配 IP 地址范围 (IP-CIDR)", + "IP-CIDR6": "匹配 IP 地址范围 (IP-CIDR6)", + "SRC-IP-CIDR": "匹配来源 IP 地址范围 (SRC-IP-CIDR)", + "IP-SUFFIX": "匹配 IP 后缀范围 (IP-SUFFIX)", + "SRC-IP-SUFFIX": "匹配来源 IP 后缀范围 (SRC-IP-SUFFIX)", + "SRC-PORT": "匹配请求来源端口范围 (SRC-PORT)", + "DST-PORT": "匹配请求目标端口范围 (DST-PORT)", + "IN-PORT": "匹配入站端口 (IN-PORT)", + "DSCP": "DSCP 标记(仅限 TPROXY UDP 入站)(DSCP)", + "PROCESS-NAME": "匹配进程名称 (PROCESS-NAME)", + "PROCESS-PATH": "匹配完整进程路径 (PROCESS-PATH)", + "PROCESS-NAME-REGEX": "正则匹配完整进程名称 (PROCESS-NAME-REGEX)", + "PROCESS-PATH-REGEX": "正则匹配完整进程路径 (PROCESS-PATH-REGEX)", + "NETWORK": "匹配传输协议 (TCP/UDP) (NETWORK)", + "UID": "匹配 Linux USER ID (UID)", + "IN-TYPE": "匹配入站类型 (IN-TYPE)", + "IN-USER": "匹配入站用户名 (IN-USER)", + "IN-NAME": "匹配入站名称 (IN-NAME)", + "SUB-RULE": "子规则 (SUB-RULE)", + "RULE-SET": "匹配规则集 (RULE-SET)", + "AND": "逻辑与 (AND)", + "OR": "逻辑或 (OR)", + "NOT": "逻辑非 (NOT)", + "MATCH": "匹配所有请求 (MATCH)" + }, + "title": "编辑规则" + } + } +} diff --git a/src/locales/zh/settings.json b/src/locales/zh/settings.json new file mode 100644 index 000000000..368cdc4e4 --- /dev/null +++ b/src/locales/zh/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "使用手册", + "telegram": "Telegram 频道", + "github": "GitHub 项目地址" + }, + "title": "设置" + }, + "sections": { + "system": { + "title": "系统设置", + "toggles": { + "tunMode": "虚拟网卡模式", + "systemProxy": "系统代理" + }, + "tooltips": { + "autoLaunchAdmin": "管理员模式可能不支持开机自启", + "silentStart": "程序启动时以后台模式运行,不显示程序面板" + }, + "fields": { + "autoLaunch": "开机自启", + "silentStart": "静默启动" + }, + "notifications": { + "tunMode": { + "autoDisabled": "由于服务不可用,TUN 模式已自动关闭", + "autoDisableFailed": "自动关闭 TUN 模式失败" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "修改操作系统的代理设置,如果开启失败,可手动修改操作系统的代理设置", + "tunMode": "TUN(虚拟网卡)模式接管系统所有流量,启用时无须打开系统代理", + "tunUnavailable": "TUN 模式需要安装服务模式或管理员模式" + }, + "actions": { + "installService": "安装服务", + "uninstallService": "卸载服务" + }, + "fields": { + "systemProxy": "系统代理", + "tunMode": "虚拟网卡模式" + } + }, + "externalController": { + "title": "外部控制器监听地址", + "fields": { + "enable": "启用外部控制器", + "address": "外部控制器监听地址", + "secret": "API 访问密钥" + }, + "placeholders": { + "address": "必填", + "secret": "建议设置" + }, + "tooltips": { + "copy": "复制到剪贴板" + }, + "messages": { + "addressRequired": "控制器地址不能为空", + "secretRequired": "访问密钥不能为空", + "copyFailed": "复制失败", + "controllerCopied": "控制器地址已复制到剪贴板", + "secretCopied": "访问密钥已复制到剪贴板" + } + }, + "externalCors": { + "title": "外部控制跨域设置", + "fields": { + "allowPrivateNetwork": "允许专用网络访问", + "allowedOrigins": "允许的来源" + }, + "placeholders": { + "origin": "请输入有效的网址" + }, + "actions": { + "add": "添加" + }, + "messages": { + "alwaysIncluded": "始终包含来源:{{urls}}" + }, + "tooltips": { + "open": "外部控制跨域设置" + } + }, + "appearance": { + "light": "浅色", + "dark": "深色", + "system": "系统" + }, + "clash": { + "title": "Clash 设置", + "form": { + "fields": { + "allowLan": "局域网连接", + "dnsOverwrite": "DNS 覆写", + "ipv6": "IPv6", + "unifiedDelay": "统一延迟", + "logLevel": "日志等级", + "portConfig": "端口设置", + "external": "外部控制", + "webUI": "网页界面", + "clashCore": "Clash 内核", + "openUwpTool": "UWP 工具", + "updateGeoData": "更新 GeoData" + }, + "tooltips": { + "networkInterface": "网络接口", + "unifiedDelay": "开启统一延迟时,会进行两次延迟测试,以消除连接握手等带来的不同类型节点的延迟差异", + "logLevel": "仅对日志目录 Service 文件夹下的内核日志文件生效", + "openUwpTool": "Windows 8 开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge 基础设置", + "actions": { + "browse": "浏览" + }, + "trayOptions": { + "showMainWindow": "显示主窗口", + "showTrayMenu": "显示托盘菜单", + "disable": "禁用" + }, + "fields": { + "language": "语言设置", + "themeMode": "主题模式", + "trayClickEvent": "托盘点击事件", + "copyEnvType": "复制环境变量类型", + "startPage": "启动页面", + "startupScript": "启动脚本", + "themeSetting": "主题设置", + "layoutSetting": "界面设置", + "misc": "杂项设置", + "hotkeySetting": "热键设置" + } + }, + "advanced": { + "title": "Verge 高级设置", + "tooltips": { + "backupInfo": "支持本地或 WebDAV 方式备份配置文件", + "openConfDir": "如果软件运行异常,!备份!并删除此文件夹下的所有文件,重启软件", + "liteMode": "关闭GUI界面,仅保留内核运行" + }, + "actions": { + "copyVersion": "复制Verge版本号" + }, + "notifications": { + "latestVersion": "当前已是最新版本", + "versionCopied": "Verge 版本已复制到剪贴板" + }, + "fields": { + "backupSetting": "备份设置", + "runtimeConfig": "当前配置", + "openConfDir": "配置目录", + "openCoreDir": "内核目录", + "openLogsDir": "日志目录", + "checkUpdates": "检查更新", + "openDevTools": "开发者工具", + "liteModeSettings": "轻量模式设置", + "exit": "退出", + "exportDiagnostics": "导出诊断信息", + "vergeVersion": "Verge 版本" + } + }, + "theme": { + "title": "主题设置", + "fields": { + "primaryColor": "主要颜色", + "secondaryColor": "次要颜色", + "primaryText": "文本主要颜色", + "secondaryText": "文本次要颜色", + "infoColor": "信息颜色", + "warningColor": "警告颜色", + "errorColor": "错误颜色", + "successColor": "成功颜色", + "fontFamily": "字体系列", + "cssInjection": "CSS 注入" + }, + "actions": { + "editCss": "编辑 CSS" + }, + "dialogs": { + "editCssTitle": "编辑 CSS" + } + }, + "layout": { + "title": "界面设置", + "fields": { + "preferSystemTitlebar": "优先使用系统标题栏", + "trafficGraph": "流量图显", + "memoryUsage": "内核占用", + "proxyGroupIcon": "代理组图标", + "hoverNavigator": "悬浮跳转导航", + "hoverNavigatorDelay": "悬浮跳转导航延迟", + "navIcon": "导航栏图标", + "trayIcon": "托盘图标", + "showProxyGroupsInline": "将代理组显示在托盘一级菜单", + "commonTrayIcon": "常规托盘图标", + "systemProxyTrayIcon": "系统代理托盘图标", + "tunTrayIcon": "TUN 模式托盘图标", + "enableTrayIcon": "启用托盘图标", + "enableTraySpeed": "启用托盘速率" + }, + "tooltips": { + "hoverNavigator": "鼠标悬停在字母上时自动滚动到对应代理组", + "hoverNavigatorDelay": "鼠标悬停后触发自动跳转前等待的毫秒数" + }, + "options": { + "icon": { + "monochrome": "单色图标", + "colorful": "彩色图标", + "disable": "禁用" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "端口设置", + "fields": { + "mixed": "混合代理端口", + "socks": "SOCKS 代理端口", + "http": "HTTP(S) 代理端口", + "redir": "Redir 透明代理端口", + "tproxy": "Tproxy 透明代理端口" + }, + "actions": { + "random": "随机端口" + }, + "messages": { + "saved": "端口设置已保存", + "saveFailed": "端口设置保存失败" + } + }, + "clashCore": { + "variants": { + "release": "正式版", + "alpha": "预览版" + } + }, + "liteMode": { + "title": "轻量模式设置", + "actions": { + "enterNow": "立即进入轻量模式" + }, + "toggles": { + "autoEnter": "自动进入轻量模式" + }, + "tooltips": { + "autoEnter": "启用后,将在窗口关闭一段时间后自动激活轻量模式" + }, + "fields": { + "delay": "自动进入轻量模式延迟" + }, + "messages": { + "autoEnterHint": "关闭窗口后,轻量模式将在 {{n}} 分钟后自动激活" + } + }, + "backup": { + "title": "备份设置", + "tabs": { + "local": "本地备份", + "webdav": "WebDAV 备份" + }, + "actions": { + "selectTarget": "选择备份目标", + "backup": "备份", + "export": "导出", + "exportBackup": "导出备份", + "deleteBackup": "删除备份", + "restore": "恢复", + "restoreBackup": "恢复备份" + }, + "fields": { + "webdavUrl": "WebDAV 服务器地址 http(s)://", + "username": "用户名", + "info": "在应用数据目录中创建本地备份,您可以通过下方列表进行恢复或删除。" + }, + "messages": { + "webdavUrlRequired": "WebDAV 服务器地址不能为空", + "invalidWebdavUrl": "无效的 WebDAV 服务器地址格式", + "usernameRequired": "用户名不能为空", + "passwordRequired": "密码不能为空", + "webdavConfigSaved": "WebDAV 配置保存成功", + "webdavConfigSaveFailed": "保存 WebDAV 配置失败: {{error}}", + "backupCreated": "备份创建成功", + "backupFailed": "备份失败: {{error}}", + "localBackupCreated": "本地备份创建成功", + "localBackupFailed": "本地备份失败", + "restoreSuccess": "恢复成功,应用将在 1 秒后重启", + "localBackupExported": "本地备份导出成功", + "localBackupExportFailed": "本地备份导出失败", + "confirmDelete": "确认删除此备份文件吗?", + "confirmRestore": "确认恢复此份文件吗?" + }, + "table": { + "filename": "文件名称", + "backupTime": "备份时间", + "actions": "操作", + "noBackups": "暂无备份", + "rowsPerPage": "每页行数" + } + }, + "misc": { + "title": "杂项设置", + "fields": { + "appLogLevel": "应用日志等级", + "appLogMaxSize": "应用日志最大大小", + "appLogMaxCount": "应用日志最大数量", + "autoCloseConnections": "自动关闭连接", + "autoCheckUpdate": "自动检查更新", + "enableBuiltinEnhanced": "内置增强功能", + "proxyLayoutColumns": "代理页布局列数", + "autoLogClean": "自动清理日志", + "autoDelayDetection": "自动延迟检测", + "defaultLatencyTest": "默认测试链接", + "defaultLatencyTimeout": "测试超时时间" + }, + "tooltips": { + "autoCloseConnections": "当代理组选中节点或代理模式变动时,关闭已建立的连接", + "enableBuiltinEnhanced": "配置文件的兼容性处理", + "autoDelayDetection": "后台定时检测当前节点延迟", + "defaultLatencyTest": "仅用于 HTTP 客户端请求测试,不会对配置文件产生影响" + }, + "options": { + "proxyLayoutColumns": { + "auto": "自动列数" + }, + "autoLogClean": { + "never": "不清理", + "retainDays": "保留 {{n}} 天" + } + } + }, + "update": { + "title": "新版本 v{{version}}", + "actions": { + "goToRelease": "前往发布页", + "update": "更新" + }, + "messages": { + "portableError": "便携版不支持应用内更新,请手动下载替换", + "breakChangeError": "此版本为重大更新,不支持应用内更新,请卸载后手动下载安装" + } + }, + "sysproxy": { + "title": "系统代理设置", + "fieldsets": { + "currentStatus": "当前系统代理" + }, + "fields": { + "enableStatus": "开启状态:", + "serverAddr": "服务地址:", + "pacUrl": "PAC 地址:", + "proxyHost": "代理主机", + "usePacMode": "使用 PAC 模式", + "proxyGuard": "系统代理守卫", + "guardDuration": "代理守卫间隔", + "alwaysUseDefaultBypass": "始终使用默认绕过", + "proxyBypass": "代理绕过设置:", + "bypass": "当前绕过:", + "pacScriptContent": "PAC 脚本内容" + }, + "tooltips": { + "proxyGuard": "开启以防止其他软件修改操作系统的代理设置" + }, + "messages": { + "durationTooShort": "代理守护间隔时间不得低于 1 秒", + "invalidBypass": "无效的代理绕过格式", + "invalidProxyHost": "代理主机格式无效" + }, + "actions": { + "editPac": "编辑 PAC" + } + }, + "tun": { + "title": "虚拟网卡模式", + "fields": { + "stack": "TUN 模式堆栈", + "device": "虚拟网卡名称", + "autoRoute": "自动设置全局路由", + "strictRoute": "严格路由", + "autoDetectInterface": "自动选择流量出口接口", + "dnsHijack": "DNS 劫持", + "mtu": "最大传输单元" + }, + "tooltips": { + "dnsHijack": "多个 DNS 服务器请使用 , 分隔" + }, + "messages": { + "applied": "设置已应用" + } + }, + "dns": { + "dialog": { + "title": "DNS 覆写", + "warning": "如果你不清楚这里的设置请不要修改,并保持 DNS 覆写开启" + }, + "sections": { + "general": "DNS 设置", + "fallbackFilter": "回退过滤设置", + "hosts": "Hosts 设置" + }, + "fields": { + "enable": "启用 DNS", + "listen": "DNS 监听地址", + "enhancedMode": "增强模式", + "fakeIpRange": "Fake IP 范围", + "fakeIpFilterMode": "Fake IP 过滤模式", + "ipv6": { + "label": "IPv6", + "description": "启用 IPv6 DNS 解析" + }, + "preferH3": { + "label": "优先使用 HTTP/3", + "description": "DNS DOH 使用 HTTP/3 协议" + }, + "respectRules": { + "label": "遵循路由规则", + "description": "DNS 连接遵循路由规则" + }, + "useHosts": { + "label": "使用 Hosts", + "description": "启用通过 hosts 文件解析域名" + }, + "useSystemHosts": { + "label": "使用系统 Hosts", + "description": "启用通过系统 hosts 文件解析域名" + }, + "directPolicy": { + "label": "直连域名服务器遵循策略", + "description": "是否遵循 nameserver-policy 设置" + }, + "defaultNameserver": { + "label": "默认域名服务器", + "description": "用于解析 DNS 服务器的默认 DNS 服务器" + }, + "nameserver": { + "label": "域名服务器", + "description": "DNS 服务器列表,用逗号分隔" + }, + "fallback": { + "label": "回退服务器", + "description": "回退 DNS 服务器列表,用逗号分隔" + }, + "proxy": { + "label": "代理节点DNS", + "description": "代理节点域名解析服务器,仅用于解析代理节点的域名,用逗号分隔" + }, + "directNameserver": { + "label": "直连域名服务器", + "description": "直连出口域名解析服务器,支持 system 关键字,用逗号分隔" + }, + "fakeIpFilter": { + "label": "Fake IP 过滤", + "description": "跳过 Fake IP 解析的域名,用逗号分隔" + }, + "nameserverPolicy": { + "label": "域名服务器策略", + "description": "特定域名的 DNS 服务器,多个服务器使用分号分隔,格式: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP 过滤", + "description": "启用 GeoIP 回退过滤" + }, + "geoipCode": "GeoIP 国家代码", + "fallbackIpCidr": { + "label": "回退 IP CIDR", + "description": "不使用回退服务器的 IP CIDR,用逗号分隔" + }, + "fallbackDomain": { + "label": "回退域名", + "description": "使用回退服务器的域名,用逗号分隔" + }, + "hosts": { + "label": "Hosts", + "description": "自定义域名到 IP 或域名的映射,用逗号分隔" + } + }, + "messages": { + "saved": "DNS 设置已保存", + "configError": "DNS 配置错误:" + }, + "errors": { + "invalid": "配置无效", + "invalidYaml": "YAML 格式无效" + } + }, + "webUI": { + "actions": { + "openUrl": "打开链接" + }, + "title": "网页界面", + "messages": { + "supportedPlaceholders": "支持 %host, %port, %secret", + "placeholderInstruction": "使用 %host, %port, %secret 表示 主机, 端口, 访问密钥" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "启用全局热键" + }, + "title": "热键设置", + "functions": { + "rule": "规则模式", + "global": "全局模式", + "openOrCloseDashboard": "打开/关闭面板", + "toggleSystemProxy": "打开/关闭系统代理", + "toggleTunMode": "打开/关闭 TUN 模式", + "entryLightweightMode": "进入轻量模式", + "direct": "直连模式" + } + }, + "password": { + "prompts": { + "enterRoot": "请输入您的 root 密码" + } + }, + "networkInterface": { + "title": "网络接口", + "fields": { + "ipAddress": "IP 地址", + "macAddress": "MAC 地址" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "已重启 Clash 内核", + "versionUpdated": "内核版本已更新", + "alreadyLatestVersion": "已经是最新内核版本", + "changeSuccess": "内核切换成功", + "changeFailed": "无法切换内核", + "geoDataUpdated": "已更新 GeoData" + }, + "clashService": { + "installSuccess": "已成功安装服务", + "uninstallSuccess": "已成功卸载服务" + }, + "updater": { + "withClashProxySuccess": "使用 Clash 代理更新成功", + "withClashProxyFailed": "使用 Clash 代理更新也失败" + } + } + }, + "statuses": { + "clash": { + "stopping": "停止内核中...", + "restarting": "重启内核中..." + }, + "clashService": { + "installing": "安装服务中...", + "uninstalling": "卸载服务中..." + } + } +} diff --git a/src/locales/zh/shared.json b/src/locales/zh/shared.json new file mode 100644 index 000000000..788e1d79e --- /dev/null +++ b/src/locales/zh/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "取消", + "close": "关闭", + "confirm": "确认", + "save": "保存", + "delete": "删除", + "edit": "编辑", + "new": "新建", + "enable": "启用", + "upgrade": "升级内核", + "restart": "重启内核", + "resetToDefault": "重置为默认值", + "refresh": "刷新", + "retry": "重试", + "refreshPage": "刷新页面", + "showDetails": "显示详情", + "hideDetails": "隐藏详情", + "listView": "列表视图", + "tableView": "表格视图", + "pause": "暂停", + "resume": "继续", + "closeAll": "关闭全部", + "clear": "清除" + }, + "labels": { + "updateAt": "更新于", + "timeout": "超时", + "icon": "图标", + "name": "名称", + "readOnly": "只读", + "expireTime": "到期时间", + "updateTime": "更新时间", + "usedTotal": "已使用 / 总量", + "from": "来自", + "password": "密码", + "retryAttempts": "重试次数", + "downloaded": "下载量", + "uploaded": "上传量" + }, + "statuses": { + "enabled": "已启用", + "disabled": "未启用", + "saving": "保存中...", + "empty": "空空如也" + }, + "units": { + "milliseconds": "毫秒", + "seconds": "秒", + "minutes": "分钟", + "kilobytes": "KB", + "files": "文件" + }, + "placeholders": { + "filter": "过滤条件", + "matchCase": "区分大小写", + "matchWholeWord": "全字匹配", + "useRegex": "使用正则表达式" + }, + "validation": { + "invalidRegex": "无效的正则表达式" + }, + "window": { + "maximize": "最大化", + "minimize": "最小化" + }, + "editorModes": { + "visualization": "可视化", + "advanced": "高级" + }, + "feedback": { + "errors": { + "trafficStats": "流量统计错误", + "trafficStatsDescription": "流量统计组件发生错误,为防止崩溃已暂时停用。" + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "导入订阅成功", + "importSubscriptionSuccess": "导入订阅成功", + "importWithClashProxy": "使用 Clash 代理导入订阅成功", + "updateAvailable": "有可用更新", + "saved": "保存成功", + "common": { + "copySuccess": "复制成功", + "saveSuccess": "配置保存成功", + "saveFailed": "配置保存失败" + } + }, + "validation": { + "config": { + "failed": "订阅配置校验失败,请检查订阅配置文件,变更已撤销,错误详情:", + "bootFailed": "启动订阅配置校验失败,已使用默认配置启动;请检查订阅配置文件,错误详情:", + "coreChangeFailed": "切换内核时配置校验失败,已使用默认配置启动;请检查订阅配置文件,错误详情:", + "processTerminated": "验证进程被终止" + }, + "script": { + "syntaxError": "脚本语法错误,变更已撤销", + "missingMain": "脚本错误,变更已撤销", + "fileNotFound": "文件丢失,变更已撤销", + "fileError": "脚本文件错误,变更已撤销" + }, + "yaml": { + "syntaxError": "YAML 语法错误,变更已撤销", + "readError": "YAML 读取错误,变更已撤销", + "mappingError": "YAML 映射错误,变更已撤销", + "keyError": "YAML 键错误,变更已撤销", + "generalError": "YAML 错误,变更已撤销" + }, + "merge": { + "syntaxError": "覆写文件语法错误,变更已撤销", + "mappingError": "覆写文件映射错误,变更已撤销", + "keyError": "覆写文件键错误,变更已撤销", + "generalError": "覆写文件错误,变更已撤销" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/zh/tests.json b/src/locales/zh/tests.json new file mode 100644 index 000000000..25044e661 --- /dev/null +++ b/src/locales/zh/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "测试全部" + }, + "title": "测试" + }, + "components": { + "item": { + "actions": { + "test": "测试" + } + } + }, + "modals": { + "test": { + "title": { + "create": "新建测试", + "edit": "编辑测试" + }, + "fields": { + "url": "测试地址" + } + } + }, + "statuses": { + "test": { + "pending": "待检测", + "yes": "支持", + "no": "不支持", + "failed": "测试失败", + "completed": "检测完成", + "disallowedIsp": "不允许的 ISP", + "originalsOnly": "仅限原创", + "noDisney": "不支持(IP被Disney+禁止)", + "unsupportedRegion": "不支持的国家/地区", + "failedNetwork": "测试失败(网络连接问题)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "测试中..." + }, + "empty": "暂无解锁测试项目", + "messages": { + "detectionFailedWithName": "{{name}} 检测失败", + "detectionTimeout": "检测超时或失败" + }, + "title": "解锁测试" + } + } +} diff --git a/src/locales/zhtw.json b/src/locales/zhtw.json deleted file mode 100644 index efcbba3cd..000000000 --- a/src/locales/zhtw.json +++ /dev/null @@ -1,715 +0,0 @@ -{ - "millis": "毫秒", - "seconds": "秒", - "mins": "分鐘", - "Back": "返回", - "Close": "關閉", - "Cancel": "取消", - "Confirm": "確認", - "Maximize": "最大化", - "Minimize": "最小化", - "Format document": "格式化文件", - "Empty": "空空如也", - "New": "新增", - "Edit": "編輯", - "Save": "儲存", - "Delete": "刪除", - "Enable": "啟用", - "Disable": "停用", - "Label-Home": "首 頁", - "Label-Proxies": "代 理", - "Label-Profiles": "訂 閱", - "Label-Connections": "連 線", - "Label-Rules": "規 則", - "Label-Logs": "日 誌", - "Label-Unlock": "解 鎖", - "Label-Settings": "設 定", - "Proxies": "代理", - "Proxy Groups": "代理組", - "Proxy Chain Mode": "鏈式代理模式", - "Connect": "連線", - "Connecting...": "連線中...", - "Disconnect": "中斷", - "Failed to connect to proxy chain": "連線鏈式代理失敗", - "Proxy Provider": "代理集合", - "Proxy Count": "節點數量", - "Update All": "全部更新", - "Update At": "更新於", - "rule": "規則", - "global": "全域", - "direct": "直連", - "Chain Proxy": "🔗 鏈式代理", - "Chain Proxy Config": "鏈式代理設定", - "Proxy Rules": "代理規則", - "Select Rules": "选择规则", - "Click nodes in order to add to proxy chain": "依序點擊節點新增到鏈式代理中", - "No proxy chain configured": "暫無鏈式代理設定", - "Proxy Order": "代理順序", - "timeout": "逾時", - "Clear All": "全部清除", - "script": "指令碼", - "locate": "目前節點", - "Delay check": "延遲測試", - "Sort by default": "預設排序", - "Sort by delay": "按延遲排序", - "Sort by name": "按名稱排序", - "Delay check URL": "延遲測試網址", - "Delay check to cancel fixed": "測試延遲以取消固定", - "Proxy basic": "隱藏節點細節", - "Proxy detail": "展示節點細節", - "Profiles": "訂閱", - "Update All Profiles": "更新所有訂閱", - "View Runtime Config": "查看執行時訂閱", - "Reactivate Profiles": "重新啟用訂閱", - "Paste": "貼上", - "Profile URL": "訂閱檔網址", - "Import": "匯入", - "From": "來自", - "Update Time": "更新時間", - "Used / Total": "已使用 / 總量", - "Expire Time": "到期時間", - "Create Profile": "新增設定檔", - "Edit Profile": "編輯設定檔", - "Edit Proxies": "編輯節點", - "Use newlines for multiple uri": "多條網址,請使用換行分隔(支援 Base64 編碼)", - "Edit Rules": "編輯規則", - "Rule Type": "規則類型", - "Rule Content": "規則內容", - "Proxy Policy": "代理策略", - "No Resolve": "跳過 DNS 解析", - "Prepend Rule": "新增前置規則", - "Append Rule": "新增後置規則", - "Prepend Group": "新增前置代理組", - "Append Group": "新增後置代理組", - "Prepend Proxy": "新增前置代理節點", - "Append Proxy": "新增後置代理節點", - "Rule Condition Required": "規則條件為必填", - "Invalid Rule": "無效規則", - "Advanced": "進階", - "Visualization": "視覺化", - "DOMAIN": "配對完整網域", - "DOMAIN-SUFFIX": "配對網域後綴", - "DOMAIN-KEYWORD": "配對網域關鍵字", - "DOMAIN-REGEX": "配對網域正規表示式", - "GEOSITE": "配對 Geosite 內的網域", - "GEOIP": "配對 IP 所屬國家代碼", - "SRC-GEOIP": "配對來源 IP 所屬國家代碼", - "IP-ASN": "配對 IP 所屬 ASN", - "SRC-IP-ASN": "配對來源 IP 所屬 ASN", - "IP-CIDR": "配對 IP 位址範圍", - "IP-CIDR6": "配對 IP 位址範圍", - "SRC-IP-CIDR": "配對來源 IP 位址範圍", - "IP-SUFFIX": "配對 IP 後綴範圍", - "SRC-IP-SUFFIX": "配對來源 IP 後綴範圍", - "SRC-PORT": "配對請求來源連接埠範圍", - "DST-PORT": "配對請求目標連接埠範圍", - "IN-PORT": "配對傳入連接埠", - "DSCP": "DSCP標記(僅限 TPROXY UDP 傳入)", - "PROCESS-NAME": "配對程序名稱(Android 應用程式套件名稱)", - "PROCESS-PATH": "配對完整程序路徑", - "PROCESS-NAME-REGEX": "正規表示式配對完整程序名稱(Android 應用程式套件名稱)", - "PROCESS-PATH-REGEX": "正規表示式配對完整程序路徑", - "NETWORK": "配對傳輸協定 (TCP/UDP)", - "UID": "配對 Linux 使用者 ID", - "IN-TYPE": "配對傳入類型", - "IN-USER": "配對傳入使用者名稱", - "IN-NAME": "配對傳入名稱", - "SUB-RULE": "子規則", - "RULE-SET": "配對規則集", - "AND": "邏輯 AND", - "OR": "邏輯 OR", - "NOT": "邏輯 NOT", - "MATCH": "配對所有請求", - "DIRECT": "直連", - "REJECT": "拒絕請求", - "REJECT-DROP": "丟棄請求", - "PASS": "跳過此規則", - "Edit Groups": "編輯代理組", - "Group Type": "代理組類型", - "select": "手動選擇代理", - "url-test": "根據網址測試延遲選擇代理", - "fallback": "切換至另一個備用代理", - "load-balance": "根據負載平衡分配代理", - "relay": "根據定義的代理鏈傳送", - "Group Name": "代理組名稱", - "Use Proxies": "使用代理", - "Use Provider": "使用代理集合", - "Health Check Url": "健康檢查網址", - "Expected Status": "預期狀態碼", - "Interval": "檢查間隔", - "Lazy": "延遲載入", - "Timeout": "逾時", - "Max Failed Times": "最大失敗次數", - "Interface Name": "輸出介面", - "Routing Mark": "路由標記", - "Include All": "包含所有輸出代理、代理集合", - "Include All Providers": "包含所有代理集合", - "Include All Proxies": "包含所有輸出代理", - "Exclude Filter": "排除節點", - "Exclude Type": "排除節點類型", - "Disable UDP": "停用 UDP", - "Hidden": "隱藏代理組", - "Group Name Required": "代理組名稱為必填", - "Group Name Already Exists": "代理組名稱已存在", - "Extend Config": "擴充覆寫設定", - "Extend Script": "擴充指令碼", - "Global Merge": "全域擴充覆寫設定", - "Global Script": "全域擴充指令碼", - "Type": "類型", - "Name": "名稱", - "Descriptions": "描述", - "Subscription URL": "訂閱網址", - "Update Interval": "更新間隔", - "Choose File": "選擇檔案", - "Use System Proxy": "使用系統代理更新", - "Use Clash Proxy": "使用內核代理更新", - "Accept Invalid Certs (Danger)": "允許無效憑證(危險)", - "Refresh": "重整", - "Home": "首頁", - "Select": "使用", - "Edit Info": "編輯資訊", - "Edit File": "編輯檔案", - "Open File": "開啟檔案", - "Update": "更新", - "Update via proxy": "更新(代理)", - "Update(Proxy)": "更新(代理)", - "Confirm deletion": "確認刪除", - "This operation is not reversible": "此操作無法復原", - "Script Console": "指令碼控制台輸出", - "To Top": "前往頂端", - "To End": "前往末端", - "Connections": "連線", - "Table View": "表格檢視", - "List View": "列表檢視", - "Close All": "關閉全部", - "Close All Connections": "關閉全部連線", - "Upload": "上傳", - "Download": "下載", - "Download Speed": "下載速度", - "Upload Speed": "上傳速度", - "Host": "主機", - "Downloaded": "下載量", - "Uploaded": "上傳量", - "DL Speed": "下載速度", - "UL Speed": "上傳速度", - "Active Connections": "作用中連線", - "Chains": "鏈路", - "Rule": "規則", - "Process": "處理程序", - "Time": "連線時間", - "Source": "來源位址", - "Destination": "目標位址", - "DestinationPort": "目標連接埠", - "Close Connection": "關閉連線", - "Rules": "規則", - "Rule Provider": "規則集合", - "Logs": "日誌", - "Pause": "暫停", - "Resume": "繼續", - "Clear": "清除", - "Test": "測試", - "Test All": "測試全部", - "Testing...": "測試中...", - "Create Test": "新增測試", - "Edit Test": "編輯測試", - "Icon": "圖示", - "Test URL": "測試網址", - "Settings": "設定", - "System Setting": "系統設定", - "Tun Mode": "虛擬網路介面卡模式", - "Install Service": "安裝服務", - "Install Service failed": "安裝服務失敗", - "Uninstall Service": "解除安裝服務", - "Restart Core failed": "重新啟動內核失敗", - "Reset to Default": "重設為預設值", - "Tun Mode Info": "TUN(虛擬網路介面卡)模式接管系統所有流量,啟用時無需開啟系統代理", - "TUN requires Service Mode or Admin Mode": "虛擬網路介面卡模式需要安裝服務模式或以系統管理員身分執行", - "TUN Mode automatically disabled due to service unavailable": "由於服務不可使用,虛擬網路介面卡模式已自動停用", - "Failed to disable TUN Mode automatically": "自動停用虛擬網路介面卡模式失敗", - "System Proxy Enabled": "系統代理已啟用,您的應用程式將透過代理存取網路", - "System Proxy Disabled": "系統代理已關閉,建議大多數使用者開啟此選項", - "TUN Mode Enabled": "虛擬網路介面卡模式已啟用,應用程式將透過虛擬網路介面卡存取網路", - "TUN Mode Disabled": "虛擬網路介面卡模式已關閉,適用於特殊應用程式", - "TUN Mode Service Required": "虛擬網路介面卡模式需要服務模式,請先安裝服務", - "TUN Mode Intercept Info": "虛擬網路介面卡模式可以接管所有應用程式流量,適用於不遵循系統代理設定的特殊應用程式", - "Core communication error": "內核通信錯誤", - "Rule Mode Description": "基於預設規則智慧判斷流量走向,提供更靈活的代理策略", - "Global Mode Description": "所有流量均透過代理伺服器,適用於需要全域科學上網的場合", - "Direct Mode Description": "所有流量不透過代理伺服器,但經過Clash內核轉發連線目標伺服器,適用於需要透過內核進行分流的特定場合", - "Stack": "虛擬網路介面卡模式堆疊", - "System and Mixed Can Only be Used in Service Mode": "System 和 Mixed 只能在服務模式下使用", - "Device": "虛擬網路介面卡名稱", - "Auto Route": "自動設定全域路由", - "Strict Route": "嚴格路由", - "Auto Detect Interface": "自動偵測流量輸出介面", - "DNS Hijack": "DNS 綁架", - "MTU": "最大傳輸單位", - "Service Mode": "服務模式", - "Service Mode Info": "啟用虛擬網路介面卡模式前請先安裝服務模式,該服務啟動的內核處理程序可以獲得安裝虛擬網路介面卡(TUN 模式)的權限", - "Current State": "当前状态", - "pending": "等待中", - "installed": "已安装", - "uninstall": "未安装", - "active": "作用中", - "unknown": "未知", - "Information: Please make sure that the Clash Verge Service is installed and enabled": "提示資訊:請確認 Clash Verge Service 已安裝並啟用", - "Install": "安裝", - "Uninstall": "解除安裝", - "Disable Service Mode": "停用服務模式", - "System Proxy": "系統代理", - "System Proxy Info": "修改作業系統的代理設定,如果開啟失敗,可手動修改作業系統的代理設定", - "System Proxy Setting": "系統代理設定", - "Current System Proxy": "目前系統代理", - "Enable status": "啟用狀態:", - "Enabled": "已啟用", - "Disabled": "已停用", - "Server Addr": "服務位址:", - "Proxy Host": "代理主機", - "Invalid Proxy Host Format": "代理主機格式無效", - "Not available": "不可用", - "Proxy Guard": "系統代理守護", - "Proxy Guard Info": "開啟以防止其他軟體修改作業系統的代理設定", - "Guard Duration": "代理守護間隔", - "Always use Default Bypass": "始終使用預設繞過", - "Use Bypass Check": "啟用代理繞過檢查", - "Proxy Bypass": "代理繞過設定:", - "Bypass": "目前繞過:", - "Use PAC Mode": "使用 PAC 模式", - "PAC Script Content": "PAC 指令碼內容", - "PAC URL": "PAC 位址:", - "Auto Launch": "開機自啟", - "Administrator mode may not support auto launch": "管理員模式可能不支援開機自啟", - "Silent Start": "靜默啟動", - "Silent Start Info": "程序啟動時以後台模式執行,不顯示程序面板", - "Hover Jump Navigator": "懸浮跳轉導航", - "Hover Jump Navigator Info": "滑鼠懸停在字母上時自動捲動到對應代理組", - "Hover Jump Navigator Delay": "懸浮跳轉導航延遲", - "Hover Jump Navigator Delay Info": "滑鼠懸停後觸發自動跳轉前等待的毫秒數", - "TG Channel": "Telegram 頻道", - "Manual": "使用手冊", - "Github Repo": "GitHub 專案位址", - "Clash Setting": "Clash 設定", - "Allow Lan": "區域網路連線", - "Network Interface": "網路介面", - "Ip Address": "IP 位址", - "Mac Address": "MAC 位址", - "IPv6": "IPv6", - "Unified Delay": "統一延遲", - "Unified Delay Info": "開啟統一延遲時,會進行兩次延遲測試,以消除連線握手等帶來的不同類型節點的延遲差異", - "Log Level": "日誌等級", - "Log Level Info": "僅對日誌目錄 Service 資料夾下的內核日誌檔案生效", - "Port Config": "連接埠設定", - "Random Port": "隨機連接埠", - "Mixed Port": "混合代理連接埠", - "Socks Port": "SOCKS 代理連接埠", - "Http Port": "HTTP(S) 代理連接埠", - "Redir Port": "Redir 透明代理連接埠", - "Port settings saved": "連結埠設定已儲存", - "Failed to save port settings": "連結埠設定儲存失敗", - "External": "外部控制", - "Enable External Controller": "啟用外部控制器", - "External Controller": "外部控制器監聽位址", - "Core Secret": "API 存取金鑰", - "Recommended": "建議設定", - "Open URL": "開啟網址", - "Replace host, port, secret with %host, %port, %secret": "使用 %host, %port, %secret 表示 主機, 連接埠, 存取金鑰", - "Support %host, %port, %secret": "支援 %host, %port, %secret", - "Clash Core": "Clash 內核", - "Upgrade": "升級內核", - "Restart": "重啟內核", - "Release Version": "正式版", - "Alpha Version": "預覽版", - "Please Enable Service Mode": "請先安裝並啟用服務模式", - "Please enter your root password": "請輸入您的 root 密碼", - "Grant": "授權", - "Open UWP tool": "UWP 工具", - "Open UWP tool Info": "Windows 8 開始限制 UWP 應用程式(如Microsoft Store)直接存取本機主機的網路服務,使用此工具可繞過該限制", - "Update GeoData": "更新 GeoData", - "Verge Basic Setting": "Verge 基礎設定", - "Verge Advanced Setting": "Verge 進階設定", - "Language": "語言設定", - "Theme Mode": "主題模式", - "theme.light": "淺色", - "theme.dark": "深色", - "theme.system": "系統", - "Tray Click Event": "系統匣點擊事件", - "Show Main Window": "顯示主視窗", - "Show Tray Menu": "顯示系統匣選單", - "Copy Env Type": "複製環境變數類型", - "Copy Success": "複製成功", - "Start Page": "啟動頁面", - "Startup Script": "啟動指令碼", - "Browse": "瀏覽", - "Theme Setting": "主題設定", - "Primary Color": "主要顏色", - "Secondary Color": "次要顏色", - "Primary Text": "文字主要顏色", - "Secondary Text": "文字次要顏色", - "Info Color": "資訊顏色", - "Warning Color": "警告顏色", - "Error Color": "錯誤顏色", - "Success Color": "成功顏色", - "Font Family": "字型系列", - "CSS Injection": "CSS 注入", - "Layout Setting": "介面設定", - "Traffic Graph": "流量圖表", - "Memory Usage": "內核佔用", - "Memory Cleanup": "點擊清理記憶體", - "Proxy Group Icon": "代理組圖示", - "Nav Icon": "導覽列圖示", - "Monochrome": "單色圖示", - "Colorful": "彩色圖示", - "Tray Icon": "系統匣圖示", - "Common Tray Icon": "一般系統匣圖示", - "System Proxy Tray Icon": "系統代理系統匣圖示", - "Tun Tray Icon": "虛擬網路介面卡模式系統匣圖示", - "Miscellaneous": "雜項設定", - "App Log Level": "應用程式日誌等級", - "Auto Close Connections": "自動關閉連線", - "Auto Close Connections Info": "當代理組選中節點或代理模式變動時,關閉已建立的連線", - "Auto Check Update": "自動檢查更新", - "Enable Builtin Enhanced": "內建增強功能", - "Enable Builtin Enhanced Info": "配置檔案的相容性處理", - "Proxy Layout Columns": "代理頁面欄數", - "Auto Columns": "自動欄數", - "Auto Log Clean": "自動清理日誌", - "Never Clean": "不清理", - "Retain _n Days": "保留 {{n}} 天", - "Auto Delay Detection": "自動延遲偵測", - "Auto Delay Detection Info": "在背景定時偵測目前節點延遲", - "Default Latency Test": "預設測試網址", - "Default Latency Test Info": "僅用於 HTTP 客戶端請求測試,不會對配置檔案產生影響", - "Default Latency Timeout": "測試逾時", - "Hotkey Setting": "快速鍵設定", - "Enable Global Hotkey": "啟用全域快速鍵", - "open_or_close_dashboard": "開啟/關閉儀表板", - "clash_mode_rule": "規則模式", - "clash_mode_global": "全域模式", - "clash_mode_direct": "直連模式", - "toggle_system_proxy": "開啟/關閉系統代理", - "toggle_tun_mode": "開啟/關閉 虛擬網路介面卡模式", - "entry_lightweight_mode": "進入輕量模式", - "Backup Setting": "備份設定", - "Backup Setting Info": "支援本機或 WebDAV 方式備份配置檔案", - "Runtime Config": "執行期設定", - "Open Conf Dir": "配置目錄", - "Open Conf Dir Info": "如果軟體執行異常,!備份!並刪除此資料夾下的所有檔案,重新啟動軟體", - "Open Core Dir": "內核目錄", - "Open Logs Dir": "日誌目錄", - "Check for Updates": "檢查更新", - "Go to Release Page": "前往發佈頁面", - "Portable Updater Error": "可攜式版不支援應用程式內更新,請手動下載替換", - "Break Change Update Error": "此版本為重大更新,不支援應用程式內更新,請解除安裝後手動下載安裝", - "Open Dev Tools": "開發人員工具", - "Export Diagnostic Info": "匯出診斷資訊", - "Export Diagnostic Info For Issue Reporting": "匯出診斷資訊用於問題回報", - "Exit": "離開", - "Verge Version": "Verge 版本", - "ReadOnly": "唯讀", - "ReadOnlyMessage": "無法在唯讀模式下編輯", - "Filter": "篩選節點", - "Filter conditions": "篩選條件", - "Match Case": "區分大小寫", - "Match Whole Word": "完整字詞配對", - "Use Regular Expression": "使用正規表示式", - "Profile Imported Successfully": "匯入設定檔成功", - "Profile Switched": "訂閱已切換", - "Profile Reactivated": "訂閱已啟用", - "Profile switch interrupted by new selection": "配置切換被新的選擇中斷", - "Only YAML Files Supported": "僅支援 YAML 檔案", - "Settings Applied": "設定已套用", - "Stopping Core...": "內核停止中...", - "Restarting Core...": "內核重啟中...", - "Installing Service...": "安裝服務中...", - "Uninstalling Service...": "服務解除安裝中...", - "Service Installed Successfully": "已成功安裝服務", - "Service Uninstalled Successfully": "已成功解除安裝服務", - "Proxy Daemon Duration Cannot be Less than 1 Second": "代理守護間隔時間不得低於 1 秒", - "Invalid Bypass Format": "無效的代理繞過格式", - "Waiting for service to be ready...": "等待服務就緒...", - "Service not ready, retrying attempt {count}/{total}...": "服務未就緒,正在重試 {{count}}/{{total}} 次...", - "Failed to check service status, retrying attempt {count}/{total}...": "檢查服務狀態失敗,正在重試 {{count}}/{{total}} 次...", - "Service did not become ready after attempts. Proceeding with core restart.": "服務在嘗試後仍未就緒,正在重新啟動內核。", - "Service was ready, but core restart might have issues or service became unavailable. Please check.": "服務已就緒,但內核重啟可能存在問題或服務已不可用。請檢查。", - "Service installation or core restart encountered issues. Service might not be available. Please check system logs.": "服務安裝或內核重啟遇到問題。服務可能不可用。請檢查系統日誌。", - "Attempting to restart core as a fallback...": "嘗試重新啟動內核作為備援方案...", - "Fallback core restart also failed: {message}": "被園內核重新啟動也失敗了:{{message}}", - "Service is ready and core restarted": "服務已就緒,內核已重啟", - "Core restarted. Service is now available.": "內核已重啟,服務已就緒", - "Clash Port Modified": "Clash 連結埠已修改", - "Port Conflict": "連結埠衝突", - "Restart Application to Apply Modifications": "重新啟動 Verge 以套用修改", - "External Controller Address Modified": "外部控制器監聽位址已修改", - "Permissions Granted Successfully for _clash Core": "{{core}} 內核授權成功", - "Core Version Updated": "內核版本已更新", - "Clash Core Restarted": "已重啟 Clash 內核", - "GeoData Updated": "已更新 GeoData", - "Currently on the Latest Version": "目前已是最新版本", - "Already Using Latest Core": "已是最新內核版本", - "Import Subscription Successful": "匯入訂閱成功", - "WebDAV Server URL": "WebDAV 伺服器位址 http(s)://", - "Username": "使用者名稱", - "Password": "密碼", - "Backup": "備份", - "Local Backup": "本機備份", - "WebDAV Backup": "WebDAV 備份", - "Select Backup Target": "選擇備份目標", - "Filename": "檔案名稱", - "Actions": "動作", - "Restore": "還原", - "Export": "匯出", - "No Backups": "暫無備份", - "WebDAV URL Required": "WebDAV 伺服器位址不能為空", - "Invalid WebDAV URL": "無效的 WebDAV 伺服器位址格式", - "Username Required": "使用者名稱不能為空", - "Password Required": "密碼不能為空", - "Failed to Fetch Backups": "取得備份檔案失敗", - "WebDAV Config Saved": "WebDAV 配置儲存成功", - "WebDAV Config Save Failed": "儲存 WebDAV 配置失敗: {{error}}", - "Backup Created": "備份建立成功", - "Backup Failed": "備份失敗: {{error}}", - "Local Backup Created": "本機備份建立成功", - "Local Backup Failed": "本機備份失敗", - "Local Backup Exported": "本機備份匯出成功", - "Local Backup Export Failed": "本機備份匯出失敗", - "Local Backup Info": "在應用程式資料目錄中建立本機備份,您可以透過下方列表進行還原或刪除。", - "Delete Backup": "刪除備份", - "Export Backup": "匯出備份", - "Restore Backup": "還原備份", - "Backup Time": "備份時間", - "Confirm to delete this backup file?": "確認是否刪除此備份檔案嗎?", - "Confirm to restore this backup file?": "確認還原此份檔案嗎?", - "Restore Success, App will restart in 1s": "還原成功,應用程式將在 1 秒後重啟", - "Failed to fetch backup files": "取得備份檔案失敗", - "Profile": "配置", - "Help": "幫助", - "About": "關於", - "Theme": "主題", - "Main Window": "主視窗", - "Group Icon": "群組圖示", - "Menu Icon": "選單圖示", - "PAC File": "PAC 檔案", - "Web UI": "網頁介面", - "Hotkeys": "快捷键", - "Verge Mixed Port": "Verge 混合連結埠", - "Verge Socks Port": "Verge SOCKS 連結埠", - "Verge Redir Port": "Verge 重新導向連結埠", - "Verge Tproxy Port": "Verge 透明代理連結埠", - "Verge Port": "Verge 連結埠", - "Verge HTTP Enabled": "Verge HTTP 已啟用", - "WebDAV URL": "WebDAV 位址", - "WebDAV Username": "WebDAV 用戶名", - "WebDAV Password": "WebDAV 密碼", - "Dashboard": "儀表板", - "Restart App": "重啟應用程式", - "Restart Clash Core": "重啟 Clash 內核", - "TUN Mode": "虛擬網路介面卡模式", - "Copy Env": "複製環境變數", - "Conf Dir": "配置目錄", - "Core Dir": "內核目錄", - "Logs Dir": "日誌目錄", - "Open Dir": "開啟目錄", - "More": "更多", - "Rule Mode": "規則模式", - "Global Mode": "全域模式", - "Direct Mode": "直連模式", - "Enable Tray Speed": "啟用系統匣速率", - "Enable Tray Icon": "啟用系統匣圖示", - "Show Proxy Groups Inline": "將代理組顯示在系統匣一級選單", - "LightWeight Mode": "輕量模式", - "LightWeight Mode Info": "關閉 GUI 介面,僅保留內核執行", - "LightWeight Mode Settings": "輕量模式設定", - "Enter LightWeight Mode Now": "立即進入輕量模式", - "Auto Enter LightWeight Mode": "自動進入輕量模式", - "Auto Enter LightWeight Mode Info": "啟用後,將在視窗關閉一段時間後自動啟用輕量模式", - "Auto Enter LightWeight Mode Delay": "自動進入輕量模式延遲", - "When closing the window, LightWeight Mode will be automatically activated after _n minutes": "關閉視窗後,輕量模式將在 {{n}} 分鐘後自動啟用", - "Config Validation Failed": "訂閱配置校驗失敗,請檢查訂閱配置文件,變更已撤銷,錯誤詳情:", - "Boot Config Validation Failed": "啟動訂閱配置校驗失敗,已使用預設配置啟動;請檢查訂閱配置文件,錯誤詳情:", - "Core Change Config Validation Failed": "切換內核時配置校驗失敗,已使用預設配置啟動;請檢查訂閱配置文件,錯誤詳情:", - "Config Validation Process Terminated": "驗證程序被終止", - "Script Syntax Error": "指令碼語法錯誤,變更已撤銷", - "Script Missing Main": "指令碼錯誤,變更已撤銷", - "File Not Found": "檔案遺失,變更已撤銷", - "Script File Error": "指令碼檔案錯誤,變更已撤銷", - "Core Changed Successfully": "內核切換成功", - "Failed to Change Core": "無法切換內核", - "YAML Syntax Error": "YAML 語法錯誤,變更已撤銷", - "YAML Read Error": "YAML 讀取錯誤,變更已撤銷", - "YAML Mapping Error": "YAML 映射錯誤,變更已撤銷", - "YAML Key Error": "YAML 鍵錯誤,變更已撤銷", - "YAML Error": "YAML 錯誤,變更已撤銷", - "Merge File Syntax Error": "覆寫檔案語法錯誤,變更已撤銷", - "Merge File Mapping Error": "覆寫檔案映射錯誤,變更已撤銷", - "Merge File Key Error": "覆寫檔案鍵錯誤,變更已撤銷", - "Merge File Error": "覆寫檔案錯誤,變更已撤銷", - "Validate YAML File": "驗證YAML檔案", - "Validate Merge File": "驗證覆寫檔案", - "Validation Success": "驗證成功", - "Validation Failed": "驗證失敗", - "Service Administrator Prompt": "Clash Verge 需要管理員權限安裝系統服務", - "DNS Settings": "DNS 設定", - "DNS settings saved": "DNS 設定已儲存", - "DNS Overwrite": "DNS 覆寫", - "DNS Settings Warning": "如果你不清楚這裡的設定請不要修改,並保持 DNS 覆寫開啟", - "Enable DNS": "啟用 DNS", - "DNS Listen": "DNS 監聽位址", - "Enhanced Mode": "增強模式", - "Fake IP Range": "Fake IP 範圍", - "Fake IP Filter Mode": "Fake IP 篩選模式", - "Enable IPv6 DNS resolution": "啟用 IPv6 DNS 解析", - "Prefer H3": "優先使用 HTTP/3", - "DNS DOH使用HTTP/3": "DNS DOH 使用 HTTP/3 協定", - "Respect Rules": "遵循路由規則", - "DNS connections follow routing rules": "DNS 連線遵循路由規則", - "Use Hosts": "使用 Hosts", - "Enable to resolve hosts through hosts file": "啟用透過 hosts 檔案解析網域", - "Use System Hosts": "使用系統 Hosts", - "Enable to resolve hosts through system hosts file": "啟用透過系統 hosts 檔案解析網域", - "Direct Nameserver Follow Policy": "直連域名伺服器遵循策略", - "Whether to follow nameserver policy": "是否遵循 nameserver-policy 設定", - "Default Nameserver": "預設域名伺服器", - "Default DNS servers used to resolve DNS servers": "用於解析 DNS 伺服器的預設 DNS 伺服器", - "Nameserver": "域名伺服器", - "List of DNS servers": "DNS 伺服器列表,用逗號分隔", - "Fallback": "備援伺服器", - "List of fallback DNS servers": "備援 DNS 伺服器列表,用逗號分隔", - "Proxy Server Nameserver": "代理節點 DNS", - "Proxy Node Nameserver": "代理節點網域解析伺服器,僅用於解析代理節點的網域,用逗號分隔", - "Direct Nameserver": "直連域名伺服器", - "Direct outbound Nameserver": "直連輸出網域解析伺服器,支援 system 關鍵字,用逗號分隔", - "Fake IP Filter": "Fake IP 篩選", - "Domains that skip fake IP resolution": "跳過 Fake IP 解析的網域,用逗號分隔", - "Nameserver Policy": "域名伺服器策略", - "Domain-specific DNS server": "特定網域的 DNS 伺服器,多個伺服器使用分號分隔,格式: domain=server1;server2", - "Fallback Filter Settings": "備援篩選設定", - "GeoIP Filtering": "GeoIP 篩選", - "Enable GeoIP filtering for fallback": "啟用 GeoIP 備援篩選", - "GeoIP Code": "GeoIP 國家代碼", - "Fallback IP CIDR": "備援 IP CIDR", - "IP CIDRs not using fallback servers": "不使用備援伺服器的 IP CIDR,用逗號分隔", - "Fallback Domain": "備援網域", - "Domains using fallback servers": "使用備援伺服器的網域,用逗號分隔", - "Hosts Settings": "Hosts 設定", - "Hosts": "Hosts", - "Custom domain to IP or domain mapping": "自訂網域到 IP 或網域的映射,用逗號分隔", - "Enable Alpha Channel": "啟用 Alpha 頻道", - "Alpha versions may contain experimental features and bugs": "Alpha 版本可能內含實驗性功能和已知問題,常有不穩定的情況發生。", - "Home Settings": "首頁設定", - "Profile Card": "訂閱卡", - "Current Proxy Card": "目前代理卡", - "Network Settings Card": "網路設定卡", - "Proxy Mode Card": "代理模式卡", - "Clash Mode Card": "Clash模式卡", - "Traffic Stats Card": "流量統計卡", - "Clash Info Cards": "Clash 資訊卡", - "System Info Cards": "系統資訊卡", - "Website Tests Card": "網站測試卡", - "Traffic Stats": "流量統計", - "Website Tests": "網站測試", - "Clash Info": "Clash 資訊", - "Core Version": "內核版本", - "System Proxy Address": "系統代理位址", - "Uptime": "執行時間", - "Rules Count": "規則數量", - "System Info": "系統資訊", - "OS Info": "作業系統資訊", - "Running Mode": "執行模式", - "Sidecar Mode": "使用者模式", - "Administrator Mode": "管理員模式", - "Administrator + Service Mode": "系統管理員 + 服務模式", - "Last Check Update": "最後檢查更新", - "Click to import subscription": "點擊匯入訂閱", - "Last Update failed": "上次更新失敗", - "Next Up": "下次更新", - "No schedule": "沒有排程", - "Unknown": "未知", - "Auto update disabled": "自動更新已停用", - "Update subscription successfully": "訂閱更新成功", - "Update with Clash proxy successfully": "使用 Clash 代理更新成功", - "Update failed even with Clash proxy": "使用 Clash 代理更新也失敗", - "Profile creation failed, retrying with Clash proxy...": "訂閱建立失敗,嘗試使用 Clash 代理建立", - "Profile creation succeeded with Clash proxy": "使用 Clash 代理建立訂閱成功", - "Import failed, retrying with Clash proxy...": "訂閱匯入失敗,嘗試使用 Clash 代理匯入", - "Profile Imported with Clash proxy": "使用 Clash 代理匯入訂閱成功", - "Import failed even with Clash proxy": "使用 Clash 代理匯入訂閱也失敗", - "Current Node": "目前節點", - "No active proxy node": "暫無作用中的代理節點", - "Network Settings": "網路設定", - "Proxy Mode": "代理模式", - "Group": "代理組", - "Proxy": "節點", - "IP Information Card": "IP資訊卡", - "IP Information": "IP資訊", - "Failed to get IP info": "取得IP資訊失敗", - "ISP": "網際網路服務供應商", - "ASN": "自治系統", - "ORG": "組織", - "Location": "位置", - "Timezone": "時區", - "Auto refresh": "自動重整", - "Unlock Test": "解鎖測試", - "Pending": "待檢測", - "Yes": "支援", - "No": "不支援", - "Failed": "測試失敗", - "Completed": "檢測完成", - "Disallowed ISP": "不允許的網際網路服務供應商", - "Originals Only": "僅限原創", - "No (IP Banned By Disney+)": "不支援(IP被Disney+禁止)", - "Unsupported Country/Region": "不支援的國家/地區", - "Failed (Network Connection)": "測試失敗(網路連線問題)", - "DashboardToggledTitle": "儀錶板已切換", - "DashboardToggledBody": "已透過快速鍵切換儀錶板顯示狀態", - "ClashModeChangedTitle": "Clash模式切換", - "ClashModeChangedBody": "已切換為 {mode} 模式", - "SystemProxyToggledTitle": "系統代理切換", - "SystemProxyToggledBody": "已透過快速鍵切換系統代理狀態", - "TunModeToggledTitle": "TUN模式切換", - "TunModeToggledBody": "已透過快速鍵切換TUN模式", - "LightweightModeEnteredTitle": "輕量模式", - "LightweightModeEnteredBody": "已透過快速鍵進入輕量模式", - "AppQuitTitle": "應用程式退出", - "AppQuitBody": "已透過快速鍵退出應用程式", - "AppHiddenTitle": "應用程式隱藏", - "AppHiddenBody": "已透過快速鍵隱藏應用程式視窗", - "Invalid Profile URL": "無效的訂閱網址,請輸入以 http:// 或 https:// 開頭的位址", - "Saved Successfully": "儲存成功", - "External Cors": "外部跨來源資源共享", - "Enable one-click CORS for external API. Click to toggle CORS": "設定內核跨來源存取,點擊切換跨來源資源共享是否啟用", - "External Cors Settings": "外部跨來源資源共享設定", - "External Cors Configuration": "外部跨來源資源共享設定", - "Allow private network access": "允許專用網路存取", - "Allowed Origins": "允許的來源", - "Please enter a valid url": "請輸入有效的網址", - "Add": "新增", - "Always included origins: {{urls}}": "始終包含來源:{{urls}}", - "Invalid regular expression": "無效的正規表示式", - "Copy Version": "複製Verge版本號", - "Version copied to clipboard": "Verge版本已複製到剪貼簿", - "Controller address cannot be empty": "控制器位址不能為空", - "Secret cannot be empty": "存取金鑰不能為空", - "Configuration saved successfully": "設定儲存完成", - "Failed to save configuration": "設定儲存失敗", - "Controller address copied to clipboard": "API 連接埠已複製到剪貼簿", - "Secret copied to clipboard": "API 金鑰已複製到剪貼簿", - "Saving...": "儲存中...", - "Proxy node already exists in chain": "該節點已在鏈式代理表中", - "Detection timeout or failed": "檢測逾時或失敗", - "Batch Operations": "批次操作", - "Delete Selected Profiles": "刪除選取訂閱", - "Deselect All": "取消選取", - "Done": "完成", - "items": "項目", - "Select All": "全選", - "Selected": "已選取", - "Selected profiles deleted successfully": "選取的訂閱已成功刪除", - "Prefer System Titlebar": "優先使用系統標題欄", - "App Log Max Size": "應用程式日誌最大大小", - "App Log Max Count": "應用程式日誌最大數量", - "Allow Auto Update": "允許自動更新", - "Menu reorder mode": "選單排序模式", - "Unlock menu order": "解鎖選單排序", - "Lock menu order": "鎖定選單排序", - "TPROXY Port": "TPROXY 透明代理連接埠" -} diff --git a/src/locales/zhtw/connections.json b/src/locales/zhtw/connections.json new file mode 100644 index 000000000..6da04e1a5 --- /dev/null +++ b/src/locales/zhtw/connections.json @@ -0,0 +1,28 @@ +{ + "page": { + "title": "連線" + }, + "components": { + "fields": { + "host": "主機", + "dlSpeed": "下載速度", + "ulSpeed": "上傳速度", + "chains": "鏈路", + "rule": "規則", + "process": "處理程序", + "time": "連線時間", + "source": "來源位址", + "destination": "目標位址", + "destinationPort": "目標連接埠", + "type": "類型" + }, + "order": { + "default": "Default", + "uploadSpeed": "上傳速度", + "downloadSpeed": "下載速度" + }, + "actions": { + "closeConnection": "關閉連線" + } + } +} diff --git a/src/locales/zhtw/home.json b/src/locales/zhtw/home.json new file mode 100644 index 000000000..5853832ca --- /dev/null +++ b/src/locales/zhtw/home.json @@ -0,0 +1,138 @@ +{ + "page": { + "tooltips": { + "lightweightMode": "輕量模式", + "manual": "使用手冊", + "settings": "首頁設定" + }, + "cards": { + "trafficStats": "流量統計", + "networkSettings": "網路設定", + "proxyMode": "代理模式" + }, + "settings": { + "cards": { + "profile": "訂閱卡", + "currentProxy": "目前代理卡", + "network": "網路設定卡", + "proxyMode": "代理模式卡", + "traffic": "流量統計卡", + "tests": "網站測試卡", + "ip": "IP資訊卡", + "clashInfo": "Clash 資訊卡", + "systemInfo": "系統資訊卡" + }, + "title": "首頁設定" + }, + "title": "首頁" + }, + "components": { + "proxyTun": { + "status": { + "systemProxyEnabled": "系統代理已啟用,您的應用程式將透過代理存取網路", + "systemProxyDisabled": "系統代理已關閉,建議大多數使用者開啟此選項", + "tunModeServiceRequired": "虛擬網路介面卡模式需要服務模式,請先安裝服務", + "tunModeEnabled": "虛擬網路介面卡模式已啟用,應用程式將透過虛擬網路介面卡存取網路", + "tunModeDisabled": "虛擬網路介面卡模式已關閉,適用於特殊應用程式" + }, + "tooltips": { + "systemProxy": "修改作業系統的代理設定,如果開啟失敗,可手動修改作業系統的代理設定", + "tunMode": "虛擬網路介面卡模式可以接管所有應用程式流量,適用於不遵循系統代理設定的特殊應用程式" + } + }, + "clashInfo": { + "title": "Clash 資訊", + "fields": { + "coreVersion": "內核版本", + "systemProxyAddress": "系統代理位址", + "mixedPort": "Mixed Port", + "uptime": "執行時間", + "rulesCount": "規則數量" + } + }, + "systemInfo": { + "title": "系統資訊", + "fields": { + "osInfo": "作業系統資訊", + "autoLaunch": "開機自啟", + "runningMode": "執行模式", + "lastCheckUpdate": "最後檢查更新", + "vergeVersion": "Verge 版本" + }, + "actions": { + "settings": "設定" + }, + "tooltips": { + "autoLaunchAdmin": "管理員模式可能不支援開機自啟" + }, + "badges": { + "adminMode": "管理員模式", + "serviceMode": "服務模式", + "sidecarMode": "使用者模式", + "adminServiceMode": "系統管理員 + 服務模式" + } + }, + "ipInfo": { + "title": "IP資訊", + "labels": { + "ip": "IP", + "asn": "自治系統", + "isp": "網際網路服務供應商", + "org": "組織", + "location": "位置", + "timezone": "時區", + "autoRefresh": "自動重整", + "unknown": "未知" + }, + "errors": { + "load": "獲取 IP 資訊失敗" + } + }, + "currentProxy": { + "title": "目前節點", + "actions": { + "refreshDelay": "延遲測試" + }, + "labels": { + "globalMode": "全域模式", + "directMode": "直連模式", + "group": "代理組", + "proxy": "節點", + "noActiveNode": "暫無作用中的代理節點" + } + }, + "tests": { + "title": "網站測試" + }, + "traffic": { + "metrics": { + "uploadSpeed": "上傳速度", + "downloadSpeed": "下載速度", + "activeConnections": "作用中連線", + "memoryUsage": "內核佔用" + }, + "legends": { + "upload": "上傳", + "download": "下載" + }, + "patterns": { + "minutes": "{{time}} Minutes" + } + }, + "clashMode": { + "errors": { + "communication": "內核通信錯誤" + }, + "labels": { + "rule": "規則", + "global": "全域", + "direct": "直連" + }, + "descriptions": { + "rule": "依照規則自動選擇代理。", + "global": "將所有網路請求轉送至所選代理。", + "direct": "略過代理,直接連線至網際網路。" + } + } + } +} diff --git a/src/locales/zhtw/index.ts b/src/locales/zhtw/index.ts new file mode 100644 index 000000000..3ece5e367 --- /dev/null +++ b/src/locales/zhtw/index.ts @@ -0,0 +1,25 @@ +import connections from "./connections.json"; +import home from "./home.json"; +import layout from "./layout.json"; +import logs from "./logs.json"; +import profiles from "./profiles.json"; +import proxies from "./proxies.json"; +import rules from "./rules.json"; +import settings from "./settings.json"; +import shared from "./shared.json"; +import tests from "./tests.json"; + +const resources = { + connections: connections, + home: home, + layout: layout, + logs: logs, + profiles: profiles, + proxies: proxies, + rules: rules, + settings: settings, + shared: shared, + tests: tests, +}; + +export default resources; diff --git a/src/locales/zhtw/layout.json b/src/locales/zhtw/layout.json new file mode 100644 index 000000000..820056d0e --- /dev/null +++ b/src/locales/zhtw/layout.json @@ -0,0 +1,21 @@ +{ + "components": { + "navigation": { + "tabs": { + "home": "首 頁", + "proxies": "代 理", + "profiles": "訂 閱", + "connections": "連 線", + "rules": "規 則", + "logs": "日 誌", + "unlock": "解 鎖", + "settings": "設 定" + }, + "menu": { + "reorderMode": "選單排序模式", + "unlock": "解鎖選單排序", + "lock": "鎖定選單排序" + } + } + } +} diff --git a/src/locales/zhtw/logs.json b/src/locales/zhtw/logs.json new file mode 100644 index 000000000..183916d3c --- /dev/null +++ b/src/locales/zhtw/logs.json @@ -0,0 +1,5 @@ +{ + "page": { + "title": "日誌" + } +} diff --git a/src/locales/zhtw/profiles.json b/src/locales/zhtw/profiles.json new file mode 100644 index 000000000..0bc5cc89b --- /dev/null +++ b/src/locales/zhtw/profiles.json @@ -0,0 +1,182 @@ +{ + "page": { + "actions": { + "updateAll": "更新所有訂閱", + "viewRuntimeConfig": "查看執行時訂閱", + "reactivate": "重新啟用訂閱", + "import": "匯入" + }, + "batch": { + "actions": { + "delete": "刪除選取訂閱", + "selectAll": "全選", + "deselectAll": "取消選取", + "done": "完成" + }, + "summary": { + "selected": "已選取", + "items": "項目" + }, + "title": "批次操作" + }, + "importForm": { + "placeholder": "訂閱檔網址", + "actions": { + "paste": "貼上" + } + }, + "feedback": { + "errors": { + "invalidUrl": "無效的訂閱網址,請輸入以 http:// 或 https:// 開頭的位址", + "onlyYaml": "僅支援 YAML 檔案" + }, + "notifications": { + "importRetry": "訂閱匯入失敗,嘗試使用 Clash 代理匯入", + "importFail": "使用 Clash 代理匯入訂閱也失敗", + "importNeedsRefresh": "Profile imported but may need manual refresh", + "importSuccess": "Profile imported successfully, please restart if not visible", + "profileSwitched": "訂閱已切換", + "profileReactivated": "訂閱已啟用", + "switchInterrupted": "配置切換被新的選擇中斷", + "batchDeleted": "選取的訂閱已成功刪除" + }, + "notices": { + "forceRefreshCompleted": "Force refresh completed", + "emergencyRefreshFailed": "Emergency refresh failed: {{message}}" + } + }, + "title": "訂閱" + }, + "components": { + "card": { + "labels": { + "clickToImport": "點擊匯入訂閱" + } + }, + "fileInput": { + "chooseFile": "選擇檔案" + }, + "menu": { + "home": "首 頁", + "select": "使用", + "editInfo": "編輯資訊", + "editFile": "編輯檔案", + "editRules": "編輯規則", + "editProxies": "編輯節點", + "editGroups": "編輯代理組", + "extendConfig": "擴充覆寫設定", + "extendScript": "擴充指令碼", + "openFile": "開啟檔案", + "update": "更新", + "updateViaProxy": "更新(代理)" + }, + "more": { + "global": { + "merge": "Global Merge", + "script": "Global Script" + }, + "chips": { + "merge": "Merge", + "script": "Script" + } + }, + "profileItem": { + "tooltips": { + "showLast": "Click to show last update time", + "showNext": "Click to show next update" + }, + "status": { + "lastUpdateFailed": "上次更新失敗", + "nextUp": "下次更新", + "noSchedule": "沒有排程", + "unknown": "未知", + "autoUpdateDisabled": "自動更新已停用" + } + } + }, + "modals": { + "profileForm": { + "title": { + "create": "新增設定檔", + "edit": "編輯設定檔" + }, + "fields": { + "type": "類型", + "description": "描述", + "subscriptionUrl": "訂閱網址", + "httpTimeout": "HTTP Request Timeout", + "updateInterval": "更新間隔", + "useSystemProxy": "使用系統代理更新", + "useClashProxy": "使用內核代理更新", + "acceptInvalidCerts": "允許無效憑證(危險)", + "allowAutoUpdate": "允許自動更新" + }, + "feedback": { + "notifications": { + "creationRetry": "訂閱建立失敗,嘗試使用 Clash 代理建立", + "creationSuccess": "使用 Clash 代理建立訂閱成功" + } + } + }, + "proxiesEditor": { + "title": "編輯節點", + "placeholders": { + "multiUri": "多條網址,請使用換行分隔(支援 Base64 編碼)" + }, + "actions": { + "prepend": "新增前置代理節點", + "append": "新增後置代理節點" + } + }, + "groupsEditor": { + "title": "編輯代理組", + "errors": { + "nameRequired": "代理組名稱為必填", + "nameExists": "代理組名稱已存在" + }, + "fields": { + "type": "代理組類型", + "name": "代理組名稱", + "icon": "代理組圖示", + "proxies": "使用代理", + "provider": "使用代理集合", + "healthCheckUrl": "健康檢查網址", + "expectedStatus": "預期狀態碼", + "interval": "檢查間隔", + "maxFailedTimes": "最大失敗次數", + "interfaceName": "輸出介面", + "routingMark": "路由標記", + "filter": "篩選節點", + "excludeFilter": "排除節點", + "excludeType": "排除節點類型", + "includeAll": "包含所有輸出代理、代理集合", + "includeAllProxies": "包含所有輸出代理", + "includeAllProviders": "包含所有代理集合" + }, + "toggles": { + "lazy": "延遲載入", + "disableUdp": "停用 UDP", + "hidden": "隱藏代理組" + }, + "actions": { + "prepend": "新增前置代理組", + "append": "新增後置代理組" + } + }, + "editor": { + "actions": { + "format": "格式化文件" + }, + "messages": { + "readOnly": "無法在唯讀模式下編輯" + } + }, + "confirmDelete": { + "title": "確認刪除", + "message": "此操作無法復原" + }, + "logViewer": { + "title": "指令碼控制台輸出" + } + } +} diff --git a/src/locales/zhtw/proxies.json b/src/locales/zhtw/proxies.json new file mode 100644 index 000000000..d6a010377 --- /dev/null +++ b/src/locales/zhtw/proxies.json @@ -0,0 +1,90 @@ +{ + "page": { + "modes": { + "rule": "規則", + "global": "全局", + "direct": "直連" + }, + "actions": { + "toggleChain": "🔗 鏈式代理", + "connect": "連線", + "disconnect": "中斷", + "connecting": "連線中...", + "clearChainConfig": "刪除鏈式設定" + }, + "provider": { + "title": "代理集合", + "actions": { + "updateAll": "全部更新", + "update": "更新" + } + }, + "rules": { + "title": "代理規則", + "select": "選擇規則" + }, + "labels": { + "proxyCount": "節點數量", + "delayCheckReset": "測試延遲以取消固定" + }, + "tooltips": { + "locate": "目前節點", + "delayCheck": "延遲測試", + "sortDefault": "預設排序", + "sortDelay": "按延遲排序", + "sortName": "按名稱排序", + "delayCheckUrl": "延遲測試網址", + "showBasic": "隱藏節點細節", + "showDetail": "展示節點細節", + "filter": "篩選節點" + }, + "placeholders": { + "delayCheckUrl": "延遲測試網址" + }, + "chain": { + "header": "鏈式代理設定", + "empty": "暫無鏈式代理設定", + "instruction": "依序點擊節點新增到鏈式代理中", + "minimumNodes": "鏈式代理至少需要 2 個節點", + "minimumNodesHint": "鏈式代理至少需要 2 個節點,請再新增一個節點。", + "connectFailed": "連線鏈式代理失敗", + "disconnectFailed": "中斷鏈式代理失敗", + "duplicateNode": "該節點已在鏈式代理表中" + }, + "messages": { + "directMode": "直連模式" + }, + "title": { + "default": "代理組", + "chainMode": "鏈式代理模式" + } + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "components": { + "enums": { + "strategies": { + "select": "手動選擇代理", + "url-test": "根據網址測試延遲選擇代理", + "fallback": "切換至另一個備用代理", + "load-balance": "根據負載平衡分配代理", + "relay": "根據定義的代理鏈傳送" + }, + "policies": { + "DIRECT": "直連 (DIRECT)", + "REJECT": "拒絕請求 (REJECT)", + "REJECT-DROP": "丟棄請求 (REJECT-DROP)", + "PASS": "跳過此規則 (PASS)" + } + } + } +} diff --git a/src/locales/zhtw/rules.json b/src/locales/zhtw/rules.json new file mode 100644 index 000000000..3eca5a4fd --- /dev/null +++ b/src/locales/zhtw/rules.json @@ -0,0 +1,82 @@ +{ + "page": { + "provider": { + "trigger": "規則集合", + "dialogTitle": "規則集合", + "actions": { + "updateAll": "全部更新", + "update": "更新" + } + }, + "title": "規則" + }, + "feedback": { + "notifications": { + "provider": { + "updateSuccess": "{{name}} updated successfully", + "updateFailed": "Failed to update {{name}}: {{message}}", + "genericError": "Update failed: {{message}}", + "none": "No providers available to update", + "allUpdated": "All providers updated successfully" + } + } + }, + "modals": { + "editor": { + "form": { + "labels": { + "type": "規則類型", + "content": "規則內容", + "proxyPolicy": "代理策略" + }, + "toggles": { + "noResolve": "跳過 DNS 解析" + }, + "actions": { + "prependRule": "新增前置規則", + "appendRule": "新增後置規則" + }, + "validation": { + "conditionRequired": "規則條件為必填", + "invalidRule": "無效規則" + } + }, + "ruleTypes": { + "DOMAIN": "配對完整網域 (DOMAIN)", + "DOMAIN-SUFFIX": "配對網域後綴 (DOMAIN-SUFFIX)", + "DOMAIN-KEYWORD": "配對網域關鍵字 (DOMAIN-KEYWORD)", + "DOMAIN-REGEX": "配對網域正規表示式 (DOMAIN-REGEX)", + "GEOSITE": "配對 Geosite 內的網域 (GEOSITE)", + "GEOIP": "配對 IP 所屬國家代碼 (GEOIP)", + "SRC-GEOIP": "配對來源 IP 所屬國家代碼 (SRC-GEOIP)", + "IP-ASN": "配對 IP 所屬 ASN (IP-ASN)", + "SRC-IP-ASN": "配對來源 IP 所屬 ASN (SRC-IP-ASN)", + "IP-CIDR": "配對 IP 位址範圍 (IP-CIDR)", + "IP-CIDR6": "配對 IP 位址範圍 (IP-CIDR6)", + "SRC-IP-CIDR": "配對來源 IP 位址範圍 (SRC-IP-CIDR)", + "IP-SUFFIX": "配對 IP 後綴範圍 (IP-SUFFIX)", + "SRC-IP-SUFFIX": "配對來源 IP 後綴範圍 (SRC-IP-SUFFIX)", + "SRC-PORT": "配對請求來源連接埠範圍 (SRC-PORT)", + "DST-PORT": "配對請求目標連接埠範圍 (DST-PORT)", + "IN-PORT": "配對傳入連接埠 (IN-PORT)", + "DSCP": "DSCP標記(僅限 TPROXY UDP 傳入)(DSCP)", + "PROCESS-NAME": "配對程序名稱 (PROCESS-NAME)", + "PROCESS-PATH": "配對完整程序路徑 (PROCESS-PATH)", + "PROCESS-NAME-REGEX": "正規表示式配對完整程序名稱 (PROCESS-NAME-REGEX)", + "PROCESS-PATH-REGEX": "正規表示式配對完整程序路徑 (PROCESS-PATH-REGEX)", + "NETWORK": "配對傳輸協定 (TCP/UDP) (NETWORK)", + "UID": "配對 Linux 使用者 ID (UID)", + "IN-TYPE": "配對傳入類型 (IN-TYPE)", + "IN-USER": "配對傳入使用者名稱 (IN-USER)", + "IN-NAME": "配對傳入名稱 (IN-NAME)", + "SUB-RULE": "子規則 (SUB-RULE)", + "RULE-SET": "配對規則集 (RULE-SET)", + "AND": "邏輯與 (AND)", + "OR": "邏輯或 (OR)", + "NOT": "邏輯非 (NOT)", + "MATCH": "配對所有請求 (MATCH)" + }, + "title": "編輯規則" + } + } +} diff --git a/src/locales/zhtw/settings.json b/src/locales/zhtw/settings.json new file mode 100644 index 000000000..cfc6ab3fb --- /dev/null +++ b/src/locales/zhtw/settings.json @@ -0,0 +1,573 @@ +{ + "page": { + "actions": { + "manual": "使用手冊", + "telegram": "Telegram 頻道", + "github": "GitHub 專案位址" + }, + "title": "設定" + }, + "sections": { + "system": { + "title": "系統設定", + "toggles": { + "tunMode": "虛擬網路介面卡模式", + "systemProxy": "系統代理" + }, + "tooltips": { + "autoLaunchAdmin": "管理員模式可能不支援開機自啟", + "silentStart": "程序啟動時以後台模式執行,不顯示程序面板" + }, + "fields": { + "autoLaunch": "開機自啟", + "silentStart": "靜默啟動" + }, + "notifications": { + "tunMode": { + "autoDisabled": "由於服務不可使用,虛擬網路介面卡模式已自動停用", + "autoDisableFailed": "自動停用虛擬網路介面卡模式失敗" + } + } + }, + "proxyControl": { + "tooltips": { + "systemProxy": "修改作業系統的代理設定,如果開啟失敗,可手動修改作業系統的代理設定", + "tunMode": "TUN(虛擬網路介面卡)模式接管系統所有流量,啟用時無需開啟系統代理", + "tunUnavailable": "虛擬網路介面卡模式需要安裝服務模式或以系統管理員身分執行" + }, + "actions": { + "installService": "安裝服務", + "uninstallService": "解除安裝服務" + }, + "fields": { + "systemProxy": "系統代理", + "tunMode": "虛擬網路介面卡模式" + } + }, + "externalController": { + "title": "外部控制器監聽位址", + "fields": { + "enable": "啟用外部控制器", + "address": "外部控制器監聽位址", + "secret": "API 存取金鑰" + }, + "placeholders": { + "address": "必填", + "secret": "建議設定" + }, + "tooltips": { + "copy": "複製到剪貼簿" + }, + "messages": { + "addressRequired": "控制器位址不能為空", + "secretRequired": "存取金鑰不能為空", + "copyFailed": "複製失敗", + "controllerCopied": "API 連接埠已複製到剪貼簿", + "secretCopied": "API 金鑰已複製到剪貼簿" + } + }, + "externalCors": { + "title": "外部跨來源資源共享設定", + "fields": { + "allowPrivateNetwork": "允許專用網路存取", + "allowedOrigins": "允許的來源" + }, + "placeholders": { + "origin": "請輸入有效的網址" + }, + "actions": { + "add": "新增" + }, + "messages": { + "alwaysIncluded": "始終包含來源:{{urls}}" + }, + "tooltips": { + "open": "外部跨來源資源共享設定" + } + }, + "appearance": { + "light": "淺色", + "dark": "深色", + "system": "系統" + }, + "clash": { + "title": "Clash 設定", + "form": { + "fields": { + "allowLan": "區域網路連線", + "dnsOverwrite": "DNS 覆寫", + "ipv6": "IPv6", + "unifiedDelay": "統一延遲", + "logLevel": "日誌等級", + "portConfig": "連接埠設定", + "external": "外部控制", + "webUI": "網頁介面", + "clashCore": "Clash 內核", + "openUwpTool": "UWP 工具", + "updateGeoData": "更新 GeoData" + }, + "tooltips": { + "networkInterface": "網路介面", + "unifiedDelay": "開啟統一延遲時,會進行兩次延遲測試,以消除連線握手等帶來的不同類型節點的延遲差異", + "logLevel": "僅對日誌目錄 Service 資料夾下的內核日誌檔案生效", + "openUwpTool": "Windows 8 開始限制 UWP 應用程式(如Microsoft Store)直接存取本機主機的網路服務,使用此工具可繞過該限制" + }, + "options": { + "logLevel": { + "debug": "Debug", + "info": "Info", + "warning": "Warn", + "error": "Error", + "silent": "Silent" + } + } + } + } + }, + "components": { + "verge": { + "basic": { + "title": "Verge 基礎設定", + "actions": { + "browse": "瀏覽" + }, + "trayOptions": { + "showMainWindow": "顯示主視窗", + "showTrayMenu": "顯示系統匣選單", + "disable": "停用" + }, + "fields": { + "language": "語言設定", + "themeMode": "主題模式", + "trayClickEvent": "系統匣點擊事件", + "copyEnvType": "複製環境變數類型", + "startPage": "啟動頁面", + "startupScript": "啟動指令碼", + "themeSetting": "主題設定", + "layoutSetting": "介面設定", + "misc": "雜項設定", + "hotkeySetting": "快速鍵設定" + } + }, + "advanced": { + "title": "Verge 進階設定", + "tooltips": { + "backupInfo": "支援本機或 WebDAV 方式備份配置檔案", + "openConfDir": "如果軟體執行異常,!備份!並刪除此資料夾下的所有檔案,重新啟動軟體", + "liteMode": "關閉 GUI 介面,僅保留內核執行" + }, + "actions": { + "copyVersion": "複製Verge版本號" + }, + "notifications": { + "latestVersion": "目前已是最新版本", + "versionCopied": "Verge版本已複製到剪貼簿" + }, + "fields": { + "backupSetting": "備份設定", + "runtimeConfig": "執行期設定", + "openConfDir": "配置目錄", + "openCoreDir": "內核目錄", + "openLogsDir": "日誌目錄", + "checkUpdates": "檢查更新", + "openDevTools": "開發人員工具", + "liteModeSettings": "輕量模式設定", + "exit": "離開", + "exportDiagnostics": "匯出診斷資訊", + "vergeVersion": "Verge 版本" + } + }, + "theme": { + "title": "主題設定", + "fields": { + "primaryColor": "主要顏色", + "secondaryColor": "次要顏色", + "primaryText": "文字主要顏色", + "secondaryText": "文字次要顏色", + "infoColor": "資訊顏色", + "warningColor": "警告顏色", + "errorColor": "錯誤顏色", + "successColor": "成功顏色", + "fontFamily": "字型系列", + "cssInjection": "CSS 注入" + }, + "actions": { + "editCss": "Edit CSS" + }, + "dialogs": { + "editCssTitle": "Edit CSS" + } + }, + "layout": { + "title": "介面設定", + "fields": { + "preferSystemTitlebar": "優先使用系統標題欄", + "trafficGraph": "流量圖表", + "memoryUsage": "內核佔用", + "proxyGroupIcon": "代理組圖示", + "hoverNavigator": "懸浮跳轉導航", + "hoverNavigatorDelay": "懸浮跳轉導航延遲", + "navIcon": "導覽列圖示", + "trayIcon": "系統匣圖示", + "showProxyGroupsInline": "將代理組顯示在系統匣一級選單", + "commonTrayIcon": "一般系統匣圖示", + "systemProxyTrayIcon": "系統代理系統匣圖示", + "tunTrayIcon": "虛擬網路介面卡模式系統匣圖示", + "enableTrayIcon": "啟用系統匣圖示", + "enableTraySpeed": "啟用系統匣速率" + }, + "tooltips": { + "hoverNavigator": "滑鼠懸停在字母上時自動捲動到對應代理組", + "hoverNavigatorDelay": "滑鼠懸停後觸發自動跳轉前等待的毫秒數" + }, + "options": { + "icon": { + "monochrome": "單色圖示", + "colorful": "彩色圖示", + "disable": "停用" + } + } + } + } + }, + "modals": { + "clashPort": { + "title": "連接埠設定", + "fields": { + "mixed": "混合代理連接埠", + "socks": "SOCKS 代理連接埠", + "http": "HTTP(S) 代理連接埠", + "redir": "Redir 透明代理連接埠", + "tproxy": "Tproxy Port" + }, + "actions": { + "random": "隨機連接埠" + }, + "messages": { + "saved": "連結埠設定已儲存", + "saveFailed": "連結埠設定儲存失敗" + } + }, + "clashCore": { + "variants": { + "release": "正式版", + "alpha": "預覽版" + } + }, + "liteMode": { + "title": "輕量模式設定", + "actions": { + "enterNow": "立即進入輕量模式" + }, + "toggles": { + "autoEnter": "自動進入輕量模式" + }, + "tooltips": { + "autoEnter": "啟用後,將在視窗關閉一段時間後自動啟用輕量模式" + }, + "fields": { + "delay": "自動進入輕量模式延遲" + }, + "messages": { + "autoEnterHint": "關閉視窗後,輕量模式將在 {{n}} 分鐘後自動啟用" + } + }, + "backup": { + "title": "備份設定", + "tabs": { + "local": "本機備份", + "webdav": "WebDAV 備份" + }, + "actions": { + "selectTarget": "選擇備份目標", + "backup": "備份", + "export": "匯出", + "exportBackup": "匯出備份", + "deleteBackup": "刪除備份", + "restore": "還原", + "restoreBackup": "還原備份" + }, + "fields": { + "webdavUrl": "WebDAV 伺服器位址 http(s)://", + "username": "使用者名稱", + "info": "在應用程式資料目錄中建立本機備份,您可以透過下方列表進行還原或刪除。" + }, + "messages": { + "webdavUrlRequired": "WebDAV 伺服器位址不能為空", + "invalidWebdavUrl": "無效的 WebDAV 伺服器位址格式", + "usernameRequired": "使用者名稱不能為空", + "passwordRequired": "密碼不能為空", + "webdavConfigSaved": "WebDAV 配置儲存成功", + "webdavConfigSaveFailed": "儲存 WebDAV 配置失敗: {{error}}", + "backupCreated": "備份建立成功", + "backupFailed": "備份失敗: {{error}}", + "localBackupCreated": "本機備份建立成功", + "localBackupFailed": "本機備份失敗", + "restoreSuccess": "還原成功,應用程式將在 1 秒後重啟", + "localBackupExported": "本機備份匯出成功", + "localBackupExportFailed": "本機備份匯出失敗", + "confirmDelete": "確認是否刪除此備份檔案嗎?", + "confirmRestore": "確認還原此份檔案嗎?" + }, + "table": { + "filename": "檔案名稱", + "backupTime": "備份時間", + "actions": "動作", + "noBackups": "暫無備份", + "rowsPerPage": "Rows per page" + } + }, + "misc": { + "title": "雜項設定", + "fields": { + "appLogLevel": "應用程式日誌等級", + "appLogMaxSize": "應用程式日誌最大大小", + "appLogMaxCount": "應用程式日誌最大數量", + "autoCloseConnections": "自動關閉連線", + "autoCheckUpdate": "自動檢查更新", + "enableBuiltinEnhanced": "內建增強功能", + "proxyLayoutColumns": "代理頁面欄數", + "autoLogClean": "自動清理日誌", + "autoDelayDetection": "自動延遲偵測", + "defaultLatencyTest": "預設測試網址", + "defaultLatencyTimeout": "測試逾時" + }, + "tooltips": { + "autoCloseConnections": "當代理組選中節點或代理模式變動時,關閉已建立的連線", + "enableBuiltinEnhanced": "配置檔案的相容性處理", + "autoDelayDetection": "在背景定時偵測目前節點延遲", + "defaultLatencyTest": "僅用於 HTTP 客戶端請求測試,不會對配置檔案產生影響" + }, + "options": { + "proxyLayoutColumns": { + "auto": "自動欄數" + }, + "autoLogClean": { + "never": "不清理", + "retainDays": "保留 {{n}} 天" + } + } + }, + "update": { + "title": "New Version v{{version}}", + "actions": { + "goToRelease": "前往發佈頁面", + "update": "更新" + }, + "messages": { + "portableError": "可攜式版不支援應用程式內更新,請手動下載替換", + "breakChangeError": "此版本為重大更新,不支援應用程式內更新,請解除安裝後手動下載安裝" + } + }, + "sysproxy": { + "title": "系統代理設定", + "fieldsets": { + "currentStatus": "目前系統代理" + }, + "fields": { + "enableStatus": "啟用狀態:", + "serverAddr": "服務位址:", + "pacUrl": "PAC 位址:", + "proxyHost": "代理主機", + "usePacMode": "使用 PAC 模式", + "proxyGuard": "系統代理守護", + "guardDuration": "代理守護間隔", + "alwaysUseDefaultBypass": "始終使用預設繞過", + "proxyBypass": "代理繞過設定:", + "bypass": "目前繞過:", + "pacScriptContent": "PAC 指令碼內容" + }, + "tooltips": { + "proxyGuard": "開啟以防止其他軟體修改作業系統的代理設定" + }, + "messages": { + "durationTooShort": "代理守護間隔時間不得低於 1 秒", + "invalidBypass": "無效的代理繞過格式", + "invalidProxyHost": "代理主機格式無效" + }, + "actions": { + "editPac": "編輯 PAC" + } + }, + "tun": { + "title": "虛擬網路介面卡模式", + "fields": { + "stack": "虛擬網路介面卡模式堆疊", + "device": "Device Name", + "autoRoute": "自動設定全域路由", + "strictRoute": "嚴格路由", + "autoDetectInterface": "自動偵測流量輸出介面", + "dnsHijack": "DNS 綁架", + "mtu": "最大傳輸單位" + }, + "tooltips": { + "dnsHijack": "Please use , to separate multiple DNS servers" + }, + "messages": { + "applied": "設定已套用" + } + }, + "dns": { + "dialog": { + "title": "DNS 覆寫", + "warning": "如果你不清楚這裡的設定請不要修改,並保持 DNS 覆寫開啟" + }, + "sections": { + "general": "DNS 設定", + "fallbackFilter": "備援篩選設定", + "hosts": "Hosts 設定" + }, + "fields": { + "enable": "啟用 DNS", + "listen": "DNS 監聽位址", + "enhancedMode": "增強模式", + "fakeIpRange": "Fake IP 範圍", + "fakeIpFilterMode": "Fake IP 篩選模式", + "ipv6": { + "label": "IPv6", + "description": "啟用 IPv6 DNS 解析" + }, + "preferH3": { + "label": "優先使用 HTTP/3", + "description": "DNS DOH 使用 HTTP/3 協定" + }, + "respectRules": { + "label": "遵循路由規則", + "description": "DNS 連線遵循路由規則" + }, + "useHosts": { + "label": "使用 Hosts", + "description": "啟用透過 hosts 檔案解析網域" + }, + "useSystemHosts": { + "label": "使用系統 Hosts", + "description": "啟用透過系統 hosts 檔案解析網域" + }, + "directPolicy": { + "label": "直連域名伺服器遵循策略", + "description": "是否遵循 nameserver-policy 設定" + }, + "defaultNameserver": { + "label": "預設域名伺服器", + "description": "用於解析 DNS 伺服器的預設 DNS 伺服器" + }, + "nameserver": { + "label": "域名伺服器", + "description": "DNS 伺服器列表,用逗號分隔" + }, + "fallback": { + "label": "備援伺服器", + "description": "備援 DNS 伺服器列表,用逗號分隔" + }, + "proxy": { + "label": "代理節點 DNS", + "description": "代理節點網域解析伺服器,僅用於解析代理節點的網域,用逗號分隔" + }, + "directNameserver": { + "label": "直連域名伺服器", + "description": "直連輸出網域解析伺服器,支援 system 關鍵字,用逗號分隔" + }, + "fakeIpFilter": { + "label": "Fake IP 篩選", + "description": "跳過 Fake IP 解析的網域,用逗號分隔" + }, + "nameserverPolicy": { + "label": "域名伺服器策略", + "description": "特定網域的 DNS 伺服器,多個伺服器使用分號分隔,格式: domain=server1;server2" + }, + "geoipFiltering": { + "label": "GeoIP 篩選", + "description": "啟用 GeoIP 備援篩選" + }, + "geoipCode": "GeoIP 國家代碼", + "fallbackIpCidr": { + "label": "備援 IP CIDR", + "description": "不使用備援伺服器的 IP CIDR,用逗號分隔" + }, + "fallbackDomain": { + "label": "備援網域", + "description": "使用備援伺服器的網域,用逗號分隔" + }, + "hosts": { + "label": "Hosts", + "description": "自訂網域到 IP 或網域的映射,用逗號分隔" + } + }, + "messages": { + "saved": "DNS 設定已儲存", + "configError": "DNS 設定錯誤:" + }, + "errors": { + "invalid": "Invalid configuration", + "invalidYaml": "YAML 格式無效" + } + }, + "webUI": { + "actions": { + "openUrl": "開啟網址" + }, + "title": "網頁介面", + "messages": { + "supportedPlaceholders": "支援 %host, %port, %secret", + "placeholderInstruction": "使用 %host, %port, %secret 表示 主機, 連接埠, 存取金鑰" + } + }, + "hotkey": { + "toggles": { + "enableGlobal": "啟用全域快速鍵" + }, + "title": "快速鍵設定", + "functions": { + "rule": "規則模式", + "global": "全域模式", + "openOrCloseDashboard": "開啟/關閉儀表板", + "toggleSystemProxy": "開啟/關閉系統代理", + "toggleTunMode": "開啟/關閉 虛擬網路介面卡模式", + "entryLightweightMode": "進入輕量模式", + "direct": "直連模式" + } + }, + "password": { + "prompts": { + "enterRoot": "請輸入您的 root 密碼" + } + }, + "networkInterface": { + "title": "網路介面", + "fields": { + "ipAddress": "IP 位址", + "macAddress": "MAC 位址" + } + } + }, + "feedback": { + "notifications": { + "clash": { + "restartSuccess": "已重啟 Clash 內核", + "versionUpdated": "內核版本已更新", + "alreadyLatestVersion": "已經是最新內核版本", + "changeSuccess": "內核切換成功", + "changeFailed": "無法切換內核", + "geoDataUpdated": "已更新 GeoData" + }, + "clashService": { + "installSuccess": "已成功安裝服務", + "uninstallSuccess": "已成功解除安裝服務" + }, + "updater": { + "withClashProxySuccess": "使用 Clash 代理更新成功", + "withClashProxyFailed": "使用 Clash 代理更新也失敗" + } + } + }, + "statuses": { + "clash": { + "stopping": "內核停止中...", + "restarting": "內核重啟中..." + }, + "clashService": { + "installing": "安裝服務中...", + "uninstalling": "服務解除安裝中..." + } + } +} diff --git a/src/locales/zhtw/shared.json b/src/locales/zhtw/shared.json new file mode 100644 index 000000000..48cb83c2f --- /dev/null +++ b/src/locales/zhtw/shared.json @@ -0,0 +1,129 @@ +{ + "actions": { + "cancel": "取消", + "close": "關閉", + "confirm": "確認", + "save": "儲存", + "delete": "刪除", + "edit": "編輯", + "new": "新增", + "enable": "啟用", + "upgrade": "升級內核", + "restart": "重啟內核", + "resetToDefault": "重設為預設值", + "refresh": "重整", + "retry": "重試", + "refreshPage": "重新整理頁面", + "showDetails": "顯示詳情", + "hideDetails": "隱藏詳情", + "listView": "列表檢視", + "tableView": "表格檢視", + "pause": "暫停", + "resume": "繼續", + "closeAll": "關閉全部", + "clear": "清除" + }, + "labels": { + "updateAt": "更新於", + "timeout": "逾時", + "icon": "圖示", + "name": "名稱", + "readOnly": "唯讀", + "expireTime": "到期時間", + "updateTime": "更新時間", + "usedTotal": "已使用 / 總量", + "from": "來自", + "password": "密碼", + "retryAttempts": "重試次數", + "downloaded": "下載量", + "uploaded": "上傳量" + }, + "statuses": { + "enabled": "已啟用", + "disabled": "已停用", + "saving": "儲存中...", + "empty": "空空如也" + }, + "units": { + "milliseconds": "毫秒", + "seconds": "秒", + "minutes": "分鐘", + "kilobytes": "KB", + "files": "檔案" + }, + "placeholders": { + "filter": "篩選條件", + "matchCase": "區分大小寫", + "matchWholeWord": "完整字詞配對", + "useRegex": "使用正規表示式" + }, + "validation": { + "invalidRegex": "無效的正規表示式" + }, + "window": { + "maximize": "最大化", + "minimize": "最小化" + }, + "editorModes": { + "visualization": "視覺化", + "advanced": "進階" + }, + "feedback": { + "errors": { + "trafficStats": "流量統計錯誤", + "trafficStatsDescription": "流量統計元件發生錯誤,已停用以避免當機。" + }, + "notices": { + "raw": "{{message}}", + "prefixedRaw": "{{prefix}} {{message}}" + }, + "notifications": { + "importSuccess": "匯入設定檔成功", + "importSubscriptionSuccess": "匯入訂閱成功", + "importWithClashProxy": "使用 Clash 代理匯入訂閱成功", + "updateAvailable": "有可用更新", + "saved": "儲存成功", + "common": { + "copySuccess": "複製成功", + "saveSuccess": "設定儲存完成", + "saveFailed": "設定儲存失敗" + } + }, + "validation": { + "config": { + "failed": "訂閱配置校驗失敗,請檢查訂閱配置文件,變更已撤銷,錯誤詳情:", + "bootFailed": "啟動訂閱配置校驗失敗,已使用預設配置啟動;請檢查訂閱配置文件,錯誤詳情:", + "coreChangeFailed": "切換內核時配置校驗失敗,已使用預設配置啟動;請檢查訂閱配置文件,錯誤詳情:", + "processTerminated": "驗證程序被終止" + }, + "script": { + "syntaxError": "指令碼語法錯誤,變更已撤銷", + "missingMain": "指令碼錯誤,變更已撤銷", + "fileNotFound": "檔案遺失,變更已撤銷", + "fileError": "指令碼檔案錯誤,變更已撤銷" + }, + "yaml": { + "syntaxError": "YAML 語法錯誤,變更已撤銷", + "readError": "YAML 讀取錯誤,變更已撤銷", + "mappingError": "YAML 映射錯誤,變更已撤銷", + "keyError": "YAML 鍵錯誤,變更已撤銷", + "generalError": "YAML 錯誤,變更已撤銷" + }, + "merge": { + "syntaxError": "覆寫檔案語法錯誤,變更已撤銷", + "mappingError": "覆寫檔案映射錯誤,變更已撤銷", + "keyError": "覆寫檔案鍵錯誤,變更已撤銷", + "generalError": "覆寫檔案錯誤,變更已撤銷" + } + } + }, + "filters": { + "logLevels": { + "all": "ALL", + "debug": "DEBUG", + "info": "INFO", + "warn": "WARN", + "error": "ERROR" + } + } +} diff --git a/src/locales/zhtw/tests.json b/src/locales/zhtw/tests.json new file mode 100644 index 000000000..dbdc26944 --- /dev/null +++ b/src/locales/zhtw/tests.json @@ -0,0 +1,53 @@ +{ + "page": { + "actions": { + "testAll": "測試全部" + }, + "title": "測試" + }, + "components": { + "item": { + "actions": { + "test": "測試" + } + } + }, + "modals": { + "test": { + "title": { + "create": "新增測試", + "edit": "編輯測試" + }, + "fields": { + "url": "測試網址" + } + } + }, + "statuses": { + "test": { + "pending": "待檢測", + "yes": "支援", + "no": "不支援", + "failed": "測試失敗", + "completed": "檢測完成", + "disallowedIsp": "不允許的網際網路服務供應商", + "originalsOnly": "僅限原創", + "noDisney": "不支援(IP被Disney+禁止)", + "unsupportedRegion": "不支援的國家/地區", + "failedNetwork": "測試失敗(網路連線問題)" + } + }, + "unlock": { + "page": { + "actions": { + "testing": "測試中..." + }, + "empty": "目前沒有解鎖測試項目", + "messages": { + "detectionFailedWithName": "{{name}} 檢測失敗", + "detectionTimeout": "檢測逾時或失敗" + }, + "title": "解鎖測試" + } + } +} diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index 4111e3ef5..73ff968a4 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -437,7 +437,7 @@ const Layout = () => { : theme.palette.warning.dark, })} > - {t("Menu reorder mode")} + {t("layout.components.navigation.menu.reorderMode")} )} @@ -514,7 +514,9 @@ const Layout = () => { onClick={menuUnlocked ? handleLockMenu : handleUnlockMenu} dense > - {menuUnlocked ? t("Lock menu order") : t("Unlock menu order")} + {menuUnlocked + ? t("layout.components.navigation.menu.lock") + : t("layout.components.navigation.menu.unlock")} diff --git a/src/pages/_layout/notificationHandlers.ts b/src/pages/_layout/notificationHandlers.ts index 8d5bb544b..58631b8f3 100644 --- a/src/pages/_layout/notificationHandlers.ts +++ b/src/pages/_layout/notificationHandlers.ts @@ -15,69 +15,75 @@ export const handleNoticeMessage = ( // 未来细分事件通知时,可以考虑传入订阅 ID 或其他标识符 // navigate("/profile", { state: { current: msg } }); navigate("/profile"); - showNotice("success", t("Import Subscription Successful")); + showNotice.success( + "shared.feedback.notifications.importSubscriptionSuccess", + ); }, "import_sub_url::error": () => { navigate("/profile"); - showNotice("error", msg); + showNotice.error(msg); }, - "set_config::error": () => showNotice("error", msg), - // 后端暂时没有启用相关通知, 批量更新可能造成扰人提醒 - // update_success: () => showNotice("success", t("Update subscription successfully")), + "set_config::error": () => showNotice.error(msg), update_with_clash_proxy: () => - showNotice( - "success", - `${t("Update with Clash proxy successfully")} ${msg}`, + showNotice.success( + "settings.feedback.notifications.updater.withClashProxySuccess", + msg, ), update_failed_even_with_clash: () => - showNotice( - "error", - `${t("Update failed even with Clash proxy")}: ${msg}`, + showNotice.error( + "settings.feedback.notifications.updater.withClashProxyFailed", + msg, ), - update_failed: () => showNotice("error", msg), + update_failed: () => showNotice.error(msg), "config_validate::boot_error": () => - showNotice("error", `${t("Boot Config Validation Failed")} ${msg}`), + showNotice.error("shared.feedback.validation.config.bootFailed", msg), "config_validate::core_change": () => - showNotice( - "error", - `${t("Core Change Config Validation Failed")} ${msg}`, + showNotice.error( + "shared.feedback.validation.config.coreChangeFailed", + msg, ), "config_validate::error": () => - showNotice("error", `${t("Config Validation Failed")} ${msg}`), + showNotice.error("shared.feedback.validation.config.failed", msg), "config_validate::process_terminated": () => - showNotice("error", t("Config Validation Process Terminated")), + showNotice.error("shared.feedback.validation.config.processTerminated"), "config_validate::stdout_error": () => - showNotice("error", `${t("Config Validation Failed")} ${msg}`), + showNotice.error("shared.feedback.validation.config.failed", msg), "config_validate::script_error": () => - showNotice("error", `${t("Script File Error")} ${msg}`), + showNotice.error("shared.feedback.validation.script.fileError", msg), "config_validate::script_syntax_error": () => - showNotice("error", `${t("Script Syntax Error")} ${msg}`), + showNotice.error("shared.feedback.validation.script.syntaxError", msg), "config_validate::script_missing_main": () => - showNotice("error", `${t("Script Missing Main")} ${msg}`), + showNotice.error("shared.feedback.validation.script.missingMain", msg), "config_validate::file_not_found": () => - showNotice("error", `${t("File Not Found")} ${msg}`), + showNotice.error("shared.feedback.validation.script.fileNotFound", msg), "config_validate::yaml_syntax_error": () => - showNotice("error", `${t("YAML Syntax Error")} ${msg}`), + showNotice.error("shared.feedback.validation.yaml.syntaxError", msg), "config_validate::yaml_read_error": () => - showNotice("error", `${t("YAML Read Error")} ${msg}`), + showNotice.error("shared.feedback.validation.yaml.readError", msg), "config_validate::yaml_mapping_error": () => - showNotice("error", `${t("YAML Mapping Error")} ${msg}`), + showNotice.error("shared.feedback.validation.yaml.mappingError", msg), "config_validate::yaml_key_error": () => - showNotice("error", `${t("YAML Key Error")} ${msg}`), + showNotice.error("shared.feedback.validation.yaml.keyError", msg), "config_validate::yaml_error": () => - showNotice("error", `${t("YAML Error")} ${msg}`), + showNotice.error("shared.feedback.validation.yaml.generalError", msg), "config_validate::merge_syntax_error": () => - showNotice("error", `${t("Merge File Syntax Error")} ${msg}`), + showNotice.error("shared.feedback.validation.merge.syntaxError", msg), "config_validate::merge_mapping_error": () => - showNotice("error", `${t("Merge File Mapping Error")} ${msg}`), + showNotice.error("shared.feedback.validation.merge.mappingError", msg), "config_validate::merge_key_error": () => - showNotice("error", `${t("Merge File Key Error")} ${msg}`), + showNotice.error("shared.feedback.validation.merge.keyError", msg), "config_validate::merge_error": () => - showNotice("error", `${t("Merge File Error")} ${msg}`), + showNotice.error("shared.feedback.validation.merge.generalError", msg), "config_core::change_success": () => - showNotice("success", `${t("Core Changed Successfully")}: ${msg}`), + showNotice.success( + "settings.feedback.notifications.clash.changeSuccess", + msg, + ), "config_core::change_error": () => - showNotice("error", `${t("Failed to Change Core")}: ${msg}`), + showNotice.error( + "settings.feedback.notifications.clash.changeFailed", + msg, + ), }; const handler = handlers[status]; diff --git a/src/pages/_routers.tsx b/src/pages/_routers.tsx index 123b4b3d4..49ffad672 100644 --- a/src/pages/_routers.tsx +++ b/src/pages/_routers.tsx @@ -29,49 +29,49 @@ import UnlockPage from "./unlock"; export const navItems = [ { - label: "Label-Home", + label: "layout.components.navigation.tabs.home", path: "/", icon: [, ], Component: HomePage, }, { - label: "Label-Proxies", + label: "layout.components.navigation.tabs.proxies", path: "/proxies", icon: [, ], Component: ProxiesPage, }, { - label: "Label-Profiles", + label: "layout.components.navigation.tabs.profiles", path: "/profile", icon: [, ], Component: ProfilesPage, }, { - label: "Label-Connections", + label: "layout.components.navigation.tabs.connections", path: "/connections", icon: [, ], Component: ConnectionsPage, }, { - label: "Label-Rules", + label: "layout.components.navigation.tabs.rules", path: "/rules", icon: [, ], Component: RulesPage, }, { - label: "Label-Logs", + label: "layout.components.navigation.tabs.logs", path: "/logs", icon: [, ], Component: LogsPage, }, { - label: "Label-Unlock", + label: "layout.components.navigation.tabs.unlock", path: "/unlock", icon: [, ], Component: UnlockPage, }, { - label: "Label-Settings", + label: "layout.components.navigation.tabs.settings", path: "/settings", icon: [, ], Component: SettingsPage, diff --git a/src/pages/connections.tsx b/src/pages/connections.tsx index bb68f7925..5286b73e2 100644 --- a/src/pages/connections.tsx +++ b/src/pages/connections.tsx @@ -33,13 +33,48 @@ const initConn: IConnections = { type OrderFunc = (list: IConnectionsItem[]) => IConnectionsItem[]; +const ORDER_OPTIONS = [ + { + id: "default", + labelKey: "connections.components.order.default", + fn: (list: IConnectionsItem[]) => + list.sort( + (a, b) => + new Date(b.start || "0").getTime()! - + new Date(a.start || "0").getTime()!, + ), + }, + { + id: "uploadSpeed", + labelKey: "connections.components.order.uploadSpeed", + fn: (list: IConnectionsItem[]) => + list.sort((a, b) => b.curUpload! - a.curUpload!), + }, + { + id: "downloadSpeed", + labelKey: "connections.components.order.downloadSpeed", + fn: (list: IConnectionsItem[]) => + list.sort((a, b) => b.curDownload! - a.curDownload!), + }, +] as const; + +type OrderKey = (typeof ORDER_OPTIONS)[number]["id"]; + +const orderFunctionMap = ORDER_OPTIONS.reduce>( + (acc, option) => { + acc[option.id] = option.fn; + return acc; + }, + {} as Record, +); + const ConnectionsPage = () => { const { t } = useTranslation(); const pageVisible = useVisibility(); const [match, setMatch] = useState<(input: string) => boolean>( () => () => true, ); - const [curOrderOpt, setCurOrderOpt] = useState("Default"); + const [curOrderOpt, setCurOrderOpt] = useState("default"); const { response: { data: connections }, @@ -49,22 +84,6 @@ const ConnectionsPage = () => { const isTableLayout = setting.layout === "table"; - const orderOpts = useMemo>( - () => ({ - Default: (list) => - list.sort( - (a, b) => - new Date(b.start || "0").getTime()! - - new Date(a.start || "0").getTime()!, - ), - "Upload Speed": (list) => - list.sort((a, b) => b.curUpload! - a.curUpload!), - "Download Speed": (list) => - list.sort((a, b) => b.curDownload! - a.curDownload!), - }), - [], - ); - const [isPaused, setIsPaused] = useState(false); const [frozenData, setFrozenData] = useState(null); @@ -90,7 +109,7 @@ const ConnectionsPage = () => { }, [isPaused, frozenData, connections, pageVisible]); const [filterConn] = useMemo(() => { - const orderFunc = orderOpts[curOrderOpt]; + const orderFunc = orderFunctionMap[curOrderOpt]; let conns = displayData.connections?.filter((conn) => { const { host, destinationIP, process } = conn.metadata; return ( @@ -101,7 +120,7 @@ const ConnectionsPage = () => { if (orderFunc) conns = orderFunc(conns ?? []); return [conns]; - }, [displayData, match, curOrderOpt, orderOpts]); + }, [displayData, match, curOrderOpt]); const onCloseAll = useLockFn(closeAllConnections); @@ -129,7 +148,11 @@ const ConnectionsPage = () => { return ( {t("Connections")}} + title={ + + {t("connections.page.title")} + + } contentStyle={{ height: "100%", display: "flex", @@ -140,10 +163,12 @@ const ConnectionsPage = () => { header={ - {t("Downloaded")}: {parseTraffic(displayData.downloadTotal)} + {t("shared.labels.downloaded")}:{" "} + {parseTraffic(displayData.downloadTotal)} - {t("Uploaded")}: {parseTraffic(displayData.uploadTotal)} + {t("shared.labels.uploaded")}:{" "} + {parseTraffic(displayData.uploadTotal)} { } > {isTableLayout ? ( - + ) : ( - + )} {isPaused ? ( @@ -175,7 +202,9 @@ const ConnectionsPage = () => { )} } @@ -197,11 +226,11 @@ const ConnectionsPage = () => { {!isTableLayout && ( setCurOrderOpt(e.target.value)} + onChange={(e) => setCurOrderOpt(e.target.value as OrderKey)} > - {Object.keys(orderOpts).map((opt) => ( - - {t(opt)} + {ORDER_OPTIONS.map((option) => ( + + {t(option.labelKey)} ))} diff --git a/src/pages/home.tsx b/src/pages/home.tsx index b869787e0..efb4b9062 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -112,7 +112,7 @@ const HomeSettingsDialog = ({ return ( - {t("Home Settings")} + {t("home.page.settings.title")} handleToggle("profile")} /> } - label={t("Profile Card")} + label={t("home.page.settings.cards.profile")} /> handleToggle("proxy")} /> } - label={t("Current Proxy Card")} + label={t("home.page.settings.cards.currentProxy")} /> handleToggle("network")} /> } - label={t("Network Settings Card")} + label={t("home.page.settings.cards.network")} /> handleToggle("mode")} /> } - label={t("Proxy Mode Card")} + label={t("home.page.settings.cards.proxyMode")} /> handleToggle("traffic")} /> } - label={t("Traffic Stats Card")} + label={t("home.page.settings.cards.traffic")} /> handleToggle("test")} /> } - label={t("Website Tests Card")} + label={t("home.page.settings.cards.tests")} /> handleToggle("ip")} /> } - label={t("IP Information Card")} + label={t("home.page.settings.cards.ip")} /> handleToggle("clashinfo")} /> } - label={t("Clash Info Cards")} + label={t("home.page.settings.cards.clashInfo")} /> handleToggle("systeminfo")} /> } - label={t("System Info Cards")} + label={t("home.page.settings.cards.systemInfo")} /> - + @@ -323,7 +323,7 @@ const HomePage = () => { renderCard( "traffic", } iconColor="secondary" > @@ -364,11 +364,11 @@ const HomePage = () => { ); return ( - + await entry_lightweight_mode()} size="small" @@ -377,12 +377,12 @@ const HomePage = () => { - + - + @@ -413,7 +413,7 @@ const NetworkSettingsCard = () => { const { t } = useTranslation(); return ( } iconColor="primary" action={null} @@ -428,7 +428,7 @@ const ClashModeEnhancedCard = () => { const { t } = useTranslation(); return ( } iconColor="info" action={null} diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx index 4e49df3a2..73e4d7fb1 100644 --- a/src/pages/logs.tsx +++ b/src/pages/logs.tsx @@ -60,7 +60,7 @@ const LogPage = () => { return ( { header={ { refreshGetClashLog(true); }} > - {t("Clear")} + {t("shared.actions.clear")} } @@ -108,11 +113,13 @@ const LogPage = () => { value={logState} onChange={(e) => handleLogLevelChange(e.target.value as LogFilter)} > - ALL - DEBUG - INFO - WARN - ERROR + {t("shared.filters.logLevels.all")} + + {t("shared.filters.logLevels.debug")} + + {t("shared.filters.logLevels.info")} + {t("shared.filters.logLevels.warn")} + {t("shared.filters.logLevels.error")} { diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx index fa3bbff0f..1beb190f4 100644 --- a/src/pages/profiles.tsx +++ b/src/pages/profiles.tsx @@ -145,13 +145,13 @@ const ProfilePage = () => { } setActivatings((prev) => prev.filter((id) => id !== previousSwitching)); - showNotice( - "info", - `${t("Profile switch interrupted by new selection")}: ${previousSwitching} → ${newProfile}`, + showNotice.info( + "profiles.page.feedback.notifications.switchInterrupted", + `${previousSwitching} → ${newProfile}`, 3000, ); }, - [t], + [], ); // 清理切换状态 @@ -191,7 +191,7 @@ const ProfilePage = () => { for (const file of paths) { if (!file.endsWith(".yaml") && !file.endsWith(".yml")) { - showNotice("error", t("Only YAML Files Supported")); + showNotice.error("profiles.page.feedback.errors.onlyYaml"); continue; } const item = { @@ -239,10 +239,17 @@ const ProfilePage = () => { await new Promise((resolve) => setTimeout(resolve, 500)); await onEnhance(false); - showNotice("success", "数据已强制刷新", 2000); - } catch (error: any) { + showNotice.success( + "profiles.page.feedback.notices.forceRefreshCompleted", + 2000, + ); + } catch (error) { console.error("[紧急刷新] 失败:", error); - showNotice("error", `紧急刷新失败: ${error.message}`, 4000); + showNotice.error( + "profiles.page.feedback.notices.emergencyRefreshFailed", + { message: String(error) }, + 4000, + ); } }); @@ -271,13 +278,13 @@ const ProfilePage = () => { if (!url) return; // 校验url是否为http/https if (!/^https?:\/\//i.test(url)) { - showNotice("error", t("Invalid Profile URL")); + showNotice.error("profiles.page.feedback.errors.invalidUrl"); return; } setLoading(true); const handleImportSuccess = async (noticeKey: string) => { - showNotice("success", t(noticeKey)); + showNotice.success(noticeKey); setUrl(""); await performRobustRefresh(); }; @@ -285,24 +292,25 @@ const ProfilePage = () => { try { // 尝试正常导入 await importProfile(url); - await handleImportSuccess("Profile Imported Successfully"); + await handleImportSuccess("shared.feedback.notifications.importSuccess"); } catch (initialErr) { console.warn("[订阅导入] 首次导入失败:", initialErr); - showNotice("info", t("Import failed, retrying with Clash proxy...")); + showNotice.info("profiles.page.feedback.notifications.importRetry"); try { // 使用自身代理尝试导入 await importProfile(url, { with_proxy: false, self_proxy: true, }); - await handleImportSuccess("Profile Imported with Clash proxy"); - } catch (retryErr: any) { + await handleImportSuccess( + "shared.feedback.notifications.importWithClashProxy", + ); + } catch (retryErr) { // 回退导入也失败 - const retryErrmsg = retryErr?.message || retryErr.toString(); - showNotice( - "error", - `${t("Import failed even with Clash proxy")}: ${retryErrmsg}`, + showNotice.error( + "profiles.page.feedback.notifications.importFail", + String(retryErr), ); } } finally { @@ -349,16 +357,14 @@ const ProfilePage = () => { // 清除SWR缓存并重新获取 await mutate("getProfiles", getProfiles(), { revalidate: true }); await onEnhance(false); - showNotice( - "error", - t("Profile imported but may need manual refresh"), + showNotice.error( + "profiles.page.feedback.notifications.importNeedsRefresh", 3000, ); } catch (finalError) { console.error(`[导入刷新] 最终刷新尝试失败:`, finalError); - showNotice( - "error", - t("Profile imported successfully, please restart if not visible"), + showNotice.error( + "profiles.page.feedback.notifications.importSuccess", 5000, ); } @@ -477,7 +483,10 @@ const ProfilePage = () => { closeAllConnections(); if (notifySuccess && success) { - showNotice("success", t("Profile Switched"), 1000); + showNotice.success( + "profiles.page.feedback.notifications.profileSwitched", + 1000, + ); } console.log( @@ -508,7 +517,7 @@ const ProfilePage = () => { } console.error(`[Profile] 切换失败:`, err); - showNotice("error", err?.message || err.toString(), 4000); + showNotice.error(err, 4000); } finally { // 只有当前profile仍然是正在切换的profile且序列号匹配时才清理状态 if ( @@ -529,7 +538,6 @@ const ProfilePage = () => { profiles, patchProfiles, mutateLogs, - t, executeBackgroundTasks, handleProfileInterrupt, cleanupSwitchState, @@ -574,10 +582,13 @@ const ProfilePage = () => { await enhanceProfiles(); mutateLogs(); if (notifySuccess) { - showNotice("success", t("Profile Reactivated"), 1000); + showNotice.success( + "profiles.page.feedback.notifications.profileReactivated", + 1000, + ); } } catch (err: any) { - showNotice("error", err.message || err.toString(), 3000); + showNotice.error(err, 3000); } finally { // 保留正在切换的profile,清除其他状态 setActivatings((prev) => @@ -597,7 +608,7 @@ const ProfilePage = () => { await onEnhance(false); } } catch (err: any) { - showNotice("error", err?.message || err.toString()); + showNotice.error(err); } finally { setActivatings([]); } @@ -713,17 +724,17 @@ const ProfilePage = () => { setSelectedProfiles(new Set()); setBatchMode(false); - showNotice("success", t("Selected profiles deleted successfully")); + showNotice.success("profiles.page.feedback.notifications.batchDeleted"); } catch (err: any) { - showNotice("error", err?.message || err.toString()); + showNotice.error(err); } finally { setActivatings([]); } }); const mode = useThemeMode(); - const islight = mode === "light" ? true : false; - const dividercolor = islight + const isLight = mode === "light"; + const dividercolor = isLight ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)"; @@ -793,7 +804,7 @@ const ProfilePage = () => { return ( @@ -803,7 +814,7 @@ const ProfilePage = () => { @@ -812,7 +823,7 @@ const ProfilePage = () => { @@ -821,7 +832,7 @@ const ProfilePage = () => { configRef.current?.open()} > @@ -830,7 +841,7 @@ const ProfilePage = () => { onEnhance(true)} > @@ -862,7 +873,11 @@ const ProfilePage = () => { { - {t("Selected")} {selectedProfiles.size} {t("items")} + {t("profiles.page.batch.summary.selected")}{" "} + {selectedProfiles.size} {t("profiles.page.batch.summary.items")} )} @@ -923,7 +939,7 @@ const ProfilePage = () => { event.preventDefault(); void onImport(); }} - placeholder={t("Profile URL")} + placeholder={t("profiles.page.importForm.placeholder")} slotProps={{ input: { sx: { pr: 1 }, @@ -931,7 +947,7 @@ const ProfilePage = () => { @@ -940,7 +956,7 @@ const ProfilePage = () => { setUrl("")} > @@ -957,7 +973,7 @@ const ProfilePage = () => { sx={{ borderRadius: "6px" }} onClick={onImport} > - {t("Import")} + {t("profiles.page.actions.import")} @@ -1002,7 +1018,7 @@ const ProfilePage = () => { if (prev !== curr && profiles.current === item.uid) { await onEnhance(false); // await restartCore(); - // Notice.success(t("Clash Core Restarted"), 1000); + // Notice.success(t("settings.feedback.notifications.clash.restartSuccess"), 1000); } }} onDelete={() => { diff --git a/src/pages/proxies.tsx b/src/pages/proxies.tsx index 89642a62d..29b630f68 100644 --- a/src/pages/proxies.tsx +++ b/src/pages/proxies.tsx @@ -15,6 +15,12 @@ import { updateProxyChainConfigInRuntime, } from "@/services/cmds"; +const MODES = ["rule", "global", "direct"] as const; +type Mode = (typeof MODES)[number]; +const MODE_SET = new Set(MODES); +const isMode = (value: unknown): value is Mode => + typeof value === "string" && MODE_SET.has(value); + const ProxyPage = () => { const { t } = useTranslation(); @@ -50,11 +56,12 @@ const ProxyPage = () => { const { verge } = useVerge(); - const modeList = useMemo(() => ["rule", "global", "direct"], []); + const modeList = useMemo(() => MODES, []); - const curMode = clashConfig?.mode?.toLowerCase(); + const normalizedMode = clashConfig?.mode?.toLowerCase(); + const curMode = isMode(normalizedMode) ? normalizedMode : undefined; - const onChangeMode = useLockFn(async (mode: string) => { + const onChangeMode = useLockFn(async (mode: Mode) => { // 断开连接 if (mode !== curMode && verge?.auto_close_connection) { closeAllConnections(); @@ -124,16 +131,20 @@ const ProxyPage = () => { }, [isChainMode, updateChainConfigData]); useEffect(() => { - if (curMode && !modeList.includes(curMode)) { + if (normalizedMode && !isMode(normalizedMode)) { onChangeMode("rule"); } - }, [curMode, modeList, onChangeMode]); + }, [normalizedMode, onChangeMode]); return ( @@ -146,7 +157,7 @@ const ProxyPage = () => { onClick={() => onChangeMode(mode)} sx={{ textTransform: "capitalize" }} > - {t(mode)} + {t(`proxies.page.modes.${mode}`)} ))} @@ -157,13 +168,13 @@ const ProxyPage = () => { onClick={onToggleChainMode} sx={{ ml: 1 }} > - {t("Chain Proxy")} + {t("proxies.page.actions.toggleChain")} } > diff --git a/src/pages/rules.tsx b/src/pages/rules.tsx index 1d0eeebad..66e7a5692 100644 --- a/src/pages/rules.tsx +++ b/src/pages/rules.tsx @@ -48,7 +48,7 @@ const RulesPage = () => { return ( { const { t } = useTranslation(); const onError = (err: any) => { - showNotice("error", err?.message || err.toString()); + showNotice.error(err); }; const toGithubRepo = useLockFn(() => { @@ -36,13 +36,13 @@ const SettingPage = () => { return ( @@ -50,7 +50,7 @@ const SettingPage = () => { @@ -59,7 +59,7 @@ const SettingPage = () => { diff --git a/src/pages/test.tsx b/src/pages/test.tsx index 66a63e743..e0148d690 100644 --- a/src/pages/test.tsx +++ b/src/pages/test.tsx @@ -141,7 +141,7 @@ const TestPage = () => { return ( } diff --git a/src/pages/unlock.tsx b/src/pages/unlock.tsx index 1993cebac..95c8bd2e3 100644 --- a/src/pages/unlock.tsx +++ b/src/pages/unlock.tsx @@ -37,6 +37,19 @@ interface UnlockItem { const UNLOCK_RESULTS_STORAGE_KEY = "clash_verge_unlock_results"; const UNLOCK_RESULTS_TIME_KEY = "clash_verge_unlock_time"; +const STATUS_LABEL_KEYS: Record = { + Pending: "tests.statuses.test.pending", + Yes: "tests.statuses.test.yes", + No: "tests.statuses.test.no", + Failed: "tests.statuses.test.failed", + Completed: "tests.statuses.test.completed", + "Disallowed ISP": "tests.statuses.test.disallowedIsp", + "Originals Only": "tests.statuses.test.originalsOnly", + "No (IP Banned By Disney+)": "tests.statuses.test.noDisney", + "Unsupported Country/Region": "tests.statuses.test.unsupportedRegion", + "Failed (Network Connection)": "tests.statuses.test.failedNetwork", +}; + const UnlockPage = () => { const { t } = useTranslation(); const theme = useTheme(); @@ -150,7 +163,8 @@ const UnlockPage = () => { invoke(cmd, args), new Promise((_, reject) => setTimeout( - () => reject(new Error(t("Detection timeout or failed"))), + () => + reject(new Error(t("tests.unlock.page.messages.detectionTimeout"))), timeout, ), ), @@ -173,10 +187,7 @@ const UnlockPage = () => { setIsCheckingAll(false); } catch (err: any) { setIsCheckingAll(false); - showNotice( - "error", - err?.message || err?.toString() || t("Detection timeout or failed"), - ); + showNotice.error("tests.unlock.page.messages.detectionTimeout", err); console.error("Failed to check media unlock:", err); } }); @@ -206,11 +217,10 @@ const UnlockPage = () => { setLoadingItems((prev) => prev.filter((item) => item !== name)); } catch (err: any) { setLoadingItems((prev) => prev.filter((item) => item !== name)); - showNotice( - "error", - err?.message || - err?.toString() || - t("Detection failed for {name}").replace("{name}", name), + showNotice.error( + "tests.unlock.page.messages.detectionFailedWithName", + { name }, + err, ); console.error(`Failed to check ${name}:`, err); } @@ -258,7 +268,7 @@ const UnlockPage = () => { return ( } @@ -288,7 +300,7 @@ const UnlockPage = () => { height: "50%", }} > - + ) : ( @@ -330,7 +342,7 @@ const UnlockPage = () => { > {item.name} - +