From 8378c7081c2871671991d4c94a09201c983f5f55 Mon Sep 17 00:00:00 2001 From: chen08209 Date: Fri, 25 Sep 2026 03:57:04 +0800 Subject: [PATCH] feat(views): rework the proxies and scan pages, lay out records by their parts and unify search A queued delay test shows a static clock until the task pool runs it, so only the running tests animate while the list scrolls. Changelog: Hide timed-out nodes and search every list --- .agents/architecture.md | 4 +- arb/intl_en.arb | 313 ++- arb/intl_ja.arb | 315 ++- arb/intl_ru.arb | 315 ++- arb/intl_zh_CN.arb | 333 ++- lib/bootstrap.dart | 3 +- lib/common/common.dart | 1 + lib/common/compute.dart | 81 +- lib/common/constant.dart | 5 + lib/common/datetime.dart | 6 +- lib/common/link.dart | 35 +- lib/common/picker.dart | 15 +- lib/common/scroll.dart | 25 +- lib/common/search.dart | 59 + lib/common/task_pool.dart | 2 + lib/enum/enum.dart | 50 +- lib/features/connection/connection.dart | 1 + .../connection/tracker_info_item.dart | 338 +-- .../connection/tracker_info_list.dart | 20 +- .../connection/tracker_speed_ranker.dart | 115 + lib/l10n/intl/messages_en.dart | 766 +++-- lib/l10n/intl/messages_ja.dart | 671 +++-- lib/l10n/intl/messages_ru.dart | 797 ++++-- lib/l10n/intl/messages_zh_CN.dart | 597 ++-- lib/l10n/l10n.dart | 2455 +++++++++++++---- lib/models/common.dart | 368 ++- lib/models/generated/common.freezed.dart | 1021 ++++++- lib/models/generated/common.g.dart | 51 + lib/models/generated/state.freezed.dart | 654 ++--- lib/models/state.dart | 23 +- lib/pages/scan.dart | 826 +++++- lib/providers/action.dart | 5 +- lib/providers/actions/proxies.dart | 158 +- lib/providers/actions/setup.dart | 169 +- lib/providers/app.dart | 312 ++- lib/providers/generated/action.g.dart | 119 +- lib/providers/generated/app.g.dart | 588 +++- lib/providers/generated/state.g.dart | 1070 +++++-- lib/providers/state/proxies.dart | 109 +- lib/views/about.dart | 367 ++- lib/views/connection/connections.dart | 106 +- lib/views/connection/requests.dart | 53 +- lib/views/developer.dart | 33 +- lib/views/disclaimer.dart | 402 +++ lib/views/logs.dart | 155 +- lib/views/profiles/add.dart | 51 +- lib/views/profiles/edit.dart | 105 +- lib/views/profiles/preview.dart | 48 +- lib/views/profiles/profiles.dart | 118 +- lib/views/proxies/card.dart | 254 +- lib/views/proxies/common.dart | 43 +- lib/views/proxies/list.dart | 301 +- lib/views/proxies/proxies.dart | 123 +- lib/views/proxies/setting.dart | 157 +- lib/views/proxies/tab.dart | 437 ++- lib/views/resources.dart | 9 +- lib/views/views.dart | 1 + lib/widgets/chip.dart | 47 +- lib/widgets/icon.dart | 192 +- lib/widgets/keyed_animated_list.dart | 122 +- lib/widgets/list.dart | 135 +- lib/widgets/loading.dart | 15 +- lib/widgets/record.dart | 213 ++ lib/widgets/scroll.dart | 527 +++- lib/widgets/search_field.dart | 68 + lib/widgets/widgets.dart | 2 + pubspec.lock | 4 +- pubspec.yaml | 2 +- test/common/compute_test.dart | 115 + test/common/datetime_test.dart | 11 + test/common/filter_test.dart | 158 +- test/common/link_test.dart | 47 + test/common/search_test.dart | 88 + test/features/tracker_speed_ranker_test.dart | 91 + test/helpers/scrollbar.dart | 45 + test/models/common_test.dart | 136 +- test/pages/scan_test.dart | 481 +++- test/providers/app_test.dart | 141 +- test/providers/geo_resource_action_test.dart | 9 +- test/providers/proxies_action_test.dart | 233 +- test/providers/setup_action_test.dart | 390 ++- test/providers/setup_state_test.dart | 54 + test/providers/state_derived_test.dart | 323 +++ test/views/connections_test.dart | 21 + test/views/logs_view_test.dart | 110 +- test/views/profile_preview_test.dart | 15 +- test/views/proxies_list_test.dart | 86 + test/views/requests_test.dart | 51 +- test/views/resources_view_test.dart | 8 +- test/widgets/connection_item_test.dart | 107 + test/widgets/connections_view_test.dart | 42 + test/widgets/detail_row_test.dart | 52 + test/widgets/floating_scrollbar_test.dart | 243 +- test/widgets/keyed_animated_list_test.dart | 39 + test/widgets/profile_focus_test.dart | 4 +- test/widgets/proxies_list_test.dart | 164 ++ test/widgets/proxies_tab_test.dart | 57 + test/widgets/proxy_card_focus_test.dart | 149 + test/widgets/scrollbar_inset_test.dart | 42 +- test/widgets/uncovered_views_test.dart | 199 +- test/widgets/views_smoke_test.dart | 155 +- 101 files changed, 15754 insertions(+), 4997 deletions(-) create mode 100644 lib/common/search.dart create mode 100644 lib/features/connection/tracker_speed_ranker.dart create mode 100644 lib/views/disclaimer.dart create mode 100644 lib/widgets/record.dart create mode 100644 lib/widgets/search_field.dart create mode 100644 test/common/search_test.dart create mode 100644 test/features/tracker_speed_ranker_test.dart create mode 100644 test/helpers/scrollbar.dart create mode 100644 test/providers/setup_state_test.dart create mode 100644 test/views/proxies_list_test.dart create mode 100644 test/widgets/detail_row_test.dart create mode 100644 test/widgets/proxies_list_test.dart create mode 100644 test/widgets/proxy_card_focus_test.dart diff --git a/.agents/architecture.md b/.agents/architecture.md index 44882e39..ae400fd4 100644 --- a/.agents/architecture.md +++ b/.agents/architecture.md @@ -230,7 +230,9 @@ surface. It is shown only outside dashboard edit mode and only when `coreLib == Proxy delay testing follows the same failure-safe UI rule. `ProxiesAction._runDelayTests` marks its keys in `pendingDelayTestsProvider` and releases them in `finally`, and a test the Core does not answer leaves the last -measurement in place; the delay-test bullets under Core API Safety in `.agents/rules.md` give the reasons. A group's delay +measurement in place; the delay-test bullets under Core API Safety in `.agents/rules.md` give the reasons. A key stays +`queued` until the `TaskPool` actually runs it, so node cards animate a loader for at most `maxConcurrentDelayTests` +nodes and show a static glyph for the rest; a loader on every queued node made fast scrolling drop frames. A group's delay test button, the tab page's action and the list page's group header alike, spins while `delayTestingGroupsProvider` holds the group; `delayTestPageGroup` marks it, ignores a second request for the same group, and clears it in `finally`, so an RPC failure cannot leave the button spinning and remounting a header does not lose the state. diff --git a/arb/intl_en.arb b/arb/intl_en.arb index cec5e552..6fe2f266 100644 --- a/arb/intl_en.arb +++ b/arb/intl_en.arb @@ -9,19 +9,32 @@ "profiles": "Profiles", "tools": "Tools", "logs": "Logs", - "logsDesc": "Captured log records", "resources": "Resources", - "resourcesDesc": "Information about external resources", "trafficUsage": "Traffic usage", "networkSpeed": "Network speed", "outboundMode": "Outbound mode", "networkDetection": "Network detection", + "serviceStatus": "Service status", + "serviceRestricted": "Access restricted", + "serviceAvailable": "Available", + "serviceUnavailable": "Unavailable", + "serviceFailed": "Check failed", + "serviceDisallowedIsp": "Disallowed ISP", + "serviceBlocked": "Blocked", + "serviceUnsupportedRegion": "Region not supported", + "serviceOriginalsOnly": "Originals only", + "serviceComingSoon": "Coming soon", + "servicePending": "Not checked", + "serviceManage": "Manage services", + "serviceCheck": "Check", + "serviceCheckAll": "Check all", + "serviceCheckedAt": "Checked at {time}", "upload": "Upload", "download": "Download", "usedTraffic": "Used traffic", "totalTraffic": "Total traffic", "expireTime": "Expiration time", - "nullProfileDesc": "No profiles yet, please add one first", + "nullProfileDesc": "Add a profile to get started", "settings": "Settings", "language": "Language", "defaultText": "Default", @@ -36,27 +49,22 @@ "themeDesc": "Set dark mode and adjust colors", "override": "Override", "allowLan": "Allow LAN", - "allowLanDesc": "Allow proxy access over the LAN", "tun": "TUN", "tunDesc": "Only effective in administrator mode", "minimizeOnExit": "Minimize on exit", - "minimizeOnExitDesc": "Override the default system exit behavior", "autoLaunch": "Auto launch", "autoLaunchDesc": "Launch automatically at system startup", "silentLaunch": "Silent launch", - "silentLaunchDesc": "Start in the background", + "silentLaunchDesc": "Start without showing the window", "autoRun": "Auto run", "autoRunDesc": "Run automatically when the app opens", "logcat": "Logcat", "logcatDesc": "Disabling hides the log entry point", "autoCheckUpdate": "Auto check for updates", - "autoCheckUpdateDesc": "Check for updates automatically when the app starts", "checkCertificate": "Verify TLS certificates", "checkCertificateDesc": "Reject untrusted certificates. Turning this off exposes subscriptions and backups to man-in-the-middle attacks", "accessControl": "Access control", "accessControlDesc": "Control which apps use the proxy", - "application": "Application", - "applicationDesc": "Adjust application settings", "edit": "Edit", "confirm": "Confirm", "update": "Update", @@ -103,12 +111,14 @@ "show": "Show", "exit": "Exit", "systemProxy": "System proxy", + "safeMode": "Safe mode", + "safeModeAppTitle": "{appName} (Safe mode)", "project": "Project", "core": "Core", "tabAnimation": "Tab animation", "desc": "A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.", - "startVpn": "Starting VPN...", - "stopVpn": "Stopping VPN...", + "startVpn": "Starting VPN…", + "stopVpn": "Stopping VPN…", "compatible": "Compatibility mode", "notSelectedTip": "The current proxy group cannot be selected", "changeProxyFailedTip": "Failed to switch proxy; the previous selection has been restored", @@ -137,28 +147,26 @@ "country": "Region", "search": "Search", "allowBypass": "Allow apps to bypass VPN", - "allowBypassDesc": "When enabled, some apps can bypass the VPN", "externalController": "External controller", "externalControllerDesc": "When enabled, the Clash core can be controlled on port 9090", "ipv6Desc": "When enabled, IPv6 traffic can be received", "app": "App", "general": "General", - "systemProxyDesc": "Set the system proxy", + "startupAndBackground": "Startup and background", + "requestsAndUpdates": "Requests and updates", + "logsAndDiagnostics": "Logs and diagnostics", "userAgent": "User-Agent", "unifiedDelay": "Unified delay", - "unifiedDelayDesc": "Remove extra delays such as handshakes", "tcpConcurrent": "TCP concurrent", - "tcpConcurrentDesc": "Allow concurrent TCP connections", "geodataLoader": "Geo low-memory mode", - "geodataLoaderDesc": "Use the low-memory Geo loader", "requests": "Requests", - "requestsDesc": "View recent request records", + "recentRequests": "Recent requests", "findProcessMode": "Find process", "init": "Init", "infiniteTime": "Never expires", "connections": "Connections", + "liveConnections": "Live connections", "inbound": "Inbound", - "connectionsDesc": "View current connection data", "intranetIP": "Intranet IP", "view": "View", "cut": "Cut", @@ -182,19 +190,18 @@ "go": "Go", "externalLink": "External link", "otherContributors": "Other contributors", + "appIconDesign": "App icon design", "autoCloseConnections": "Auto close connections", "autoCloseConnectionsDesc": "Close connections automatically after switching nodes", "onlyStatisticsProxy": "Only count proxy traffic", - "onlyStatisticsProxyDesc": "When enabled, only proxy traffic is counted", "showNotificationStopAction": "Stop button in notification", - "showNotificationStopActionDesc": "Show a stop button on the persistent notification. Turn it off if your system keeps the notification expanded because of it", "pureBlackMode": "Pure black mode", + "sidebarBlur": "Sidebar blur", + "sidebarBlurDesc": "Show the blurred desktop behind the window through the sidebar", "keepAliveIntervalDesc": "TCP keep-alive interval", "entries": " entries", "local": "Local", "remote": "Remote", - "remoteBackupDesc": "Back up data to WebDAV", - "localBackupDesc": "Back up data locally", "mode": "Mode", "time": "Time", "source": "Source", @@ -209,69 +216,119 @@ "profilesSort": "Sort profiles", "start": "Start", "stop": "Stop", - "dnsDesc": "Update DNS-related settings", "key": "Key", "value": "Value", - "hostsDesc": "Append hosts", "vpnTip": "Changes take effect after restarting the VPN", "vpnEnableDesc": "Route all system traffic through VpnService automatically", "options": "Options", - "loopback": "Loopback unlock tool", - "loopbackDesc": "Used for UWP loopback exemption", + "enabled": "Enabled", + "disabled": "Disabled", + "loopback": "UWP loopback exemption", "providers": "External resources", "proxyProviders": "Proxy providers", + "ruleProviders": "Rule providers", + "appProxyProviders": "App proxy providers", + "appRuleProviders": "App rule providers", + "behavior": "Behavior", + "format": "Format", + "providerUrlTip": "Only remote providers are supported", "subscriptionInfo": "Subscription info", "overrideDns": "Override DNS", - "overrideDnsDesc": "When enabled, the DNS options in the profile are overridden", + "overrideNtp": "Override NTP", + "ntpStatusDesc": "Take the time from an NTP server instead of the system clock", + "server": "Server", + "ntpInterval": "Sync interval (minutes)", + "dialerProxy": "Dialer proxy", + "dialerProxyDesc": "The outbound used to reach the NTP server", + "writeToSystem": "Write to system", + "writeToSystemDesc": "Also set the system clock; Android ignores it", + "overrideEntries": "Override entries", + "addOverrideEntry": "Add override entry", + "discardChanges": "Discard the changes?", + "quickEdit": "Quick edit", "status": "Status", "statusDesc": "When disabled, the system DNS is used", - "preferH3Desc": "Prefer HTTP/3 for DoH", "respectRules": "Respect rules", - "respectRulesDesc": "DNS connections follow rules; requires proxy-server-nameserver", + "respectRulesDesc": "DNS connections follow rules; requires Proxy Server Nameserver", "dnsMode": "DNS mode", "fakeipRange": "Fake-IP range", "fakeipFilter": "Fake-IP filter", - "defaultNameserver": "Default nameserver", - "defaultNameserverDesc": "Used to resolve DNS servers", - "nameserver": "Nameserver", - "nameserverDesc": "Used to resolve domains", "useHosts": "Use hosts", "useSystemHosts": "Use system hosts", - "nameserverPolicy": "Nameserver policy", - "nameserverPolicyDesc": "Specify the nameserver policy for matching domains", - "proxyNameserver": "Proxy nameserver", - "proxyNameserverDesc": "Used to resolve proxy node domains", - "fallback": "Fallback", - "fallbackDesc": "Usually an overseas DNS", "fallbackFilter": "Fallback filter", - "geoipCode": "GeoIP code", - "ipcidr": "IP/CIDR", "domain": "Domain", + "listenRoutingMark": "Listen routing mark", + "listenRoutingMarkDesc": "Linux only", + "ipv6Timeout": "IPv6 timeout (ms)", + "cacheAlgorithm": "Cache algorithm", + "cacheMaxSize": "Cache size", + "fakeipRange6": "Fake-IP range (IPv6)", + "fakeipFilterMode": "Fake-IP filter mode", + "fakeipFilterModeDesc": "blacklist excludes matches, whitelist fakes only matches, rule matches as rules", + "fakeipTtl": "Fake-IP TTL", "reset": "Reset", "actionView": "Show/Hide", "actionStart": "Start/Stop", "actionMode": "Switch mode", "actionProxy": "System proxy", "actionTun": "TUN", + "actionRuleMode": "Rule mode", + "actionGlobalMode": "Global mode", + "actionDirectMode": "Direct mode", + "actionDelayTest": "Test all delays", + "actionUpdateProfiles": "Update profiles", "disclaimer": "Disclaimer", - "disclaimerDesc": "This software is intended only for non-commercial uses such as learning and research. Using it for any commercial purpose is strictly prohibited; any commercial activity is unrelated to this software.", + "disclaimerDesc": "Before using FlClash (\"the Software\"), please read this statement carefully and make sure you understand all of it. Tapping \"Agree\" means you have read, understood, and accept every term below. If you do not agree, tap \"Exit\" and stop using the Software.", + "disclaimerSoftwareTitle": "Nature of the software", + "disclaimerSoftwareContent": "The Software is an open-source network proxy client built on the Clash.Meta (mihomo) core. It only provides local tooling such as configuration management, rule-based routing, and traffic forwarding.\n\nThe Software itself does not provide any proxy server, node, subscription, or network access service, and has no partnership, agency, or guarantee relationship with any provider of such services.", + "disclaimerUsageTitle": "Restrictions on use", + "disclaimerUsageContent": "The Software is intended only for non-commercial uses such as learning, exchange, and technical research. Using it for any commercial purpose is strictly prohibited, including but not limited to paid distribution, bundled sales, use as part of a commercial service, or doing business in the name of the Software. Any commercial activity is unrelated to the Software and its developers.\n\nUsing the Software for anything that violates the laws and regulations of your country or region is strictly prohibited, including but not limited to bypassing lawfully imposed network access restrictions, spreading illegal content, launching network attacks, or infringing the lawful rights of others.", + "disclaimerResponsibilityTitle": "Your responsibility", + "disclaimerResponsibilityContent": "You are responsible for making sure that using the Software is lawful where you live, and you alone bear the legal responsibility for everything you do with it and its consequences.\n\nThe subscriptions, nodes, and configurations you import are your own choice. Whether their source is lawful, their content is safe, and their service is reliable is a matter between you and their providers.", + "disclaimerThirdPartyTitle": "Third-party content", + "disclaimerThirdPartyContent": "Subscription links, configuration files, rule sets, scripts, external resources, and external links are all provided by third parties. The developers cannot and do not review or guarantee their legality, accuracy, security, or availability.\n\nAny data leak, financial loss, account ban, or other loss caused by third-party content is to be settled between you and the third party; the developers bear no responsibility for it.", + "disclaimerWarrantyTitle": "No warranty", + "disclaimerWarrantyContent": "The Software is provided \"as is\" and \"as available\", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, non-infringement, uninterrupted availability, freedom from errors, or freedom from security vulnerabilities.\n\nThe developers do not guarantee that the Software will meet your needs or that it will run without interruption or error.", + "disclaimerLiabilityTitle": "Limitation of liability", + "disclaimerLiabilityContent": "To the maximum extent permitted by applicable law, neither the developers nor any contributor shall be liable for any direct, indirect, incidental, special, punitive, or consequential damages arising from the use of or inability to use the Software, including but not limited to data loss, device damage, network failures, business interruption, lost profits, or any resulting legal dispute, even if advised of the possibility of such damages.", + "disclaimerPrivacyTitle": "Data collection and privacy", + "disclaimerPrivacyContent": "The Software does not collect or upload your subscription URLs, node details, configuration content, visited websites, connection records, traffic content, or logs. This data stays on your device and the developers have no access to it.\n\nThe Software only reaches the network when you use a feature that needs it, such as fetching the subscription URL you provided when updating a profile, or contacting GitHub when checking for updates.\n\nThe desktop versions (Windows, macOS, Linux) include no analytics or crash reporting service. The Android version includes the following two Google Firebase services to improve stability:", + "disclaimerCrashlyticsTitle": "Firebase Crashlytics (crash analytics)", + "disclaimerCrashlyticsContent": "When the app crashes, a crash report is uploaded automatically.\n\nWhat is collected: the crash stack trace and error message, the time of the crash, the app version and build number, the device brand and model, the Android version, screen orientation, free memory and storage, whether the device is rooted, and a random installation ID that is created on install and reset on reinstall.\n\nPurpose: only to locate and fix crashes.\n\nYou can turn it off at any time under \"Tools > General > Crash analytics\".", + "disclaimerAnalyticsTitle": "Firebase Analytics (usage statistics)", + "disclaimerAnalyticsContent": "Basic app usage statistics are collected automatically with Firebase.\n\nWhat is collected: basic events such as first launch, app opens and session length, and app updates; an app instance ID; the device model, OS version, and system language; and an approximate country- or region-level location inferred from the IP address.\n\nPurpose: only to understand the number of active devices, version distribution, and OS compatibility. The developers do not use this data for advertising, do not sell it, and do not link it to your subscriptions or configurations.", + "disclaimerDataProcessingContent": "This data is processed and stored by Google on our behalf, may be transferred to servers outside your country or region (such as in the United States), and is governed by the Google Privacy Policy and the Firebase privacy and security documentation. Crash reports are kept for up to 90 days; statistics are kept under the Firebase default retention policy.", + "disclaimerLicenseTitle": "Open-source license", + "disclaimerLicenseContent": "The Software is open source under the GPL-3.0 license. You may use, modify, and distribute it freely as long as you comply with that license, which requires derivative works to be released under GPL-3.0 as well and the original copyright notices to be kept.\n\nThird-party components in the Software, including the Clash.Meta core, follow their own licenses. The original authors are not responsible for any issue arising from modified or redistributed versions.", + "disclaimerChangesTitle": "Changes to this statement", + "disclaimerChangesContent": "The developers may revise this statement with any release, and the revision takes effect when that release is published. Continuing to use the Software after updating means you accept the revised statement.", + "disclaimerAcceptTitle": "Acceptance", + "disclaimerAcceptContent": "By installing, copying, or using the Software, you are deemed to have read and agreed to this entire statement. If you disagree with any of its terms, stop using and uninstall the Software immediately.", + "disclaimerAndroidOnly": "Android only", + "disclaimerGooglePrivacy": "Google Privacy Policy", + "disclaimerFirebasePrivacy": "Firebase privacy and security", "agree": "Agree", "hotkeyManagement": "Hotkey management", - "hotkeyManagementDesc": "Control the app with the keyboard", - "pressKeyboard": "Please press a key", - "inputCorrectHotkey": "Please enter a valid hotkey", - "hotkeyConflict": "Hotkey conflict", + "hotkeyDesc": "Global hotkeys work even while the window is hidden. Tap an action to record its key combination.", + "hotkeyNotSet": "Not set", + "pressKeyboard": "Press a key combination", + "hotkeyNeedsModifier": "Include at least one of {modifiers}", + "hotkeyConflictWith": "Already used by “{action}”. Saving moves it here.", + "hotkeyUnavailable": "Not registered, it may be taken by another app", "remove": "Remove", - "noHotKey": "No hotkeys yet", "noNetwork": "No network", "ipv6InboundDesc": "Allow IPv6 inbound", "exportLogs": "Export logs", "exportSuccess": "Export successful", "iconStyle": "Icon style", - "onlyIcon": "Icon only", + "iconStyleFilled": "Filled", + "iconStylePlain": "Plain", + "iconStyleHidden": "Hidden", + "filter": "Filter", + "hideTimeoutProxies": "Hide timed-out nodes", + "hideTimeoutProxiesDesc": "Leave out nodes whose last delay test timed out", "stackMode": "Stack mode", "network": "Network", - "networkDesc": "Adjust network-related settings", "bypassDomain": "Bypass domains", "bypassDomainDesc": "Only takes effect while the system proxy is enabled", "resetTip": "Are you sure you want to reset?", @@ -284,7 +341,6 @@ "routeModeBypassPrivate": "Bypass private addresses", "routeModeConfig": "Use config", "routeAddress": "Route addresses", - "routeAddressDesc": "Configure the listened route addresses", "interfaceNameMode": "Outbound interface", "interfaceNameModeClear": "Clear", "interfaceNameModeFollow": "Follow config", @@ -293,6 +349,20 @@ "interfaceNameDesc": "Network interface used for outbound connections", "copyEnvVar": "Copy environment variables", "memoryInfo": "Memory info", + "total": "Total", + "releaseMemory": "Release memory", + "memoryCoreHeapInuse": "Heap in use", + "memoryCoreHeapIdle": "Heap idle", + "memoryCoreStack": "Goroutine stacks", + "memoryCoreRuntime": "Runtime overhead", + "memoryCoreNotRunning": "Core is not running", + "memoryAppResident": "Resident memory", + "memoryAppShared": "App & shared", + "memoryEstimateDesc": "Estimated from process resident memory; it may differ from what the system reports.", + "memoryEstimateSharedDesc": "The Core runs inside the app process. Its share is estimated from runtime stats, and the rest counts as app and shared memory.", + "memoryReleased": "Memory released", + "memoryReleasedSize": "Released {size}", + "releaseMemoryFailed": "Failed to release memory", "cancel": "Cancel", "fileIsUpdate": "The file has been modified. Save the changes?", "profileHasUpdate": "The profile has been modified. Turn off auto update?", @@ -305,27 +375,27 @@ "listen": "Listen", "undo": "Undo", "redo": "Redo", + "lineWrap": "Word wrap", "none": "None", - "basicConfig": "Basic configuration", - "basicConfigDesc": "Modify the basic configuration globally", "advancedConfig": "Advanced configuration", - "advancedConfigDesc": "Provides diverse configuration options", + "advancedConfigDesc": "Network, DNS, added rules, and scripts", "selectedCountTitle": "{count} selected", "addRule": "Add rule", "ruleName": "Rule name", "content": "Content", "subRule": "Sub-rule", "ruleTarget": "Rule target", - "matchTargetTitle": "Match target", "matchTarget": "MATCH-TARGET", "followProfile": "Follow profile", - "matchTargetDesc": "Where rules targeting MATCH-TARGET go. Defaults to the target of the final MATCH rule in this profile.", - "selectMatchTarget": "Select MATCH-TARGET", "sourceIp": "Source IP", "noResolve": "Don't resolve IP", "saveChanges": "Save the changes?", - "findProcessModeDesc": "Enabling causes some performance loss", - "tabAnimationDesc": "Only effective in mobile view", + "navigationBarStyle": "Bottom bar", + "floating": "Floating", + "docked": "Docked", + "slide": "Slide", + "fade": "Fade", + "pureBlack": "Pure black", "colorSchemes": "Color schemes", "palette": "Palette", "tonalSpotScheme": "Tonal spot", @@ -348,6 +418,8 @@ "launchInterruptedTip": "The app exited unexpectedly while it was starting up last time. Automatic setup was skipped for this launch; you can start it manually to retry.", "clearData": "Clear data", "textScale": "Text scaling", + "textScalePreview": "Text in the app will look like this", + "followSystem": "Follow system", "internet": "Internet", "systemApp": "System apps", "noNetworkApp": "No-network apps", @@ -361,7 +433,13 @@ "interval": "Interval", "existsTip": "{label} already exists", "maxLengthTip": "{label} must be at most {max} characters", - "multipleValuesTip": "Separate multiple values with commas", + "singleAdd": "Single add", + "batchAdd": "Batch add", + "batchListInputTip": "One item per line, or separated by commas", + "batchMapInputTip": "One entry per line: key, a space, then value", + "batchPreviewTip": "{count} to add, {skipped} skipped as existing", + "lineIssueTip": "Line {line}: {message}", + "singleValueTip": "{label} must be a single item", "deleteTip": "Are you sure you want to delete this {label}?", "deleteMultipTip": "Are you sure you want to delete the selected {label}?", "nullTip": "No {label} yet", @@ -378,6 +456,7 @@ "import": "Import", "importFile": "Import from file", "importUrl": "Import from URL", + "startFromScratch": "Start from scratch", "autoSetSystemDns": "Auto-set system DNS", "details": "{label} details", "creationTime": "Creation time", @@ -396,7 +475,7 @@ "request": "Request", "connected": "Connected", "disconnected": "Disconnected", - "connecting": "Connecting...", + "connecting": "Connecting…", "restartCoreTip": "Are you sure you want to restart the core?", "forceRestartCoreTip": "Are you sure you want to force restart the core?", "dnsHijacking": "DNS hijacking", @@ -406,20 +485,25 @@ "crashlytics": "Crash analytics", "crashlyticsTip": "When enabled, crash logs without sensitive information are uploaded automatically when the app crashes", "appendSystemDns": "Append system DNS", - "appendSystemDnsTip": "Force-append the system DNS to the configuration", "editRule": "Edit rule", "overrideMode": "Override mode", "standardModeDesc": "Standard mode: overrides the basic configuration and offers simple rule additions", "scriptModeDesc": "Script mode: uses external extension scripts to override the configuration in one click", "addedRules": "Added rules", "controlGlobalAddedRules": "Control global added rules", + "quickAdd": "Quick add", + "rulePresetBlockQuic": "Block QUIC", + "rulePresetBlockStun": "Block STUN", + "rulePresetBlockDot": "Block DNS over TLS", + "rulePresetSystemServicesDirect": "Apple and Microsoft direct", + "rulePresetBittorrentDirect": "BitTorrent direct", + "rulePresetLanDirect": "LAN direct", "overrideScript": "Override script", "goToConfigureScript": "Go to script configuration", "editGlobalRules": "Edit global rules", - "externalFetch": "External fetch", "confirmForceCrashCore": "Are you sure you want to force crash the core?", "confirmClearAllData": "Are you sure you want to clear all data?", - "loading": "Loading...", + "loading": "Loading…", "yearsAgo": "{count, plural, =1{1 year ago} other{{count} years ago}}", "monthsAgo": "{count, plural, =1{1 month ago} other{{count} months ago}}", "daysAgo": "{count, plural, =1{1 day ago} other{{count} days ago}}", @@ -435,24 +519,31 @@ "speedStatistics": "Speed statistics", "resetPageChangesTip": "This page has changes. Are you sure you want to reset?", "overwriteTypeCustom": "Custom", - "overwriteTypeCustomDesc": "Custom mode: fully customize proxy groups and rules", + "overwriteTypeCustomDesc": "Custom mode: fully customize proxies, proxy groups and rules", "unknownNetworkError": "Unknown network error", - "restoreException": "Restore error", - "networkException": "Network error, please check your connection and try again", + "backupFromNewerVersion": "This backup comes from a newer version of the app. Update the app before restoring it", + "networkTimeoutError": "The request timed out. Check your network or proxy, then try again", + "networkHostLookupError": "Couldn't resolve the server address. Check that the URL is correct and DNS is working", + "networkConnectionError": "Couldn't connect to the server. Check your network connection or proxy settings", + "networkTlsError": "Secure connection failed. The server's certificate may be invalid, or the connection is being intercepted", + "networkCancelledError": "The request was cancelled", + "networkAccessDeniedError": "The server denied access (HTTP {code}). The link may have expired, or the credentials are wrong", + "networkNotFoundError": "Nothing was found at this address (HTTP {code}). Check that the URL is correct", + "networkRateLimitedError": "Too many requests (HTTP 429). Wait a moment and try again", + "networkServerError": "The server ran into a problem (HTTP {code}). Try again later", + "networkBadResponseError": "The server rejected the request (HTTP {code})", + "networkRequestFailed": "Network request failed: {detail}", "invalidBackupFile": "Invalid backup file", "pruneCache": "Prune cache", "backupAndRestore": "Backup and restore", "backupAndRestoreDesc": "Sync data via WebDAV or files", "restore": "Restore", "restoreSuccess": "Restore successful", - "restoreFromWebDAVDesc": "Restore data from WebDAV", - "restoreFromFileDesc": "Restore data from a file", "restoreOnlyConfig": "Restore profiles only", "restoreAllData": "Restore all data", "addProfile": "Add profile", "delayTest": "Delay test", "proxyGroupEmpty": "Proxy group is empty", - "proxyGroupNameEmpty": "Proxy group name cannot be empty", "proxyGroupNameDuplicate": "Duplicate proxy group name", "confirmExitWindow": "Are you sure you want to exit the current window?", "dataChangedSave": "Data changes detected. Save them?", @@ -464,6 +555,8 @@ "excludeProxyFilter": "Exclude proxy filter", "excludeType": "Exclude type", "expectedStatus": "Expected status", + "strategy": "Strategy", + "tolerance": "Tolerance", "selectProxies": "Select proxies", "inputProxyGroupName": "Enter the proxy group name", "helperCorruptTip": "Helper service unavailable; TUN mode cannot be enabled. Reinstall FlClash to restore it.", @@ -488,7 +581,7 @@ "basicStrategy": "Basic strategies", "editProxy": "Edit proxy", "includeAllProxyProviders": "Include all proxy providers", - "includeAllProxyProvidersTip": "When enabled, the imported proxy providers are overridden", + "includeAllProxyProvidersTip": "When enabled, the group takes every proxy provider of this profile: the subscription's own, plus the profiles and app proxy providers any proxy group uses", "addProxyProviders": "Add proxy providers", "includeAllProxies": "Include all proxies", "includeAllProxiesTip": "Imports all proxies outside proxy groups; extra proxy groups can be added below", @@ -550,17 +643,16 @@ "invalidSubRule": "{subRule} is an invalid SUB_RULE", "invalidPolicy": "{target} is an invalid policy", "invalidProxyProvider": "{providerName} is an invalid proxy provider", + "invalidRuleSet": "{ruleSet} is an invalid rule set", + "invalidNetworkContent": "Only tcp or udp is supported", + "invalidRangeContent": "Enter numbers or ranges such as 80 or 8000-9000, separated by /", + "invalidDscpContent": "A DSCP mark cannot exceed 63", "invalidProxy": "{proxyName} is an invalid proxy", - "proxyGroupDetectedAbnormal": "The current proxy group is abnormal", - "proxyProviderDetectedAbnormal": "The selected proxy providers are abnormal", - "proxyDetectedAbnormal": "The selected proxies are abnormal", - "createProfile": "Create profile", "locationPermissionRequired": "Location permission required", "locationPermissionGuide": "1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check {appName} in the list\n\nWhen you are done, return to the app to continue. Thank you for your cooperation.", "prerequisites": "Prerequisites", "ignoreBatteryOptimization": "Ignore battery optimization", "batteryOptimizationDesc": "To keep the app running in the background, disable battery optimization for it. Tap to open settings.", - "batteryOptimizationStatusTip": "Due to system limitations, the battery optimization status cannot be read correctly while running", "locationPermission": "Location permission", "locationPermissionDesc": "The system requires location permission to read the Wi-Fi name. On Android choose \"Allow all the time\", otherwise the Wi-Fi name cannot be read while the app is in the background.", "excludeSsids": "Exclude SSIDs", @@ -573,7 +665,7 @@ "editSsid": "Edit SSID", "authorized": "Authorized", "tapToAuthorize": "Tap to authorize", - "suspended": "Suspended...", + "suspended": "Suspended…", "geoOptions": "Geo options", "geoAutoUpdate": "Auto update", "geoAutoUpdateInterval": "Auto-update interval", @@ -584,7 +676,6 @@ "geoSkipped": "{name} is already up to date", "geoUpdated": "{name} updated", "secondsCount": "{count, plural, =1{1 second} other{{count} seconds}}", - "entriesCount": "{count, plural, =1{1 entry} other{{count} entries}}", "proxiesCount": "{count, plural, =1{1 proxy} other{{count} proxies}}", "rulesCount": "{count, plural, =1{1 rule} other{{count} rules}}", "changelogBreaking": "Breaking changes", @@ -600,7 +691,6 @@ "pinWindow": "Pin window", "unpinWindow": "Unpin window", "exitFullScreen": "Exit full screen", - "toggleLabel": "Toggle labels", "torch": "Flashlight", "pickFromAlbum": "Choose from album", "blockConnection": "Block connection", @@ -611,11 +701,76 @@ "previousMatch": "Previous match", "nextMatch": "Next match", "clearSearch": "Clear search", + "noSearchResults": "No matching results", "addWidget": "Add widget", "showPassword": "Show password", "hidePassword": "Hide password", "authorize": "Authorize", "installedAppsPermissionRequired": "App list permission required", "installedAppsPermissionDesc": "This system hides the installed app list until the permission is granted. Authorize it to configure the per-app proxy.", - "installedAppsPermissionDeniedMessage": "The app list permission was denied, so installed apps cannot be listed. Please grant it manually in system settings." + "installedAppsPermissionDeniedMessage": "The app list permission was denied, so installed apps cannot be listed. Please grant it manually in system settings.", + "outboundIp": "Outbound IP", + "ipAddress": "IP address", + "ipQualityLevel": "Level", + "ipQualityGood": "Good", + "ipQualityNormal": "Normal", + "ipQualityRisky": "Risky", + "ipType": "Type", + "ipTypeResidential": "Residential", + "ipTypeMobile": "Mobile network", + "ipTypeBusiness": "Business", + "ipTypeHosting": "Data center", + "ipFlags": "Flags", + "ipFlagProxy": "Proxy", + "ipFlagVpn": "VPN", + "ipFlagTor": "Tor", + "ipFlagAbuser": "Abuse history", + "ipOrganization": "Organization", + "ipAsn": "ASN", + "ipQualitySource": "Answered by", + "ipQualitySources": "Sources", + "ipQualityFailed": "Couldn't determine the IP type", + "ipQualityRetry": "Check again", + "ipSourceNoType": "No type", + "ipSourceRateLimited": "Rate limited", + "ipSourceIpMismatch": "Different outbound IP", + "hideIp": "Hide IP", + "editorUnavailable": "Editor unavailable", + "replace": "Replace", + "replaceAll": "Replace all", + "cameraPermissionRequired": "Camera permission required", + "cameraPermissionDesc": "Allow camera access in system settings to scan QR codes, or choose a QR code image from the album.", + "cameraUnavailable": "Camera unavailable", + "retry": "Retry", + "invalidProfileQrcode": "This QR code doesn't contain a profile link", + "dnsQueries": "DNS queries", + "recordType": "Record type", + "answers": "Answers", + "responseCode": "Response code", + "error": "Error", + "initiator": "Initiator", + "cache": "Cache", + "proxyNode": "Proxy node", + "yes": "Yes", + "no": "No", + "nonTextProviderFile": "This external resource is not a text file", + "addCustomProxy": "Add proxy", + "proxyDefinition": "Full configuration", + "proxyDefinitionNotMap": "The configuration must be a YAML mapping with a name and a type", + "customProxiesEmpty": "No custom proxies, so the profile's own proxies are used", + "overwriteIssueEmptyName": "The name is empty", + "overwriteIssueReservedName": "{name} is a built-in policy name and cannot be used here", + "overwriteIssueDuplicateName": "The name {name} is already used by another proxy or proxy group", + "overwriteIssueCoreRejected": "The core cannot parse this proxy: {message}", + "overwriteIssueMissingProxies": "These proxies or policies do not exist: {names}", + "overwriteIssueMissingProviders": "These proxy providers do not exist: {names}", + "overwriteIssueNoProxySource": "No proxies or proxy providers are selected, so the core rejects this group", + "overwriteIssueGroupLoop": "Proxy groups reference each other in a loop: {path}", + "overwriteIssuesSummary": "{count} items have problems, and applying this override may fail", + "overwriteIssueSubscriptionGroupMissingProxies": "The profile's own proxy groups name proxies that the custom proxies no longer include: {names}", + "overwriteIssueProviderShadowed": "The profile already has a provider named {name}, so the app-level one is not used. Rename it to use it", + "providerInUse": "{label} is still used by the custom proxy groups or rules of {profiles}. Remove it there first", + "providerSourceSubscription": "Subscription", + "providerRenameShadowed": "The subscriptions of {profiles} already have {label}, so those profiles would switch to theirs. Choose another name", + "appProviderShadowed": "The app-level one of this name is not used here" } diff --git a/arb/intl_ja.arb b/arb/intl_ja.arb index dfbdf551..c6083795 100644 --- a/arb/intl_ja.arb +++ b/arb/intl_ja.arb @@ -9,19 +9,32 @@ "profiles": "プロファイル", "tools": "ツール", "logs": "ログ", - "logsDesc": "キャプチャしたログの記録", "resources": "リソース", - "resourcesDesc": "外部リソースの関連情報", "trafficUsage": "トラフィック統計", "networkSpeed": "ネットワーク速度", "outboundMode": "アウトバウンドモード", "networkDetection": "ネットワーク検出", + "serviceStatus": "サービスの状態", + "serviceRestricted": "アクセス制限", + "serviceAvailable": "利用可能", + "serviceUnavailable": "利用不可", + "serviceFailed": "検出に失敗しました", + "serviceDisallowedIsp": "許可されていない ISP", + "serviceBlocked": "ブロック済み", + "serviceUnsupportedRegion": "対象外の地域", + "serviceOriginalsOnly": "オリジナル作品のみ", + "serviceComingSoon": "近日提供予定", + "servicePending": "未検査", + "serviceManage": "サービスを管理", + "serviceCheck": "検査", + "serviceCheckAll": "すべて検査", + "serviceCheckedAt": "{time} に検査", "upload": "アップロード", "download": "ダウンロード", "usedTraffic": "使用済みトラフィック", "totalTraffic": "合計トラフィック", "expireTime": "有効期限", - "nullProfileDesc": "プロファイルがありません。先にプロファイルを追加してください", + "nullProfileDesc": "プロファイルを追加して始めましょう", "settings": "設定", "language": "言語", "defaultText": "デフォルト", @@ -36,27 +49,22 @@ "themeDesc": "ダークモードの設定と色の調整", "override": "上書き", "allowLan": "LANプロキシ", - "allowLanDesc": "LAN経由でのプロキシ利用を許可します", "tun": "TUN", "tunDesc": "管理者モードでのみ有効", "minimizeOnExit": "終了時に最小化", - "minimizeOnExitDesc": "システム標準の終了動作を変更します", "autoLaunch": "自動起動", "autoLaunchDesc": "システム起動時に自動的に起動します", "silentLaunch": "サイレント起動", - "silentLaunchDesc": "バックグラウンドで起動します", + "silentLaunchDesc": "起動時にウィンドウを表示しません", "autoRun": "自動実行", "autoRunDesc": "アプリを開いたときに自動的に実行します", "logcat": "ログキャプチャ", "logcatDesc": "無効にするとログの入り口が非表示になります", "autoCheckUpdate": "更新の自動チェック", - "autoCheckUpdateDesc": "アプリ起動時に更新を自動的にチェックします", "checkCertificate": "TLS証明書を検証", "checkCertificateDesc": "信頼できない証明書を拒否します。無効にすると、サブスクリプションやバックアップが中間者攻撃にさらされます", "accessControl": "アクセス制御", "accessControlDesc": "プロキシを利用するアプリを設定します", - "application": "アプリケーション", - "applicationDesc": "アプリケーション関連の設定を変更します", "edit": "編集", "confirm": "OK", "update": "更新", @@ -103,12 +111,14 @@ "show": "表示", "exit": "終了", "systemProxy": "システムプロキシ", + "safeMode": "セーフモード", + "safeModeAppTitle": "{appName}(セーフモード)", "project": "プロジェクト", "core": "コア", "tabAnimation": "タブアニメーション", "desc": "ClashMetaベースのマルチプラットフォーム対応プロキシクライアント。シンプルで使いやすく、オープンソースで広告もありません。", - "startVpn": "VPNを起動しています...", - "stopVpn": "VPNを停止しています...", + "startVpn": "VPNを起動しています…", + "stopVpn": "VPNを停止しています…", "compatible": "互換モード", "notSelectedTip": "現在のプロキシグループは選択できません", "changeProxyFailedTip": "プロキシの切り替えに失敗したため、前回の選択に戻しました", @@ -137,28 +147,26 @@ "country": "地域", "search": "検索", "allowBypass": "アプリによるVPNバイパスを許可", - "allowBypassDesc": "有効にすると、一部のアプリがVPNをバイパスできます", "externalController": "外部コントローラー", "externalControllerDesc": "有効にすると、ポート9090でClashコアを制御できます", "ipv6Desc": "有効にすると、IPv6トラフィックを受信できます", "app": "アプリ", "general": "一般", - "systemProxyDesc": "システムプロキシを設定します", + "startupAndBackground": "起動とバックグラウンド", + "requestsAndUpdates": "リクエストと更新", + "logsAndDiagnostics": "ログと診断", "userAgent": "User-Agent", "unifiedDelay": "統一遅延", - "unifiedDelayDesc": "ハンドシェイクなどの余分な遅延を除きます", "tcpConcurrent": "TCP同時接続", - "tcpConcurrentDesc": "有効にすると、TCPの同時接続を許可します", "geodataLoader": "Geo低メモリモード", - "geodataLoaderDesc": "有効にすると、低メモリのGeoローダーを使用します", "requests": "リクエスト", - "requestsDesc": "最近のリクエスト記録を表示します", + "recentRequests": "最近のリクエスト", "findProcessMode": "プロセス検出", "init": "初期化", "infiniteTime": "無期限", "connections": "接続", + "liveConnections": "リアルタイム接続", "inbound": "インバウンド", - "connectionsDesc": "現在の接続データを表示します", "intranetIP": "イントラネットIP", "view": "表示", "cut": "切り取り", @@ -182,19 +190,18 @@ "go": "開く", "externalLink": "外部リンク", "otherContributors": "その他の貢献者", + "appIconDesign": "アプリアイコンのデザイン", "autoCloseConnections": "接続を自動的に閉じる", "autoCloseConnectionsDesc": "ノードの切り替え後、接続を自動的に閉じます", - "onlyStatisticsProxy": "プロキシのみ集計", - "onlyStatisticsProxyDesc": "有効にすると、プロキシのトラフィックのみを集計します", + "onlyStatisticsProxy": "プロキシトラフィックのみ集計", "showNotificationStopAction": "通知に停止ボタンを表示", - "showNotificationStopActionDesc": "常駐通知に停止ボタンを表示します。これが原因で通知が常に展開される場合はオフにしてください", "pureBlackMode": "ピュアブラックモード", + "sidebarBlur": "サイドバーのぼかし", + "sidebarBlurDesc": "ウィンドウ背後のデスクトップをぼかしてサイドバーに透過します", "keepAliveIntervalDesc": "TCPキープアライブ間隔", "entries": " 件", "local": "ローカル", "remote": "リモート", - "remoteBackupDesc": "WebDAVにデータをバックアップします", - "localBackupDesc": "ローカルにデータをバックアップします", "mode": "モード", "time": "時刻", "source": "ソース", @@ -209,69 +216,119 @@ "profilesSort": "プロファイルの並べ替え", "start": "開始", "stop": "停止", - "dnsDesc": "DNS関連の設定を更新します", "key": "キー", "value": "値", - "hostsDesc": "Hostsを追加します", "vpnTip": "変更はVPNの再起動後に有効になります", "vpnEnableDesc": "VpnServiceでシステムの全トラフィックを自動的にルーティングします", "options": "オプション", - "loopback": "ループバック解除ツール", - "loopbackDesc": "UWPのループバック解除に使用します", + "enabled": "有効", + "disabled": "無効", + "loopback": "UWP ループバック解除", "providers": "外部リソース", "proxyProviders": "プロキシプロバイダー", + "ruleProviders": "ルールプロバイダー", + "appProxyProviders": "アプリのプロキシプロバイダー", + "appRuleProviders": "アプリのルールプロバイダー", + "behavior": "動作", + "format": "形式", + "providerUrlTip": "リモートリソースのみ対応しています", "subscriptionInfo": "サブスクリプション情報", "overrideDns": "DNSを上書き", - "overrideDnsDesc": "有効にすると、プロファイル内のDNS設定を上書きします", + "overrideNtp": "NTPを上書き", + "ntpStatusDesc": "システムクロックではなくNTPサーバーから時刻を取得します", + "server": "サーバー", + "ntpInterval": "同期間隔(分)", + "dialerProxy": "ダイヤラープロキシ", + "dialerProxyDesc": "NTPサーバーへの接続に使用するアウトバウンド", + "writeToSystem": "システムに書き込む", + "writeToSystemDesc": "システムクロックも設定します。Androidでは無視されます", + "overrideEntries": "上書き項目", + "addOverrideEntry": "上書き項目を追加", + "discardChanges": "変更を破棄しますか?", + "quickEdit": "クイック編集", "status": "状態", "statusDesc": "無効にすると、システムDNSを使用します", - "preferH3Desc": "DoHでHTTP/3を優先します", "respectRules": "ルールに従う", - "respectRulesDesc": "DNS接続がルールに従います。proxy-server-nameserverの設定が必要です", + "respectRulesDesc": "DNS接続がルールに従います。Proxy Server Nameserverの設定が必要です", "dnsMode": "DNSモード", "fakeipRange": "Fake-IP範囲", "fakeipFilter": "Fake-IPフィルター", - "defaultNameserver": "デフォルトネームサーバー", - "defaultNameserverDesc": "DNSサーバーの名前解決に使用します", - "nameserver": "ネームサーバー", - "nameserverDesc": "ドメインの名前解決に使用します", "useHosts": "Hostsを使用", "useSystemHosts": "システムのHostsを使用", - "nameserverPolicy": "ネームサーバーポリシー", - "nameserverPolicyDesc": "ドメインごとのネームサーバーポリシーを指定します", - "proxyNameserver": "プロキシネームサーバー", - "proxyNameserverDesc": "プロキシノードのドメイン解決に使用します", - "fallback": "フォールバック", - "fallbackDesc": "通常は国外のDNSを使用します", "fallbackFilter": "フォールバックフィルター", - "geoipCode": "GeoIPコード", - "ipcidr": "IP/CIDR", "domain": "ドメイン", + "listenRoutingMark": "リッスンのルーティングマーク", + "listenRoutingMarkDesc": "Linuxのみ", + "ipv6Timeout": "IPv6タイムアウト(ms)", + "cacheAlgorithm": "キャッシュアルゴリズム", + "cacheMaxSize": "キャッシュサイズ", + "fakeipRange6": "Fake-IP範囲(IPv6)", + "fakeipFilterMode": "Fake-IPフィルターモード", + "fakeipFilterModeDesc": "blacklistは一致を除外、whitelistは一致のみ、ruleはルールで判定", + "fakeipTtl": "Fake-IP TTL", "reset": "リセット", "actionView": "表示/非表示", "actionStart": "開始/停止", "actionMode": "モード切替", "actionProxy": "システムプロキシ", "actionTun": "TUN", + "actionRuleMode": "ルールモード", + "actionGlobalMode": "グローバルモード", + "actionDirectMode": "ダイレクトモード", + "actionDelayTest": "すべての遅延をテスト", + "actionUpdateProfiles": "プロファイルを更新", "disclaimer": "免責事項", - "disclaimerDesc": "本ソフトウェアは、学習・交流や研究などの非商用目的でのみ使用できます。商用目的での使用は固く禁じられています。いかなる商業行為も本ソフトウェアとは一切関係ありません。", + "disclaimerDesc": "FlClash(以下「本ソフトウェア」)をご利用になる前に、本声明の内容をよくお読みになり、十分にご理解ください。「同意する」をタップすると、以下のすべての条項を読み、理解し、承諾したものとみなされます。同意いただけない場合は「終了」をタップし、本ソフトウェアの使用を中止してください。", + "disclaimerSoftwareTitle": "ソフトウェアの性質", + "disclaimerSoftwareContent": "本ソフトウェアは Clash.Meta(mihomo)コアをベースとしたオープンソースのネットワークプロキシクライアントであり、設定管理、ルールによる振り分け、トラフィック転送などのローカルツール機能のみを提供します。\n\n本ソフトウェア自体は、プロキシサーバー、ノード、サブスクリプション、ネットワーク接続サービスを一切提供しておらず、それらのサービス提供者と提携、代理、保証の関係はありません。", + "disclaimerUsageTitle": "使用の制限", + "disclaimerUsageContent": "本ソフトウェアは学習、交流、技術研究などの非商用目的でのみ使用できます。有償配布、抱き合わせ販売、商用サービスの一部としての利用、本ソフトウェアの名義での事業活動など、あらゆる商用目的での使用を固く禁じます。いかなる商業行為も本ソフトウェアおよび開発者とは一切関係ありません。\n\nお住まいの国または地域の法令に違反する目的での使用を固く禁じます。これには、法に基づくネットワークアクセス制限の回避、違法情報の拡散、サイバー攻撃、他者の権利の侵害などが含まれますが、これらに限りません。", + "disclaimerResponsibilityTitle": "利用者の責任", + "disclaimerResponsibilityContent": "お住まいの国または地域で本ソフトウェアの使用が合法であることはご自身で確認する必要があり、本ソフトウェアを使用したすべての行為とその結果について、ご自身が単独で法的責任を負います。\n\nインポートするサブスクリプション、ノード、設定はご自身の判断で選択したものです。その出所の適法性、内容の安全性、サービスの安定性については、利用者と各提供者の間で解決してください。", + "disclaimerThirdPartyTitle": "サードパーティのコンテンツ", + "disclaimerThirdPartyContent": "サブスクリプションリンク、設定ファイル、ルールセット、スクリプト、外部リソース、外部リンクはすべて第三者が提供するものであり、開発者はその適法性、正確性、安全性、可用性を審査または保証することはできず、また行いません。\n\nサードパーティのコンテンツの使用に起因する情報漏えい、財産上の損失、アカウント停止その他の損失は、利用者と第三者の間で解決するものとし、開発者は一切責任を負いません。", + "disclaimerWarrantyTitle": "無保証", + "disclaimerWarrantyContent": "本ソフトウェアは「現状のまま」かつ「提供可能な範囲で」提供され、商品性、特定目的への適合性、非侵害、継続的な可用性、エラーやセキュリティ上の脆弱性がないことの保証を含め、明示または黙示を問わずいかなる保証も伴いません。\n\n開発者は、本ソフトウェアが利用者の要件を満たすこと、また中断やエラーなく動作することを保証しません。", + "disclaimerLiabilityTitle": "責任の制限", + "disclaimerLiabilityContent": "適用法で認められる最大限の範囲において、開発者およびすべての貢献者は、本ソフトウェアの使用または使用不能に起因する直接的、間接的、偶発的、特別、懲罰的または結果的な損害(データの消失、機器の損傷、ネットワーク障害、業務の中断、逸失利益、およびそれに起因する法的紛争を含むがこれらに限らない)について、その可能性を知らされていた場合であっても、一切責任を負いません。", + "disclaimerPrivacyTitle": "データ収集とプライバシー", + "disclaimerPrivacyContent": "本ソフトウェアは、サブスクリプション URL、ノード情報、設定内容、閲覧したウェブサイト、接続記録、通信内容、ログを収集またはアップロードしません。これらのデータは端末内にのみ保存され、開発者がアクセスすることはできません。\n\n本ソフトウェアが外部ネットワークにアクセスするのは、プロファイル更新時に指定されたサブスクリプション URL へアクセスする場合や、アップデート確認時に GitHub へアクセスする場合など、該当する機能を使用したときのみです。\n\nデスクトップ版(Windows、macOS、Linux)には、統計やクラッシュレポートのサービスは一切組み込まれていません。Android 版には、安定性向上のため以下の 2 つの Google Firebase サービスが組み込まれています。", + "disclaimerCrashlyticsTitle": "Firebase Crashlytics(クラッシュ分析)", + "disclaimerCrashlyticsContent": "アプリがクラッシュした際に、クラッシュレポートを自動的に送信します。\n\n収集内容:クラッシュのスタックトレースとエラー情報、発生日時、アプリのバージョンとビルド番号、端末のメーカーとモデル、Android のバージョン、画面の向き、空きメモリと空きストレージ、root 化の有無、およびインストール時に生成され再インストールでリセットされるランダムなインストール ID。\n\n目的:クラッシュの特定と修正のためにのみ使用します。\n\n「ツール > 一般 > クラッシュ分析」からいつでもオフにできます。", + "disclaimerAnalyticsTitle": "Firebase Analytics(利用統計)", + "disclaimerAnalyticsContent": "Firebase により基本的なアプリ利用統計が自動的に収集されます。\n\n収集内容:初回起動、アプリの起動とセッション時間、アプリの更新などの基本イベント、アプリインスタンス ID、端末のモデル、OS のバージョン、システム言語、および IP アドレスから推定される国または地域レベルのおおよその位置情報。\n\n目的:アクティブな端末数、バージョン分布、OS の互換性を把握するためにのみ使用します。開発者はこれらのデータを広告に使用したり、販売したり、サブスクリプションや設定と関連付けたりすることはありません。", + "disclaimerDataProcessingContent": "これらのデータは Google が代わりに処理・保存し、お住まいの国または地域外(米国など)のサーバーに転送される場合があり、Google のプライバシーポリシーおよび Firebase のプライバシーとセキュリティに関する説明に従って取り扱われます。クラッシュレポートは最大 90 日間保存され、統計データは Firebase の既定の保存ポリシーに従って保存されます。", + "disclaimerLicenseTitle": "オープンソースライセンス", + "disclaimerLicenseContent": "本ソフトウェアは GPL-3.0 ライセンスのもとでオープンソースとして公開されています。同ライセンスを遵守する限り、自由に使用、改変、再配布できますが、派生物も GPL-3.0 で公開し、原著作者の著作権表示を保持する必要があります。\n\n本ソフトウェアに含まれるサードパーティのコンポーネント(Clash.Meta コアを含む)は、それぞれのライセンスに従います。改変版や再配布版に起因する問題について、原著作者は責任を負いません。", + "disclaimerChangesTitle": "本声明の変更", + "disclaimerChangesContent": "開発者はバージョンの更新に伴い本声明を変更することがあり、変更内容は新しいバージョンの公開とともに効力を生じます。更新後も本ソフトウェアを引き続き使用した場合、変更後の声明に同意したものとみなされます。", + "disclaimerAcceptTitle": "声明への同意", + "disclaimerAcceptContent": "本ソフトウェアをインストール、複製または使用した時点で、本声明のすべての内容を読み、同意したものとみなされます。いずれかの条項に同意いただけない場合は、直ちに使用を中止し、本ソフトウェアをアンインストールしてください。", + "disclaimerAndroidOnly": "Android のみ", + "disclaimerGooglePrivacy": "Google プライバシーポリシー", + "disclaimerFirebasePrivacy": "Firebase のプライバシーとセキュリティ", "agree": "同意する", "hotkeyManagement": "ホットキー管理", - "hotkeyManagementDesc": "キーボードでアプリを操作します", - "pressKeyboard": "キーを押してください", - "inputCorrectHotkey": "正しいホットキーを入力してください", - "hotkeyConflict": "ホットキーが競合しています", + "hotkeyDesc": "グローバルホットキーはウィンドウが非表示でも有効です。アクションをタップしてキーの組み合わせを記録します。", + "hotkeyNotSet": "未設定", + "pressKeyboard": "キーの組み合わせを押してください", + "hotkeyNeedsModifier": "{modifiers} のいずれかを含めてください", + "hotkeyConflictWith": "「{action}」で使用中です。保存するとこちらに移動します。", + "hotkeyUnavailable": "登録できませんでした。他のアプリが使用している可能性があります", "remove": "削除", - "noHotKey": "ホットキーはまだありません", "noNetwork": "ネットワークがありません", "ipv6InboundDesc": "IPv6インバウンドを許可します", "exportLogs": "ログをエクスポート", "exportSuccess": "エクスポートが完了しました", "iconStyle": "アイコンスタイル", - "onlyIcon": "アイコンのみ", + "iconStyleFilled": "背景あり", + "iconStylePlain": "背景なし", + "iconStyleHidden": "非表示", + "filter": "フィルター", + "hideTimeoutProxies": "タイムアウトしたノードを隠す", + "hideTimeoutProxiesDesc": "前回の遅延テストがタイムアウトしたノードを表示しない", "stackMode": "スタックモード", "network": "ネットワーク", - "networkDesc": "ネットワーク関連の設定を変更します", "bypassDomain": "除外ドメイン", "bypassDomainDesc": "システムプロキシが有効な場合のみ適用されます", "resetTip": "リセットしてもよろしいですか?", @@ -284,7 +341,6 @@ "routeModeBypassPrivate": "プライベートアドレスをバイパス", "routeModeConfig": "設定を使用", "routeAddress": "ルートアドレス", - "routeAddressDesc": "リッスンするルートアドレスを設定します", "interfaceNameMode": "アウトバウンドインターフェース", "interfaceNameModeClear": "クリア", "interfaceNameModeFollow": "設定に従う", @@ -293,6 +349,20 @@ "interfaceNameDesc": "アウトバウンド接続に使用するネットワークインターフェース名", "copyEnvVar": "環境変数をコピー", "memoryInfo": "メモリ情報", + "total": "合計", + "releaseMemory": "メモリを解放", + "memoryCoreHeapInuse": "使用中のヒープ", + "memoryCoreHeapIdle": "未使用のヒープ", + "memoryCoreStack": "ゴルーチンスタック", + "memoryCoreRuntime": "ランタイムのオーバーヘッド", + "memoryCoreNotRunning": "コアは実行されていません", + "memoryAppResident": "常駐メモリ", + "memoryAppShared": "アプリと共有", + "memoryEstimateDesc": "プロセスの常駐メモリからの推定値で、システムの表示とは異なる場合があります。", + "memoryEstimateSharedDesc": "コアはアプリと同じプロセスで動作します。コア分はランタイム統計から推定し、残りはアプリと共有メモリとして計上します。", + "memoryReleased": "メモリを解放しました", + "memoryReleasedSize": "{size} を解放しました", + "releaseMemoryFailed": "メモリの解放に失敗しました", "cancel": "キャンセル", "fileIsUpdate": "ファイルが変更されています。変更を保存しますか?", "profileHasUpdate": "プロファイルが変更されています。自動更新を無効にしますか?", @@ -305,27 +375,27 @@ "listen": "リッスン", "undo": "元に戻す", "redo": "やり直す", + "lineWrap": "折り返し", "none": "なし", - "basicConfig": "基本設定", - "basicConfigDesc": "基本設定をグローバルに変更します", "advancedConfig": "詳細設定", - "advancedConfigDesc": "多彩な設定項目を提供します", + "advancedConfigDesc": "ネットワーク、DNS、追加ルール、スクリプト", "selectedCountTitle": "{count} 件選択中", "addRule": "ルールを追加", "ruleName": "ルール名", "content": "内容", "subRule": "サブルール", "ruleTarget": "ルールターゲット", - "matchTargetTitle": "マッチ先", "matchTarget": "MATCH-TARGET", "followProfile": "プロファイルに従う", - "matchTargetDesc": "MATCH-TARGET を対象にしたルールの行き先。既定ではこのプロファイル末尾の MATCH ルールのターゲットを使います。", - "selectMatchTarget": "MATCH-TARGET を選択", "sourceIp": "送信元IP", "noResolve": "IPを解決しない", "saveChanges": "変更を保存しますか?", - "findProcessModeDesc": "有効にすると、パフォーマンスが多少低下します", - "tabAnimationDesc": "モバイル表示でのみ有効です", + "navigationBarStyle": "ボトムバー", + "floating": "フローティング", + "docked": "固定", + "slide": "スライド", + "fade": "フェード", + "pureBlack": "ピュアブラック", "colorSchemes": "カラースキーム", "palette": "パレット", "tonalSpotScheme": "トーナルスポット", @@ -348,6 +418,8 @@ "launchInterruptedTip": "前回、アプリは起動中に予期せず終了しました。今回の自動セットアップはスキップしました。手動で起動して再試行できます。", "clearData": "データを消去", "textScale": "テキストの拡大縮小", + "textScalePreview": "アプリ内の文字はこの大きさで表示されます", + "followSystem": "システムに従う", "internet": "インターネット", "systemApp": "システムアプリ", "noNetworkApp": "ネットワーク不使用アプリ", @@ -361,7 +433,13 @@ "interval": "間隔", "existsTip": "{label}はすでに存在します", "maxLengthTip": "{label}は最大{max}文字です", - "multipleValuesTip": "複数の値はカンマで区切ってください", + "singleAdd": "個別追加", + "batchAdd": "一括追加", + "batchListInputTip": "1行に1項目、またはカンマ区切りで入力してください", + "batchMapInputTip": "1行に1件、キーと値はスペースで区切ってください", + "batchPreviewTip": "{count}件を追加、{skipped}件は既存のためスキップ", + "lineIssueTip": "{line}行目:{message}", + "singleValueTip": "{label}は1項目のみ指定できます", "deleteTip": "この{label}を削除してもよろしいですか?", "deleteMultipTip": "選択した{label}を削除してもよろしいですか?", "nullTip": "{label}はまだありません", @@ -378,6 +456,7 @@ "import": "インポート", "importFile": "ファイルからインポート", "importUrl": "URLからインポート", + "startFromScratch": "最初から作成", "autoSetSystemDns": "システムDNSを自動設定", "details": "{label}の詳細", "creationTime": "作成日時", @@ -396,7 +475,7 @@ "request": "リクエスト", "connected": "接続済み", "disconnected": "切断済み", - "connecting": "接続中...", + "connecting": "接続中…", "restartCoreTip": "コアを再起動してもよろしいですか?", "forceRestartCoreTip": "コアを強制再起動してもよろしいですか?", "dnsHijacking": "DNSハイジャック", @@ -406,20 +485,25 @@ "crashlytics": "クラッシュ分析", "crashlyticsTip": "有効にすると、アプリのクラッシュ時に機密情報を含まないクラッシュログを自動的にアップロードします", "appendSystemDns": "システムDNSを追加", - "appendSystemDnsTip": "設定にシステムDNSを強制的に追加します", "editRule": "ルールを編集", "overrideMode": "上書きモード", "standardModeDesc": "標準モード:基本設定を上書きし、シンプルなルール追加機能を提供します", "scriptModeDesc": "スクリプトモード:外部の拡張スクリプトを使用し、ワンクリックで設定を上書きします", "addedRules": "追加ルール", "controlGlobalAddedRules": "グローバル追加ルールを管理", + "quickAdd": "クイック追加", + "rulePresetBlockQuic": "QUIC をブロック", + "rulePresetBlockStun": "STUN をブロック", + "rulePresetBlockDot": "DNS over TLS をブロック", + "rulePresetSystemServicesDirect": "Apple と Microsoft に直接接続", + "rulePresetBittorrentDirect": "BitTorrent を直接接続", + "rulePresetLanDirect": "LAN 直接接続", "overrideScript": "上書きスクリプト", "goToConfigureScript": "スクリプト設定へ移動", "editGlobalRules": "グローバルルールを編集", - "externalFetch": "外部取得", "confirmForceCrashCore": "コアを強制クラッシュさせてもよろしいですか?", "confirmClearAllData": "すべてのデータを消去してもよろしいですか?", - "loading": "読み込み中...", + "loading": "読み込み中…", "yearsAgo": "{count} 年前", "monthsAgo": "{count} か月前", "daysAgo": "{count} 日前", @@ -435,24 +519,31 @@ "speedStatistics": "速度統計", "resetPageChangesTip": "このページには変更があります。リセットしてもよろしいですか?", "overwriteTypeCustom": "カスタム", - "overwriteTypeCustomDesc": "カスタムモード:プロキシグループとルールを完全にカスタマイズできます", + "overwriteTypeCustomDesc": "カスタムモード:プロキシ、プロキシグループ、ルールを完全にカスタマイズできます", "unknownNetworkError": "不明なネットワークエラー", - "restoreException": "復元エラー", - "networkException": "ネットワークエラーです。接続を確認してから再試行してください", + "backupFromNewerVersion": "このバックアップは新しいバージョンのアプリで作成されています。アプリを更新してから復元してください", + "networkTimeoutError": "リクエストがタイムアウトしました。ネットワークまたはプロキシを確認してから再試行してください", + "networkHostLookupError": "サーバーのアドレスを解決できませんでした。URL が正しいこと、DNS が使えることを確認してください", + "networkConnectionError": "サーバーに接続できませんでした。ネットワーク接続またはプロキシ設定を確認してください", + "networkTlsError": "安全な接続に失敗しました。サーバー証明書が無効か、接続が傍受されている可能性があります", + "networkCancelledError": "リクエストはキャンセルされました", + "networkAccessDeniedError": "サーバーがアクセスを拒否しました(HTTP {code})。リンクの期限切れか、認証情報が誤っている可能性があります", + "networkNotFoundError": "このアドレスには何も見つかりませんでした(HTTP {code})。URL が正しいか確認してください", + "networkRateLimitedError": "リクエストが多すぎます(HTTP 429)。しばらく待ってから再試行してください", + "networkServerError": "サーバーで問題が発生しました(HTTP {code})。しばらくしてから再試行してください", + "networkBadResponseError": "サーバーがリクエストを拒否しました(HTTP {code})", + "networkRequestFailed": "ネットワークリクエストに失敗しました:{detail}", "invalidBackupFile": "無効なバックアップファイル", "pruneCache": "キャッシュを整理", "backupAndRestore": "バックアップと復元", "backupAndRestoreDesc": "WebDAVまたはファイルでデータを同期します", "restore": "復元", "restoreSuccess": "復元が完了しました", - "restoreFromWebDAVDesc": "WebDAVからデータを復元します", - "restoreFromFileDesc": "ファイルからデータを復元します", "restoreOnlyConfig": "プロファイルのみ復元", "restoreAllData": "すべてのデータを復元", "addProfile": "プロファイルを追加", "delayTest": "遅延テスト", "proxyGroupEmpty": "プロキシグループが空です", - "proxyGroupNameEmpty": "プロキシグループ名は空にできません", "proxyGroupNameDuplicate": "プロキシグループ名が重複しています", "confirmExitWindow": "現在のウィンドウを閉じてもよろしいですか?", "dataChangedSave": "データの変更を検出しました。保存しますか?", @@ -464,6 +555,8 @@ "excludeProxyFilter": "除外ノードフィルター", "excludeType": "除外タイプ", "expectedStatus": "期待するステータス", + "strategy": "戦略", + "tolerance": "許容値", "selectProxies": "プロキシを選択", "inputProxyGroupName": "プロキシグループ名を入力してください", "helperCorruptTip": "Helper サービスが利用できないため、TUN モードを有効にできません。FlClash を再インストールしてください。", @@ -488,7 +581,7 @@ "basicStrategy": "基本ポリシー", "editProxy": "プロキシを編集", "includeAllProxyProviders": "すべてのプロキシプロバイダーを含める", - "includeAllProxyProvidersTip": "有効にすると、取り込んだプロキシプロバイダーを上書きします", + "includeAllProxyProvidersTip": "有効にすると、このプロファイルのすべてのプロキシプロバイダーを含めます。サブスクリプション自身のものに加え、いずれかのプロキシグループが使うプロファイルとアプリのプロキシプロバイダーも含みます", "addProxyProviders": "プロキシプロバイダーを追加", "includeAllProxies": "すべてのプロキシを含める", "includeAllProxiesTip": "プロキシグループに属さないすべてのプロキシを取り込みます。下でプロキシグループを追加できます", @@ -550,17 +643,16 @@ "invalidSubRule": "{subRule} は無効な SUB_RULE です", "invalidPolicy": "{target} は無効なポリシーです", "invalidProxyProvider": "{providerName} は無効なプロキシプロバイダーです", + "invalidRuleSet": "{ruleSet} は無効なルールセットです", + "invalidNetworkContent": "tcp または udp のみ対応しています", + "invalidRangeContent": "80 や 8000-9000 のような数値または範囲を / 区切りで入力してください", + "invalidDscpContent": "DSCP マークは 63 を超えられません", "invalidProxy": "{proxyName} は無効なプロキシです", - "proxyGroupDetectedAbnormal": "現在のプロキシグループに異常が見つかりました", - "proxyProviderDetectedAbnormal": "選択したプロキシプロバイダーに異常が見つかりました", - "proxyDetectedAbnormal": "選択したプロキシに異常が見つかりました", - "createProfile": "プロファイルを作成", "locationPermissionRequired": "位置情報の権限が必要です", "locationPermissionGuide": "1. システム設定 > プライバシーとセキュリティ を開く\n2. 位置情報サービス を選択\n3. リストで {appName} を見つけてチェックを入れる\n\n設定が完了したらアプリに戻ると、通常どおり使用できます。ご協力ありがとうございます。", "prerequisites": "前提条件", "ignoreBatteryOptimization": "電池の最適化を無視", "batteryOptimizationDesc": "バックグラウンドでの動作を維持するため、このアプリの電池の最適化を無効にしてください。タップすると設定を開きます。", - "batteryOptimizationStatusTip": "システムの制限により、実行中は電池の最適化の状態を正しく取得できません", "locationPermission": "位置情報の権限", "locationPermissionDesc": "システムの要件により、Wi-Fi 名の取得には位置情報の権限が必要です。Android では「常に許可」を選択してください。そうしないと、アプリがバックグラウンドにあるときに Wi-Fi 名を取得できません。", "excludeSsids": "除外SSID", @@ -573,7 +665,7 @@ "editSsid": "SSIDを編集", "authorized": "許可済み", "tapToAuthorize": "タップして許可", - "suspended": "一時停止中...", + "suspended": "一時停止中…", "geoOptions": "Geoオプション", "geoAutoUpdate": "自動更新", "geoAutoUpdateInterval": "自動更新間隔", @@ -584,7 +676,6 @@ "geoSkipped": "{name} はすでに最新です", "geoUpdated": "{name} を更新しました", "secondsCount": "{count} 秒", - "entriesCount": "{count} 件", "proxiesCount": "プロキシ {count} 件", "rulesCount": "ルール {count} 件", "changelogBreaking": "破壊的変更", @@ -600,7 +691,6 @@ "pinWindow": "最前面に固定", "unpinWindow": "固定を解除", "exitFullScreen": "全画面表示を終了", - "toggleLabel": "ラベルを切り替え", "torch": "ライト", "pickFromAlbum": "アルバムから選択", "blockConnection": "接続をブロック", @@ -611,11 +701,76 @@ "previousMatch": "前の一致", "nextMatch": "次の一致", "clearSearch": "検索をクリア", + "noSearchResults": "一致する結果はありません", "addWidget": "ウィジェットを追加", "showPassword": "パスワードを表示", "hidePassword": "パスワードを隠す", "authorize": "許可", "installedAppsPermissionRequired": "アプリ一覧の権限が必要です", "installedAppsPermissionDesc": "このシステムでは、許可するまでインストール済みアプリの一覧が提供されません。許可すると、アプリごとのプロキシを設定できます。", - "installedAppsPermissionDeniedMessage": "アプリ一覧の権限が拒否されたため、インストール済みアプリを取得できません。システム設定から手動で許可してください。" + "installedAppsPermissionDeniedMessage": "アプリ一覧の権限が拒否されたため、インストール済みアプリを取得できません。システム設定から手動で許可してください。", + "outboundIp": "アウトバウンド IP", + "ipAddress": "IP アドレス", + "ipQualityLevel": "レベル", + "ipQualityGood": "良好", + "ipQualityNormal": "普通", + "ipQualityRisky": "リスクあり", + "ipType": "タイプ", + "ipTypeResidential": "住宅", + "ipTypeMobile": "モバイル回線", + "ipTypeBusiness": "ビジネス", + "ipTypeHosting": "データセンター", + "ipFlags": "検出", + "ipFlagProxy": "プロキシ", + "ipFlagVpn": "VPN", + "ipFlagTor": "Tor", + "ipFlagAbuser": "不正利用の履歴", + "ipOrganization": "組織", + "ipAsn": "ASN", + "ipQualitySource": "採用したソース", + "ipQualitySources": "各ソース", + "ipQualityFailed": "IP タイプを判定できませんでした", + "ipQualityRetry": "再確認", + "ipSourceNoType": "判定不可", + "ipSourceRateLimited": "レート制限", + "ipSourceIpMismatch": "アウトバウンド IP が不一致", + "hideIp": "IP を隠す", + "editorUnavailable": "エディターを利用できません", + "replace": "置換", + "replaceAll": "すべて置換", + "cameraPermissionRequired": "カメラの権限が必要です", + "cameraPermissionDesc": "QRコードをスキャンするには、システム設定でカメラへのアクセスを許可するか、アルバムからQRコード画像を選択してください。", + "cameraUnavailable": "カメラを使用できません", + "retry": "再試行", + "invalidProfileQrcode": "このQRコードにはプロファイルのリンクが含まれていません", + "dnsQueries": "DNSクエリ", + "recordType": "レコードタイプ", + "answers": "応答", + "responseCode": "応答コード", + "error": "エラー", + "initiator": "発信元", + "cache": "キャッシュ", + "proxyNode": "プロキシノード", + "yes": "はい", + "no": "いいえ", + "nonTextProviderFile": "この外部リソースはテキストファイルではありません", + "addCustomProxy": "プロキシを追加", + "proxyDefinition": "完全な設定", + "proxyDefinitionNotMap": "設定は name と type を含む YAML マッピングである必要があります", + "customProxiesEmpty": "カスタムプロキシがないため、プロファイル自身のプロキシを使用します", + "overwriteIssueEmptyName": "名前が空です", + "overwriteIssueReservedName": "{name} は組み込みポリシー名のため使用できません", + "overwriteIssueDuplicateName": "名前 {name} は他のプロキシまたはプロキシグループで使用されています", + "overwriteIssueCoreRejected": "コアがこのプロキシを解析できません:{message}", + "overwriteIssueMissingProxies": "次のプロキシまたはポリシーは存在しません:{names}", + "overwriteIssueMissingProviders": "次のプロキシプロバイダーは存在しません:{names}", + "overwriteIssueNoProxySource": "プロキシもプロキシプロバイダーも選択されていないため、コアはこのグループを拒否します", + "overwriteIssueGroupLoop": "プロキシグループが循環参照しています:{path}", + "overwriteIssuesSummary": "{count} 件に問題があり、上書きの適用に失敗する可能性があります", + "overwriteIssueSubscriptionGroupMissingProxies": "プロファイル自身のプロキシグループが、カスタムプロキシに含まれないプロキシを参照しています:{names}", + "overwriteIssueProviderShadowed": "プロファイルに {name} という名前のプロバイダーが既にあるため、同名のアプリレベルのプロバイダーは使用されません。名前を変更してください", + "providerInUse": "{label} は {profiles} のカスタムプロキシグループまたはルールでまだ使用されています。先にそこから外してください", + "providerSourceSubscription": "サブスクリプション", + "providerRenameShadowed": "{profiles} のサブスクリプションには既に {label} があるため、名前を変えるとそちらが使われます。別の名前にしてください", + "appProviderShadowed": "同名のアプリ側の項目はここでは使われません" } diff --git a/arb/intl_ru.arb b/arb/intl_ru.arb index 9eab3a00..2f15ec02 100644 --- a/arb/intl_ru.arb +++ b/arb/intl_ru.arb @@ -9,19 +9,32 @@ "profiles": "Профили", "tools": "Инструменты", "logs": "Логи", - "logsDesc": "Записи захваченных логов", "resources": "Ресурсы", - "resourcesDesc": "Сведения о внешних ресурсах", "trafficUsage": "Статистика трафика", "networkSpeed": "Скорость сети", "outboundMode": "Режим исходящего трафика", "networkDetection": "Проверка сети", + "serviceStatus": "Состояние сервисов", + "serviceRestricted": "Доступ ограничен", + "serviceAvailable": "Доступен", + "serviceUnavailable": "Недоступен", + "serviceFailed": "Ошибка проверки", + "serviceDisallowedIsp": "Недопустимый провайдер", + "serviceBlocked": "Заблокировано", + "serviceUnsupportedRegion": "Регион не поддерживается", + "serviceOriginalsOnly": "Только оригиналы", + "serviceComingSoon": "Скоро появится", + "servicePending": "Не проверено", + "serviceManage": "Управление сервисами", + "serviceCheck": "Проверить", + "serviceCheckAll": "Проверить все", + "serviceCheckedAt": "Проверено в {time}", "upload": "Отдача", "download": "Загрузка", "usedTraffic": "Использованный трафик", "totalTraffic": "Общий трафик", "expireTime": "Срок действия", - "nullProfileDesc": "Профилей пока нет. Сначала добавьте профиль", + "nullProfileDesc": "Добавьте профиль, чтобы начать", "settings": "Настройки", "language": "Язык", "defaultText": "По умолчанию", @@ -36,27 +49,22 @@ "themeDesc": "Тёмный режим и настройка цветов", "override": "Переопределение", "allowLan": "Разрешить LAN", - "allowLanDesc": "Разрешить доступ к прокси из локальной сети", "tun": "TUN", "tunDesc": "Работает только в режиме администратора", "minimizeOnExit": "Сворачивать при выходе", - "minimizeOnExitDesc": "Изменяет стандартное поведение при выходе", "autoLaunch": "Автозапуск", "autoLaunchDesc": "Запускаться автоматически при старте системы", "silentLaunch": "Тихий запуск", - "silentLaunchDesc": "Запускаться в фоновом режиме", + "silentLaunchDesc": "Запускаться без показа окна", "autoRun": "Автовключение", "autoRunDesc": "Включаться автоматически при открытии приложения", "logcat": "Захват логов", "logcatDesc": "При отключении раздел логов будет скрыт", "autoCheckUpdate": "Автопроверка обновлений", - "autoCheckUpdateDesc": "Автоматически проверять обновления при запуске приложения", "checkCertificate": "Проверять TLS-сертификаты", "checkCertificateDesc": "Отклонять недоверенные сертификаты. Отключение подвергает подписки и резервные копии атаке «человек посередине»", "accessControl": "Контроль доступа", "accessControlDesc": "Выбор приложений, использующих прокси", - "application": "Приложение", - "applicationDesc": "Настройки, связанные с приложением", "edit": "Редактировать", "confirm": "Подтвердить", "update": "Обновить", @@ -103,12 +111,14 @@ "show": "Показать", "exit": "Выход", "systemProxy": "Системный прокси", + "safeMode": "Безопасный режим", + "safeModeAppTitle": "{appName} (Безопасный режим)", "project": "Проект", "core": "Ядро", "tabAnimation": "Анимация вкладок", "desc": "Многоплатформенный прокси-клиент на основе ClashMeta: простой и удобный, с открытым исходным кодом и без рекламы.", - "startVpn": "Запуск VPN...", - "stopVpn": "Остановка VPN...", + "startVpn": "Запуск VPN…", + "stopVpn": "Остановка VPN…", "compatible": "Режим совместимости", "notSelectedTip": "Текущую группу прокси нельзя выбрать", "changeProxyFailedTip": "Не удалось переключить прокси; восстановлен предыдущий выбор", @@ -137,28 +147,26 @@ "country": "Регион", "search": "Поиск", "allowBypass": "Разрешить приложениям обходить VPN", - "allowBypassDesc": "При включении некоторые приложения смогут обходить VPN", "externalController": "Внешний контроллер", "externalControllerDesc": "При включении ядром Clash можно управлять через порт 9090", "ipv6Desc": "При включении можно принимать трафик IPv6", "app": "Приложение", "general": "Общие", - "systemProxyDesc": "Настроить системный прокси", + "startupAndBackground": "Запуск и фоновая работа", + "requestsAndUpdates": "Запросы и обновления", + "logsAndDiagnostics": "Логи и диагностика", "userAgent": "User-Agent", "unifiedDelay": "Единая задержка", - "unifiedDelayDesc": "Убирает лишние задержки, например рукопожатие", "tcpConcurrent": "Параллельный TCP", - "tcpConcurrentDesc": "При включении разрешает параллельные TCP-подключения", "geodataLoader": "Geo: экономия памяти", - "geodataLoaderDesc": "При включении используется Geo-загрузчик с низким потреблением памяти", "requests": "Запросы", - "requestsDesc": "Просмотр последних запросов", + "recentRequests": "Последние запросы", "findProcessMode": "Поиск процесса", "init": "Инициализация", "infiniteTime": "Бессрочно", "connections": "Соединения", + "liveConnections": "Активные соединения", "inbound": "Входящие", - "connectionsDesc": "Просмотр данных о текущих соединениях", "intranetIP": "Внутренний IP", "view": "Просмотр", "cut": "Вырезать", @@ -182,19 +190,18 @@ "go": "Перейти", "externalLink": "Внешняя ссылка", "otherContributors": "Другие участники", + "appIconDesign": "Дизайн значка приложения", "autoCloseConnections": "Автозакрытие соединений", "autoCloseConnectionsDesc": "Автоматически закрывать соединения после смены узла", - "onlyStatisticsProxy": "Учитывать только прокси", - "onlyStatisticsProxyDesc": "При включении учитывается только трафик через прокси", + "onlyStatisticsProxy": "Учитывать только трафик прокси", "showNotificationStopAction": "Кнопка остановки в уведомлении", - "showNotificationStopActionDesc": "Показывать кнопку остановки в постоянном уведомлении. Отключите, если из-за неё система всегда разворачивает уведомление", "pureBlackMode": "Чисто чёрный режим", + "sidebarBlur": "Размытие боковой панели", + "sidebarBlurDesc": "Показывать сквозь боковую панель размытый рабочий стол за окном", "keepAliveIntervalDesc": "Интервал TCP keep-alive", "entries": " записей", "local": "Локально", "remote": "Удалённо", - "remoteBackupDesc": "Резервное копирование данных в WebDAV", - "localBackupDesc": "Резервное копирование данных локально", "mode": "Режим", "time": "Время", "source": "Источник", @@ -209,69 +216,119 @@ "profilesSort": "Сортировка профилей", "start": "Старт", "stop": "Стоп", - "dnsDesc": "Настройки, связанные с DNS", "key": "Ключ", "value": "Значение", - "hostsDesc": "Добавить записи hosts", "vpnTip": "Изменения вступят в силу после перезапуска VPN", "vpnEnableDesc": "Автоматически направляет весь системный трафик через VpnService", "options": "Опции", - "loopback": "Инструмент разблокировки loopback", - "loopbackDesc": "Для снятия ограничения loopback у UWP-приложений", + "enabled": "Включено", + "disabled": "Выключено", + "loopback": "Снятие ограничения loopback для UWP", "providers": "Внешние ресурсы", "proxyProviders": "Провайдеры прокси", + "ruleProviders": "Провайдеры правил", + "appProxyProviders": "Прокси-провайдеры приложения", + "appRuleProviders": "Провайдеры правил приложения", + "behavior": "Поведение", + "format": "Формат", + "providerUrlTip": "Поддерживаются только удалённые ресурсы", "subscriptionInfo": "Информация о подписке", "overrideDns": "Переопределить DNS", - "overrideDnsDesc": "При включении настройки DNS профиля переопределяются", + "overrideNtp": "Переопределить NTP", + "ntpStatusDesc": "Брать время с NTP-сервера, а не из системных часов", + "server": "Сервер", + "ntpInterval": "Интервал синхронизации (минуты)", + "dialerProxy": "Прокси для подключения", + "dialerProxyDesc": "Исход, через который идёт обращение к NTP-серверу", + "writeToSystem": "Записывать в систему", + "writeToSystemDesc": "Также устанавливать системные часы; Android это игнорирует", + "overrideEntries": "Переопределяемые параметры", + "addOverrideEntry": "Добавить параметр", + "discardChanges": "Отменить изменения?", + "quickEdit": "Быстрое редактирование", "status": "Статус", "statusDesc": "При отключении используется системный DNS", - "preferH3Desc": "Предпочитать HTTP/3 для DoH", "respectRules": "Соблюдать правила", - "respectRulesDesc": "DNS-соединения следуют правилам; требуется настроить proxy-server-nameserver", + "respectRulesDesc": "DNS-соединения следуют правилам; требуется Proxy Server Nameserver", "dnsMode": "Режим DNS", "fakeipRange": "Диапазон Fake-IP", "fakeipFilter": "Фильтр Fake-IP", - "defaultNameserver": "DNS-сервер по умолчанию", - "defaultNameserverDesc": "Используется для разрешения адресов DNS-серверов", - "nameserver": "DNS-сервер", - "nameserverDesc": "Используется для разрешения доменов", "useHosts": "Использовать hosts", "useSystemHosts": "Использовать системный hosts", - "nameserverPolicy": "Политика DNS-серверов", - "nameserverPolicyDesc": "Задать политику DNS-серверов для доменов", - "proxyNameserver": "DNS-сервер для прокси", - "proxyNameserverDesc": "Используется для разрешения доменов прокси-узлов", - "fallback": "Fallback", - "fallbackDesc": "Обычно зарубежный DNS", "fallbackFilter": "Фильтр fallback", - "geoipCode": "Код GeoIP", - "ipcidr": "IP/CIDR", "domain": "Домен", + "listenRoutingMark": "Метка маршрутизации", + "listenRoutingMarkDesc": "Только Linux", + "ipv6Timeout": "Тайм-аут IPv6 (мс)", + "cacheAlgorithm": "Алгоритм кэша", + "cacheMaxSize": "Размер кэша", + "fakeipRange6": "Диапазон Fake-IP (IPv6)", + "fakeipFilterMode": "Режим фильтра Fake-IP", + "fakeipFilterModeDesc": "blacklist исключает совпадения, whitelist — только их, rule — по правилам", + "fakeipTtl": "TTL Fake-IP", "reset": "Сброс", "actionView": "Показать/Скрыть", "actionStart": "Старт/Стоп", "actionMode": "Переключить режим", "actionProxy": "Системный прокси", "actionTun": "TUN", + "actionRuleMode": "Режим правил", + "actionGlobalMode": "Глобальный режим", + "actionDirectMode": "Прямой режим", + "actionDelayTest": "Проверить все задержки", + "actionUpdateProfiles": "Обновить профили", "disclaimer": "Отказ от ответственности", - "disclaimerDesc": "Это программное обеспечение предназначено только для некоммерческого использования: обучения, обмена опытом и научных исследований. Коммерческое использование строго запрещено; любая коммерческая деятельность не имеет отношения к этому программному обеспечению.", + "disclaimerDesc": "Перед использованием FlClash (далее — «Программа») внимательно прочитайте это заявление и убедитесь, что понимаете его полностью. Нажимая «Согласен», вы подтверждаете, что прочитали, поняли и принимаете все приведённые ниже условия. Если вы не согласны, нажмите «Выход» и прекратите использование Программы.", + "disclaimerSoftwareTitle": "Характер программы", + "disclaimerSoftwareContent": "Программа — это клиент сетевого прокси с открытым исходным кодом на основе ядра Clash.Meta (mihomo). Она предоставляет только локальные инструменты: управление конфигурациями, маршрутизацию по правилам и пересылку трафика.\n\nСама Программа не предоставляет прокси-серверы, узлы, подписки или услуги доступа к сети и не состоит в партнёрских, агентских или гарантийных отношениях с поставщиками таких услуг.", + "disclaimerUsageTitle": "Ограничения использования", + "disclaimerUsageContent": "Программа предназначена только для некоммерческого использования: обучения, обмена опытом и технических исследований. Любое коммерческое использование строго запрещено, включая, помимо прочего, платное распространение, продажу в комплекте, использование в составе коммерческого сервиса или ведение деятельности от имени Программы. Любая коммерческая деятельность не имеет отношения к Программе и её разработчикам.\n\nСтрого запрещено использовать Программу для действий, нарушающих законы вашей страны или региона, включая, помимо прочего, обход законно установленных ограничений доступа к сети, распространение незаконной информации, сетевые атаки и нарушение законных прав других лиц.", + "disclaimerResponsibilityTitle": "Ваша ответственность", + "disclaimerResponsibilityContent": "Вы самостоятельно убеждаетесь, что использование Программы законно в вашей стране или регионе, и единолично несёте юридическую ответственность за все действия с ней и их последствия.\n\nПодписки, узлы и конфигурации, которые вы импортируете, выбираете вы сами. Законность их источника, безопасность содержимого и надёжность сервиса — вопрос между вами и их поставщиками.", + "disclaimerThirdPartyTitle": "Сторонний контент", + "disclaimerThirdPartyContent": "Ссылки на подписки, файлы конфигурации, наборы правил, скрипты, внешние ресурсы и внешние ссылки предоставляются третьими лицами. Разработчики не могут проверять и не проверяют их законность, точность, безопасность и доступность и не дают на них никаких гарантий.\n\nУтечка данных, финансовые потери, блокировка аккаунта или иной ущерб, вызванные сторонним контентом, урегулируются между вами и третьим лицом; разработчики не несут за это никакой ответственности.", + "disclaimerWarrantyTitle": "Отсутствие гарантий", + "disclaimerWarrantyContent": "Программа предоставляется «как есть» и «по мере доступности», без каких-либо явных или подразумеваемых гарантий, включая, помимо прочего, гарантии товарной пригодности, пригодности для определённой цели, ненарушения прав, бесперебойной работы, отсутствия ошибок и уязвимостей.\n\nРазработчики не гарантируют, что Программа будет соответствовать вашим потребностям или работать без сбоев и ошибок.", + "disclaimerLiabilityTitle": "Ограничение ответственности", + "disclaimerLiabilityContent": "В максимальной степени, допустимой применимым законодательством, ни разработчики, ни участники проекта не несут ответственности за любой прямой, косвенный, случайный, особый, штрафной или последующий ущерб, возникший в результате использования или невозможности использования Программы, включая, помимо прочего, потерю данных, повреждение устройства, сбои сети, прерывание деятельности, упущенную выгоду или связанные с этим правовые споры, даже если они были предупреждены о возможности такого ущерба.", + "disclaimerPrivacyTitle": "Сбор данных и конфиденциальность", + "disclaimerPrivacyContent": "Программа не собирает и не отправляет адреса ваших подписок, сведения об узлах, содержимое конфигураций, посещённые сайты, записи о подключениях, содержимое трафика и журналы. Эти данные хранятся только на вашем устройстве, и у разработчиков нет к ним доступа.\n\nПрограмма обращается к сети только при использовании соответствующих функций, например загружает указанный вами адрес подписки при обновлении профиля или обращается к GitHub при проверке обновлений.\n\nНастольные версии (Windows, macOS, Linux) не содержат никаких сервисов статистики или отчётов о сбоях. Версия для Android использует два сервиса Google Firebase для повышения стабильности:", + "disclaimerCrashlyticsTitle": "Firebase Crashlytics (аналитика сбоев)", + "disclaimerCrashlyticsContent": "При сбое приложения отчёт о сбое отправляется автоматически.\n\nЧто собирается: трассировка стека и сообщение об ошибке, время сбоя, версия и номер сборки приложения, производитель и модель устройства, версия Android, ориентация экрана, свободная память и место в хранилище, наличие root-доступа, а также случайный идентификатор установки, который создаётся при установке и сбрасывается при переустановке.\n\nЦель: только поиск и исправление сбоев.\n\nВы можете отключить это в любой момент: «Инструменты > Общие > Аналитика сбоев».", + "disclaimerAnalyticsTitle": "Firebase Analytics (статистика использования)", + "disclaimerAnalyticsContent": "Вместе с Firebase автоматически собирается базовая статистика использования приложения.\n\nЧто собирается: базовые события, такие как первый запуск, открытие приложения и длительность сеанса, обновление приложения; идентификатор экземпляра приложения; модель устройства, версия ОС и язык системы; приблизительное местоположение на уровне страны или региона, определённое по IP-адресу.\n\nЦель: только оценка числа активных устройств, распределения версий и совместимости с ОС. Разработчики не используют эти данные для рекламы, не продают их и не связывают с вашими подписками или конфигурациями.", + "disclaimerDataProcessingContent": "Эти данные обрабатываются и хранятся компанией Google от нашего имени, могут передаваться на серверы за пределами вашей страны или региона (например, в США) и регулируются Политикой конфиденциальности Google и документацией Firebase о конфиденциальности и безопасности. Отчёты о сбоях хранятся до 90 дней; статистика хранится в соответствии с политикой хранения Firebase по умолчанию.", + "disclaimerLicenseTitle": "Лицензия с открытым исходным кодом", + "disclaimerLicenseContent": "Программа распространяется с открытым исходным кодом по лицензии GPL-3.0. Вы можете свободно использовать, изменять и распространять её при соблюдении этой лицензии: производные работы также должны распространяться по GPL-3.0 с сохранением уведомлений об авторских правах.\n\nСторонние компоненты Программы, включая ядро Clash.Meta, распространяются по своим собственным лицензиям. Авторы оригинала не несут ответственности за проблемы, возникшие в изменённых или распространяемых третьими лицами версиях.", + "disclaimerChangesTitle": "Изменения заявления", + "disclaimerChangesContent": "Разработчики могут изменять это заявление в любом выпуске; изменения вступают в силу с момента публикации выпуска. Продолжая пользоваться Программой после обновления, вы принимаете изменённое заявление.", + "disclaimerAcceptTitle": "Принятие условий", + "disclaimerAcceptContent": "Устанавливая, копируя или используя Программу, вы подтверждаете, что прочитали и приняли это заявление полностью. Если вы не согласны с каким-либо его условием, немедленно прекратите использование и удалите Программу.", + "disclaimerAndroidOnly": "Только Android", + "disclaimerGooglePrivacy": "Политика конфиденциальности Google", + "disclaimerFirebasePrivacy": "Конфиденциальность и безопасность Firebase", "agree": "Согласен", "hotkeyManagement": "Горячие клавиши", - "hotkeyManagementDesc": "Управление приложением с клавиатуры", - "pressKeyboard": "Нажмите клавишу", - "inputCorrectHotkey": "Введите корректную горячую клавишу", - "hotkeyConflict": "Конфликт горячих клавиш", + "hotkeyDesc": "Глобальные горячие клавиши работают, даже когда окно скрыто. Нажмите на действие, чтобы записать сочетание клавиш.", + "hotkeyNotSet": "Не задано", + "pressKeyboard": "Нажмите сочетание клавиш", + "hotkeyNeedsModifier": "Добавьте хотя бы одну из клавиш: {modifiers}", + "hotkeyConflictWith": "Уже используется для «{action}». При сохранении будет перенесено сюда.", + "hotkeyUnavailable": "Не зарегистрировано: сочетание может быть занято другим приложением", "remove": "Убрать", - "noHotKey": "Горячих клавиш пока нет", "noNetwork": "Нет сети", "ipv6InboundDesc": "Разрешить входящий IPv6", "exportLogs": "Экспорт логов", "exportSuccess": "Экспорт выполнен", "iconStyle": "Стиль значков", - "onlyIcon": "Только значок", + "iconStyleFilled": "С подложкой", + "iconStylePlain": "Без подложки", + "iconStyleHidden": "Скрыто", + "filter": "Фильтр", + "hideTimeoutProxies": "Скрывать узлы с таймаутом", + "hideTimeoutProxiesDesc": "Не показывать узлы, у которых последний тест задержки завершился таймаутом", "stackMode": "Режим стека", "network": "Сеть", - "networkDesc": "Настройки, связанные с сетью", "bypassDomain": "Исключённые домены", "bypassDomainDesc": "Действует только при включённом системном прокси", "resetTip": "Вы уверены, что хотите выполнить сброс?", @@ -284,7 +341,6 @@ "routeModeBypassPrivate": "Обходить частные адреса", "routeModeConfig": "Использовать конфигурацию", "routeAddress": "Адреса маршрутов", - "routeAddressDesc": "Настроить прослушиваемые адреса маршрутов", "interfaceNameMode": "Исходящий интерфейс", "interfaceNameModeClear": "Очистить", "interfaceNameModeFollow": "Как в конфигурации", @@ -293,6 +349,20 @@ "interfaceNameDesc": "Сетевой интерфейс для исходящих соединений", "copyEnvVar": "Копировать переменные окружения", "memoryInfo": "Память", + "total": "Всего", + "releaseMemory": "Освободить память", + "memoryCoreHeapInuse": "Используемая куча", + "memoryCoreHeapIdle": "Свободная куча", + "memoryCoreStack": "Стеки горутин", + "memoryCoreRuntime": "Накладные расходы среды", + "memoryCoreNotRunning": "Ядро не запущено", + "memoryAppResident": "Резидентная память", + "memoryAppShared": "Приложение и общая", + "memoryEstimateDesc": "Оценка по резидентной памяти процессов; может отличаться от данных системы.", + "memoryEstimateSharedDesc": "Ядро работает в процессе приложения. Его доля оценивается по статистике среды выполнения, остальное относится к приложению и общей памяти.", + "memoryReleased": "Память освобождена", + "memoryReleasedSize": "Освобождено {size}", + "releaseMemoryFailed": "Не удалось освободить память", "cancel": "Отмена", "fileIsUpdate": "Файл изменён. Сохранить изменения?", "profileHasUpdate": "Профиль изменён. Отключить автообновление?", @@ -305,27 +375,27 @@ "listen": "Прослушивание", "undo": "Отменить", "redo": "Повторить", + "lineWrap": "Перенос строк", "none": "Нет", - "basicConfig": "Базовая конфигурация", - "basicConfigDesc": "Глобальное изменение базовой конфигурации", "advancedConfig": "Расширенная конфигурация", - "advancedConfigDesc": "Разнообразные параметры конфигурации", + "advancedConfigDesc": "Сеть, DNS, добавленные правила и скрипты", "selectedCountTitle": "Выбрано: {count}", "addRule": "Добавить правило", "ruleName": "Название правила", "content": "Содержимое", "subRule": "Подправило", "ruleTarget": "Цель правила", - "matchTargetTitle": "Цель MATCH", "matchTarget": "MATCH-TARGET", "followProfile": "Как в профиле", - "matchTargetDesc": "Куда направляются правила с целью MATCH-TARGET. По умолчанию — цель последнего правила MATCH этого профиля.", - "selectMatchTarget": "Выбрать MATCH-TARGET", "sourceIp": "IP источника", "noResolve": "Не разрешать IP", "saveChanges": "Сохранить изменения?", - "findProcessModeDesc": "При включении возможна небольшая потеря производительности", - "tabAnimationDesc": "Действует только в мобильном виде", + "navigationBarStyle": "Нижняя панель", + "floating": "Плавающая", + "docked": "Закреплённая", + "slide": "Сдвиг", + "fade": "Растворение", + "pureBlack": "Чисто чёрный", "colorSchemes": "Цветовые схемы", "palette": "Палитра", "tonalSpotScheme": "Тональный акцент", @@ -348,6 +418,8 @@ "launchInterruptedTip": "В прошлый раз приложение неожиданно завершилось во время запуска. Автоматическая настройка для этого запуска пропущена; вы можете запустить её вручную.", "clearData": "Очистить данные", "textScale": "Масштаб текста", + "textScalePreview": "Так будет выглядеть текст в приложении", + "followSystem": "Как в системе", "internet": "Интернет", "systemApp": "Системные приложения", "noNetworkApp": "Приложения без сети", @@ -361,7 +433,13 @@ "interval": "Интервал", "existsTip": "«{label}» уже существует", "maxLengthTip": "«{label}» — не более {max} символов", - "multipleValuesTip": "Разделяйте несколько значений запятыми", + "singleAdd": "По одному", + "batchAdd": "Массовое добавление", + "batchListInputTip": "По одному значению на строку или через запятую", + "batchMapInputTip": "По одной записи на строку: ключ, пробел, значение", + "batchPreviewTip": "Будет добавлено: {count}, пропущено (уже есть): {skipped}", + "lineIssueTip": "Строка {line}: {message}", + "singleValueTip": "«{label}» — только одно значение", "deleteTip": "Вы уверены, что хотите удалить «{label}»?", "deleteMultipTip": "Вы уверены, что хотите удалить выбранные элементы ({label})?", "nullTip": "Пока нет: {label}", @@ -378,6 +456,7 @@ "import": "Импорт", "importFile": "Импорт из файла", "importUrl": "Импорт по URL", + "startFromScratch": "С нуля", "autoSetSystemDns": "Автонастройка системного DNS", "details": "Сведения: {label}", "creationTime": "Время создания", @@ -396,7 +475,7 @@ "request": "Запрос", "connected": "Подключено", "disconnected": "Отключено", - "connecting": "Подключение...", + "connecting": "Подключение…", "restartCoreTip": "Вы уверены, что хотите перезапустить ядро?", "forceRestartCoreTip": "Вы уверены, что хотите принудительно перезапустить ядро?", "dnsHijacking": "Перехват DNS", @@ -406,20 +485,25 @@ "crashlytics": "Аналитика сбоев", "crashlyticsTip": "При включении в случае сбоя приложения автоматически загружаются логи сбоя без конфиденциальной информации", "appendSystemDns": "Добавлять системный DNS", - "appendSystemDnsTip": "Принудительно добавлять системный DNS в конфигурацию", "editRule": "Редактировать правило", "overrideMode": "Режим переопределения", "standardModeDesc": "Стандартный режим: переопределяет базовую конфигурацию и позволяет просто добавлять правила", "scriptModeDesc": "Режим скрипта: использует внешние скрипты-расширения для переопределения конфигурации в один клик", "addedRules": "Добавленные правила", "controlGlobalAddedRules": "Управление глобальными добавленными правилами", + "quickAdd": "Быстрое добавление", + "rulePresetBlockQuic": "Блокировать QUIC", + "rulePresetBlockStun": "Блокировать STUN", + "rulePresetBlockDot": "Блокировать DNS over TLS", + "rulePresetSystemServicesDirect": "Apple и Microsoft напрямую", + "rulePresetBittorrentDirect": "BitTorrent напрямую", + "rulePresetLanDirect": "Локальная сеть напрямую", "overrideScript": "Скрипт переопределения", "goToConfigureScript": "Перейти к настройке скрипта", "editGlobalRules": "Редактировать глобальные правила", - "externalFetch": "Внешнее получение", "confirmForceCrashCore": "Вы уверены, что хотите принудительно завершить ядро со сбоем?", "confirmClearAllData": "Вы уверены, что хотите удалить все данные?", - "loading": "Загрузка...", + "loading": "Загрузка…", "yearsAgo": "{count, plural, one{{count} год назад} few{{count} года назад} many{{count} лет назад} other{{count} года назад}}", "monthsAgo": "{count, plural, one{{count} месяц назад} few{{count} месяца назад} many{{count} месяцев назад} other{{count} месяца назад}}", "daysAgo": "{count, plural, one{{count} день назад} few{{count} дня назад} many{{count} дней назад} other{{count} дня назад}}", @@ -435,24 +519,31 @@ "speedStatistics": "Статистика скорости", "resetPageChangesTip": "На этой странице есть изменения. Вы уверены, что хотите выполнить сброс?", "overwriteTypeCustom": "Пользовательский", - "overwriteTypeCustomDesc": "Пользовательский режим: полная настройка групп прокси и правил", + "overwriteTypeCustomDesc": "Пользовательский режим: полная настройка прокси, групп прокси и правил", "unknownNetworkError": "Неизвестная сетевая ошибка", - "restoreException": "Ошибка восстановления", - "networkException": "Ошибка сети. Проверьте подключение и повторите попытку", + "backupFromNewerVersion": "Резервная копия создана более новой версией приложения. Обновите приложение перед восстановлением", + "networkTimeoutError": "Время ожидания запроса истекло. Проверьте сеть или прокси и повторите попытку", + "networkHostLookupError": "Не удалось определить адрес сервера. Проверьте правильность URL и работу DNS", + "networkConnectionError": "Не удалось подключиться к серверу. Проверьте подключение к сети или настройки прокси", + "networkTlsError": "Не удалось установить защищённое соединение. Сертификат сервера может быть недействителен, или соединение перехватывается", + "networkCancelledError": "Запрос отменён", + "networkAccessDeniedError": "Сервер запретил доступ (HTTP {code}). Возможно, ссылка устарела или учётные данные неверны", + "networkNotFoundError": "По этому адресу ничего не найдено (HTTP {code}). Проверьте правильность URL", + "networkRateLimitedError": "Слишком много запросов (HTTP 429). Подождите немного и повторите попытку", + "networkServerError": "На сервере произошла ошибка (HTTP {code}). Повторите попытку позже", + "networkBadResponseError": "Сервер отклонил запрос (HTTP {code})", + "networkRequestFailed": "Сетевой запрос не выполнен: {detail}", "invalidBackupFile": "Недопустимый файл резервной копии", "pruneCache": "Очистить кэш", "backupAndRestore": "Резервное копирование и восстановление", "backupAndRestoreDesc": "Синхронизация данных через WebDAV или файлы", "restore": "Восстановить", "restoreSuccess": "Восстановление выполнено", - "restoreFromWebDAVDesc": "Восстановить данные из WebDAV", - "restoreFromFileDesc": "Восстановить данные из файла", "restoreOnlyConfig": "Восстановить только профили", "restoreAllData": "Восстановить все данные", "addProfile": "Добавить профиль", "delayTest": "Тест задержки", "proxyGroupEmpty": "Группа прокси пуста", - "proxyGroupNameEmpty": "Название группы прокси не может быть пустым", "proxyGroupNameDuplicate": "Название группы прокси уже используется", "confirmExitWindow": "Вы уверены, что хотите закрыть текущее окно?", "dataChangedSave": "Обнаружены изменения данных. Сохранить их?", @@ -464,6 +555,8 @@ "excludeProxyFilter": "Фильтр исключения узлов", "excludeType": "Исключаемые типы", "expectedStatus": "Ожидаемый статус", + "strategy": "Стратегия", + "tolerance": "Допуск", "selectProxies": "Выбрать прокси", "inputProxyGroupName": "Введите название группы прокси", "helperCorruptTip": "Служба Helper недоступна, поэтому TUN-режим включить нельзя. Переустановите FlClash.", @@ -488,7 +581,7 @@ "basicStrategy": "Базовые политики", "editProxy": "Редактировать прокси", "includeAllProxyProviders": "Включить всех провайдеров прокси", - "includeAllProxyProvidersTip": "При включении переопределяет подключённых провайдеров прокси", + "includeAllProxyProvidersTip": "При включении группа берёт всех провайдеров прокси этого профиля: собственных провайдеров подписки, а также профили и прокси-провайдеры приложения, которые использует любая группа прокси", "addProxyProviders": "Добавить провайдеров прокси", "includeAllProxies": "Включить все прокси", "includeAllProxiesTip": "Подключает все прокси вне групп; ниже можно добавить дополнительные группы прокси", @@ -550,17 +643,16 @@ "invalidSubRule": "{subRule} — недопустимый SUB_RULE", "invalidPolicy": "{target} — недопустимая политика", "invalidProxyProvider": "{providerName} — недопустимый провайдер прокси", + "invalidRuleSet": "{ruleSet} — недопустимый набор правил", + "invalidNetworkContent": "Поддерживаются только tcp и udp", + "invalidRangeContent": "Введите числа или диапазоны, например 80 или 8000-9000, через /", + "invalidDscpContent": "Метка DSCP не может превышать 63", "invalidProxy": "{proxyName} — недопустимый прокси", - "proxyGroupDetectedAbnormal": "Обнаружены отклонения в текущей группе прокси", - "proxyProviderDetectedAbnormal": "Обнаружены отклонения в выбранных провайдерах прокси", - "proxyDetectedAbnormal": "Обнаружены отклонения в выбранных прокси", - "createProfile": "Создать профиль", "locationPermissionRequired": "Требуется разрешение на геолокацию", "locationPermissionGuide": "1. Откройте Системные настройки > Конфиденциальность и безопасность\n2. Выберите Службы геолокации\n3. Найдите и отметьте {appName} в списке\n\nПосле настройки вернитесь в приложение и продолжайте работу. Спасибо за сотрудничество.", "prerequisites": "Предварительные условия", "ignoreBatteryOptimization": "Игнорировать оптимизацию батареи", "batteryOptimizationDesc": "Чтобы приложение работало в фоне, отключите для него оптимизацию батареи. Нажмите, чтобы перейти к настройкам.", - "batteryOptimizationStatusTip": "Из-за системных ограничений во время работы невозможно корректно получить статус оптимизации батареи", "locationPermission": "Разрешение на геолокацию", "locationPermissionDesc": "По требованию системы для получения имени сети Wi-Fi необходимо разрешение на геолокацию. На Android выберите «Разрешить всегда», иначе имя сети Wi-Fi нельзя получить, пока приложение в фоне.", "excludeSsids": "Исключённые SSID", @@ -573,7 +665,7 @@ "editSsid": "Изменить SSID", "authorized": "Разрешено", "tapToAuthorize": "Нажмите, чтобы разрешить", - "suspended": "Приостановлено...", + "suspended": "Приостановлено…", "geoOptions": "Настройки Geo", "geoAutoUpdate": "Автообновление", "geoAutoUpdateInterval": "Интервал автообновления", @@ -584,7 +676,6 @@ "geoSkipped": "{name}: уже последняя версия", "geoUpdated": "{name}: обновлено", "secondsCount": "{count, plural, one{{count} секунда} few{{count} секунды} many{{count} секунд} other{{count} секунды}}", - "entriesCount": "{count, plural, one{{count} запись} few{{count} записи} many{{count} записей} other{{count} записи}}", "proxiesCount": "{count} прокси", "rulesCount": "{count, plural, one{{count} правило} few{{count} правила} many{{count} правил} other{{count} правила}}", "changelogBreaking": "Важные изменения", @@ -600,7 +691,6 @@ "pinWindow": "Закрепить поверх всех окон", "unpinWindow": "Открепить окно", "exitFullScreen": "Выйти из полноэкранного режима", - "toggleLabel": "Переключить подписи", "torch": "Фонарик", "pickFromAlbum": "Выбрать из галереи", "blockConnection": "Заблокировать соединение", @@ -611,11 +701,76 @@ "previousMatch": "Предыдущее совпадение", "nextMatch": "Следующее совпадение", "clearSearch": "Очистить поиск", + "noSearchResults": "Ничего не найдено", "addWidget": "Добавить виджет", "showPassword": "Показать пароль", "hidePassword": "Скрыть пароль", "authorize": "Разрешить", "installedAppsPermissionRequired": "Требуется разрешение на список приложений", "installedAppsPermissionDesc": "Эта система не выдаёт список установленных приложений без разрешения. Предоставьте его, чтобы настроить прокси для отдельных приложений.", - "installedAppsPermissionDeniedMessage": "Разрешение на список приложений отклонено, поэтому установленные приложения недоступны. Предоставьте его вручную в системных настройках." + "installedAppsPermissionDeniedMessage": "Разрешение на список приложений отклонено, поэтому установленные приложения недоступны. Предоставьте его вручную в системных настройках.", + "outboundIp": "Исходящий IP", + "ipAddress": "IP-адрес", + "ipQualityLevel": "Уровень", + "ipQualityGood": "Хороший", + "ipQualityNormal": "Обычный", + "ipQualityRisky": "Рискованный", + "ipType": "Тип", + "ipTypeResidential": "Домашний", + "ipTypeMobile": "Мобильная сеть", + "ipTypeBusiness": "Бизнес", + "ipTypeHosting": "Дата-центр", + "ipFlags": "Метки", + "ipFlagProxy": "Прокси", + "ipFlagVpn": "VPN", + "ipFlagTor": "Tor", + "ipFlagAbuser": "Злоупотребления", + "ipOrganization": "Организация", + "ipAsn": "ASN", + "ipQualitySource": "Источник ответа", + "ipQualitySources": "Источники", + "ipQualityFailed": "Не удалось определить тип IP", + "ipQualityRetry": "Проверить снова", + "ipSourceNoType": "Тип не определён", + "ipSourceRateLimited": "Лимит запросов", + "ipSourceIpMismatch": "Другой исходящий IP", + "hideIp": "Скрыть IP", + "editorUnavailable": "Редактор недоступен", + "replace": "Заменить", + "replaceAll": "Заменить все", + "cameraPermissionRequired": "Требуется доступ к камере", + "cameraPermissionDesc": "Разрешите доступ к камере в системных настройках, чтобы сканировать QR-коды, или выберите изображение QR-кода из галереи.", + "cameraUnavailable": "Камера недоступна", + "retry": "Повторить", + "invalidProfileQrcode": "Этот QR-код не содержит ссылку на профиль", + "dnsQueries": "DNS-запросы", + "recordType": "Тип записи", + "answers": "Ответы", + "responseCode": "Код ответа", + "error": "Ошибка", + "initiator": "Инициатор", + "cache": "Кэш", + "proxyNode": "Прокси-узел", + "yes": "Да", + "no": "Нет", + "nonTextProviderFile": "Этот внешний ресурс не является текстовым файлом", + "addCustomProxy": "Добавить прокси", + "proxyDefinition": "Полная конфигурация", + "proxyDefinitionNotMap": "Конфигурация должна быть YAML-словарём с полями name и type", + "customProxiesEmpty": "Пользовательских прокси нет, поэтому используются прокси самого профиля", + "overwriteIssueEmptyName": "Имя не задано", + "overwriteIssueReservedName": "{name} — встроенное имя политики, его нельзя использовать", + "overwriteIssueDuplicateName": "Имя {name} уже занято другим прокси или группой прокси", + "overwriteIssueCoreRejected": "Ядро не может разобрать этот прокси: {message}", + "overwriteIssueMissingProxies": "Эти прокси или политики не существуют: {names}", + "overwriteIssueMissingProviders": "Эти провайдеры прокси не существуют: {names}", + "overwriteIssueNoProxySource": "Не выбраны ни прокси, ни провайдеры прокси, поэтому ядро отклонит эту группу", + "overwriteIssueGroupLoop": "Группы прокси ссылаются друг на друга по кругу: {path}", + "overwriteIssuesSummary": "Проблем: {count}, применение переопределения может завершиться ошибкой", + "overwriteIssueSubscriptionGroupMissingProxies": "Собственные группы прокси профиля ссылаются на прокси, которых больше нет среди пользовательских: {names}", + "overwriteIssueProviderShadowed": "В профиле уже есть провайдер с именем {name}, поэтому провайдер приложения с тем же именем не используется. Переименуйте его", + "providerInUse": "«{label}» всё ещё используется в пользовательских группах прокси или правилах профилей: {profiles}. Сначала уберите его оттуда", + "providerSourceSubscription": "Подписка", + "providerRenameShadowed": "В подписках профилей {profiles} уже есть «{label}», и после переименования они будут использовать его. Выберите другое имя", + "appProviderShadowed": "Одноимённый элемент приложения здесь не используется" } diff --git a/arb/intl_zh_CN.arb b/arb/intl_zh_CN.arb index c3dd17ca..ddc39303 100644 --- a/arb/intl_zh_CN.arb +++ b/arb/intl_zh_CN.arb @@ -9,19 +9,32 @@ "profiles": "配置", "tools": "工具", "logs": "日志", - "logsDesc": "日志捕获记录", "resources": "资源", - "resourcesDesc": "外部资源相关信息", "trafficUsage": "流量统计", "networkSpeed": "网络速度", "outboundMode": "出站模式", "networkDetection": "网络检测", + "serviceStatus": "服务状态", + "serviceRestricted": "访问受限", + "serviceAvailable": "可用", + "serviceUnavailable": "不可用", + "serviceFailed": "检测失败", + "serviceDisallowedIsp": "不允许的 ISP", + "serviceBlocked": "已被封禁", + "serviceUnsupportedRegion": "地区不支持", + "serviceOriginalsOnly": "仅限自制内容", + "serviceComingSoon": "即将上线", + "servicePending": "待检测", + "serviceManage": "管理服务", + "serviceCheck": "检测", + "serviceCheckAll": "全部检测", + "serviceCheckedAt": "检测于 {time}", "upload": "上传", "download": "下载", "usedTraffic": "已用流量", "totalTraffic": "总流量", "expireTime": "到期时间", - "nullProfileDesc": "没有配置文件,请先添加配置文件", + "nullProfileDesc": "添加一个配置文件后即可开始使用", "settings": "设置", "language": "语言", "defaultText": "默认", @@ -36,27 +49,22 @@ "themeDesc": "设置深色模式,调整色彩", "override": "覆写", "allowLan": "局域网代理", - "allowLanDesc": "允许通过局域网访问代理", "tun": "虚拟网卡", "tunDesc": "仅在管理员模式生效", "minimizeOnExit": "退出时最小化", - "minimizeOnExitDesc": "修改系统默认退出事件", "autoLaunch": "自启动", "autoLaunchDesc": "跟随系统自启动", "silentLaunch": "静默启动", - "silentLaunchDesc": "后台启动", + "silentLaunchDesc": "启动时不显示窗口", "autoRun": "自动运行", "autoRunDesc": "应用打开时自动运行", "logcat": "日志捕获", "logcatDesc": "禁用将会隐藏日志入口", "autoCheckUpdate": "自动检查更新", - "autoCheckUpdateDesc": "应用启动时自动检查更新", "checkCertificate": "校验 TLS 证书", "checkCertificateDesc": "拒绝不受信任的证书。关闭后订阅和备份将暴露于中间人攻击", "accessControl": "访问控制", "accessControlDesc": "配置应用访问代理", - "application": "应用程序", - "applicationDesc": "修改应用程序相关设置", "edit": "编辑", "confirm": "确定", "update": "更新", @@ -103,12 +111,14 @@ "show": "显示", "exit": "退出", "systemProxy": "系统代理", + "safeMode": "安全模式", + "safeModeAppTitle": "{appName}(安全模式)", "project": "项目", "core": "内核", "tabAnimation": "选项卡动画", "desc": "基于ClashMeta的多平台代理客户端,简单易用,开源无广告。", - "startVpn": "正在启动VPN...", - "stopVpn": "正在停止VPN...", + "startVpn": "正在启动VPN…", + "stopVpn": "正在停止VPN…", "compatible": "兼容模式", "notSelectedTip": "当前代理组无法选中", "changeProxyFailedTip": "切换代理失败,已恢复上一次的选择", @@ -137,28 +147,26 @@ "country": "区域", "search": "搜索", "allowBypass": "允许应用绕过VPN", - "allowBypassDesc": "开启后部分应用可绕过VPN", "externalController": "外部控制器", "externalControllerDesc": "开启后将可以通过9090端口控制Clash内核", "ipv6Desc": "开启后将可以接收IPv6流量", "app": "应用", "general": "常规", - "systemProxyDesc": "设置系统代理", + "startupAndBackground": "启动与后台", + "requestsAndUpdates": "请求与更新", + "logsAndDiagnostics": "日志与诊断", "userAgent": "用户代理", "unifiedDelay": "统一延迟", - "unifiedDelayDesc": "去除握手等额外延迟", "tcpConcurrent": "TCP并发", - "tcpConcurrentDesc": "开启后允许TCP并发", "geodataLoader": "Geo低内存模式", - "geodataLoaderDesc": "开启将使用Geo低内存加载器", "requests": "请求", - "requestsDesc": "查看最近请求记录", + "recentRequests": "最近请求", "findProcessMode": "查找进程", "init": "初始化", "infiniteTime": "长期有效", "connections": "连接", + "liveConnections": "实时连接", "inbound": "入站", - "connectionsDesc": "查看当前连接数据", "intranetIP": "内网 IP", "view": "查看", "cut": "剪切", @@ -167,7 +175,7 @@ "testUrl": "测速链接", "sync": "同步", "exclude": "从最近任务中隐藏", - "excludeDesc": "应用在后台时,从最近任务中隐藏应用", + "excludeDesc": "应用在后台时,从最近任务中隐藏应用", "expand": "标准", "shrink": "紧凑", "min": "最小", @@ -182,19 +190,18 @@ "go": "前往", "externalLink": "外部链接", "otherContributors": "其他贡献者", + "appIconDesign": "应用图标设计", "autoCloseConnections": "自动关闭连接", "autoCloseConnectionsDesc": "切换节点后自动关闭连接", - "onlyStatisticsProxy": "仅统计代理", - "onlyStatisticsProxyDesc": "开启后,将只统计代理流量", + "onlyStatisticsProxy": "仅统计代理流量", "showNotificationStopAction": "通知栏显示停止按钮", - "showNotificationStopActionDesc": "在常驻通知上显示停止按钮。若系统因此总是展开通知,可关闭", "pureBlackMode": "纯黑模式", + "sidebarBlur": "侧边栏背景模糊", + "sidebarBlurDesc": "侧边栏透出窗口后方模糊的桌面", "keepAliveIntervalDesc": "TCP保持活动间隔", "entries": "个条目", "local": "本地", "remote": "远程", - "remoteBackupDesc": "备份数据到WebDAV", - "localBackupDesc": "备份数据到本地", "mode": "模式", "time": "时间", "source": "来源", @@ -209,72 +216,122 @@ "profilesSort": "配置排序", "start": "启动", "stop": "暂停", - "dnsDesc": "更新DNS相关设置", "key": "键", "value": "值", - "hostsDesc": "追加Hosts", "vpnTip": "重启VPN后改变生效", "vpnEnableDesc": "通过VpnService自动路由系统所有流量", "options": "选项", - "loopback": "回环解锁工具", - "loopbackDesc": "用于UWP回环解锁", + "enabled": "已开启", + "disabled": "已关闭", + "loopback": "UWP 回环解锁", "providers": "外部资源", "proxyProviders": "代理集", + "ruleProviders": "规则集", + "appProxyProviders": "应用代理集", + "appRuleProviders": "应用规则集", + "behavior": "行为", + "format": "格式", + "providerUrlTip": "仅支持远程资源", "subscriptionInfo": "订阅信息", "overrideDns": "覆写DNS", - "overrideDnsDesc": "开启后将覆盖配置中的DNS选项", + "overrideNtp": "覆写NTP", + "ntpStatusDesc": "从NTP服务器获取时间,而非系统时钟", + "server": "服务器", + "ntpInterval": "同步间隔(分钟)", + "dialerProxy": "拨号代理", + "dialerProxyDesc": "用于连接NTP服务器的出站", + "writeToSystem": "写入系统", + "writeToSystemDesc": "同时设置系统时钟,Android上不生效", + "overrideEntries": "覆写项", + "addOverrideEntry": "添加覆写项", + "discardChanges": "是否放弃更改?", + "quickEdit": "快速编辑", "status": "状态", "statusDesc": "关闭后将使用系统DNS", - "preferH3Desc": "优先使用DOH的http/3", "respectRules": "遵守规则", - "respectRulesDesc": "DNS连接跟随rules,需配置proxy-server-nameserver", + "respectRulesDesc": "DNS连接遵守规则,需配置Proxy Server Nameserver", "dnsMode": "DNS模式", - "fakeipRange": "Fakeip范围", - "fakeipFilter": "Fakeip过滤", - "defaultNameserver": "默认域名服务器", - "defaultNameserverDesc": "用于解析DNS服务器", - "nameserver": "域名服务器", - "nameserverDesc": "用于解析域名", + "fakeipRange": "Fake-IP范围", + "fakeipFilter": "Fake-IP过滤", "useHosts": "使用Hosts", "useSystemHosts": "使用系统Hosts", - "nameserverPolicy": "域名服务器策略", - "nameserverPolicyDesc": "指定对应域名服务器策略", - "proxyNameserver": "代理域名服务器", - "proxyNameserverDesc": "用于解析代理节点的域名", - "fallback": "Fallback", - "fallbackDesc": "一般情况下使用境外DNS", "fallbackFilter": "Fallback过滤", - "geoipCode": "Geoip代码", - "ipcidr": "IP/掩码", "domain": "域名", + "listenRoutingMark": "监听路由标记", + "listenRoutingMarkDesc": "仅Linux有效", + "ipv6Timeout": "IPv6超时(毫秒)", + "cacheAlgorithm": "缓存算法", + "cacheMaxSize": "缓存大小", + "fakeipRange6": "Fake-IP范围(IPv6)", + "fakeipFilterMode": "Fake-IP过滤模式", + "fakeipFilterModeDesc": "blacklist排除匹配项,whitelist仅用于匹配项,rule按规则匹配", + "fakeipTtl": "Fake-IP TTL", "reset": "重置", "actionView": "显示/隐藏", "actionStart": "启动/停止", "actionMode": "切换模式", "actionProxy": "系统代理", "actionTun": "虚拟网卡", + "actionRuleMode": "规则模式", + "actionGlobalMode": "全局模式", + "actionDirectMode": "直连模式", + "actionDelayTest": "测试全部延迟", + "actionUpdateProfiles": "更新全部配置", "disclaimer": "免责声明", - "disclaimerDesc": "本软件仅供学习交流、科研等非商业性质的用途,严禁将本软件用于商业目的。如有任何商业行为,均与本软件无关。", + "disclaimerDesc": "在使用 FlClash(以下简称“本软件”)前,请仔细阅读并充分理解本声明的全部内容。点击“同意”即表示你已阅读、理解并接受以下全部条款;如不同意,请点击“退出”并停止使用本软件。", + "disclaimerSoftwareTitle": "软件性质", + "disclaimerSoftwareContent": "本软件是基于 Clash.Meta(mihomo)内核的开源网络代理客户端,仅提供配置管理、规则分流与流量转发等本地工具功能。\n\n本软件自身不提供任何代理服务器、节点、订阅、机场或网络接入服务,也不与任何此类服务的提供者存在合作、代理或担保关系。", + "disclaimerUsageTitle": "使用限制", + "disclaimerUsageContent": "本软件仅供学习交流、技术研究等非商业用途。严禁将本软件用于任何商业目的,包括但不限于付费分发、捆绑销售、作为商业服务的组成部分或以本软件名义开展经营活动;任何商业行为均与本软件及其开发者无关。\n\n严禁将本软件用于违反你所在国家或地区法律法规的活动,包括但不限于绕过依法设置的网络访问限制、传播违法信息、实施网络攻击或侵犯他人合法权益。", + "disclaimerResponsibilityTitle": "用户责任", + "disclaimerResponsibilityContent": "你应自行确认使用本软件在你所在国家或地区是合法的,并对使用本软件的全部行为及其后果独立承担法律责任。\n\n你导入的订阅、节点与配置由你自行选择和判断,其来源是否合法、内容是否安全、服务是否稳定,均由你与相关提供者自行负责。", + "disclaimerThirdPartyTitle": "第三方内容", + "disclaimerThirdPartyContent": "订阅链接、配置文件、规则集、脚本、外部资源及外部链接均由第三方提供,开发者无法也不会对其合法性、准确性、安全性和可用性进行审查或担保。\n\n因使用第三方内容导致的数据泄露、财产损失、账号封禁或其他任何损失,由你与第三方自行解决,开发者不承担任何责任。", + "disclaimerWarrantyTitle": "无担保声明", + "disclaimerWarrantyContent": "本软件按“现状”和“可用”的原则提供,不附带任何明示或默示的担保,包括但不限于适销性、特定用途适用性、不侵权以及持续可用、无错误、无安全漏洞的担保。\n\n开发者不保证本软件能满足你的需求,也不保证本软件的运行不会中断或不会出现错误。", + "disclaimerLiabilityTitle": "责任限制", + "disclaimerLiabilityContent": "在适用法律允许的最大范围内,开发者及所有贡献者均不对因使用或无法使用本软件而产生的任何直接、间接、偶然、特殊、惩罚性或后果性损害承担责任,包括但不限于数据丢失、设备损坏、网络异常、业务中断、利润损失或因此引起的任何法律纠纷,即使已被告知发生此类损害的可能性。", + "disclaimerPrivacyTitle": "数据收集与隐私", + "disclaimerPrivacyContent": "本软件不会收集或上传你的订阅地址、节点信息、配置内容、访问的网站、连接记录、流量内容和日志,这些数据仅保存在你的设备本地,开发者无法获取。\n\n本软件只会在你使用相应功能时访问外部网络,例如更新订阅时访问你提供的订阅地址、检查更新时访问 GitHub。\n\n桌面版(Windows、macOS、Linux)未集成任何数据统计或崩溃上报服务。Android 版集成了 Google Firebase 的以下两项服务,用于改进应用稳定性:", + "disclaimerCrashlyticsTitle": "Firebase Crashlytics(崩溃分析)", + "disclaimerCrashlyticsContent": "应用发生崩溃时,自动上传崩溃报告。\n\n收集内容:崩溃堆栈与错误信息、崩溃发生时间、应用版本与构建号、设备品牌与型号、Android 系统版本、屏幕方向、剩余内存与存储空间、设备是否已 root,以及一个随安装生成、重装后即重置的随机安装标识。\n\n用途:仅用于定位和修复崩溃问题。\n\n你可以在“工具 > 常规 > 崩溃分析”中随时关闭。", + "disclaimerAnalyticsTitle": "Firebase Analytics(使用统计)", + "disclaimerAnalyticsContent": "随 Firebase 自动收集基础的应用使用统计。\n\n收集内容:首次启动、应用打开与会话时长、应用更新等基础事件,应用实例标识,设备型号、系统版本、系统语言,以及由 IP 地址推断的国家或地区级大致位置。\n\n用途:仅用于了解活跃设备数、版本分布与系统兼容情况。开发者不会将这些数据用于广告,不会出售,也不会与你的订阅或配置相关联。", + "disclaimerDataProcessingContent": "上述数据由 Google 代为处理和存储,可能被传输至你所在国家或地区以外(如美国)的服务器,并受 Google 隐私政策与 Firebase 隐私和安全说明约束。崩溃报告最多保留 90 天,统计数据按 Firebase 的默认策略保留。", + "disclaimerLicenseTitle": "开源协议", + "disclaimerLicenseContent": "本软件以 GPL-3.0 协议开源。你可以在遵守该协议的前提下自由使用、修改和分发本软件,但须同样以 GPL-3.0 协议开源并保留原作者的版权声明。\n\n本软件包含的第三方组件(包括 Clash.Meta 内核)分别遵循其各自的开源协议。基于本软件修改或分发的版本所产生的任何问题,与原作者无关。", + "disclaimerChangesTitle": "声明变更", + "disclaimerChangesContent": "开发者有权随版本更新修改本声明,修改后的内容随新版本发布即生效。你在更新后继续使用本软件,即视为接受修改后的声明。", + "disclaimerAcceptTitle": "接受声明", + "disclaimerAcceptContent": "一旦你安装、复制或使用本软件,即视为你已阅读并同意本声明的全部内容。如你不同意本声明的任何条款,请立即停止使用并卸载本软件。", + "disclaimerAndroidOnly": "仅 Android", + "disclaimerGooglePrivacy": "Google 隐私政策", + "disclaimerFirebasePrivacy": "Firebase 隐私和安全说明", "agree": "同意", "hotkeyManagement": "快捷键管理", - "hotkeyManagementDesc": "使用键盘控制应用程序", - "pressKeyboard": "请按下按键", - "inputCorrectHotkey": "请输入正确的快捷键", - "hotkeyConflict": "快捷键冲突", + "hotkeyDesc": "全局快捷键在窗口隐藏时依然生效,点击操作即可录制组合键。", + "hotkeyNotSet": "未设置", + "pressKeyboard": "请按下组合键", + "hotkeyNeedsModifier": "至少包含 {modifiers} 中的一个", + "hotkeyConflictWith": "已被“{action}”使用,保存后将移到这里", + "hotkeyUnavailable": "未能注册,可能已被其他应用占用", "remove": "移除", - "noHotKey": "暂无快捷键", "noNetwork": "无网络", "ipv6InboundDesc": "允许IPv6入站", "exportLogs": "导出日志", "exportSuccess": "导出成功", "iconStyle": "图标样式", - "onlyIcon": "仅图标", + "iconStyleFilled": "色块", + "iconStylePlain": "纯图标", + "iconStyleHidden": "隐藏", + "filter": "筛选", + "hideTimeoutProxies": "隐藏超时节点", + "hideTimeoutProxiesDesc": "不显示上次延迟测试超时的节点", "stackMode": "栈模式", "network": "网络", - "networkDesc": "修改网络相关设置", "bypassDomain": "排除域名", "bypassDomainDesc": "仅在系统代理启用时生效", - "resetTip": "确定要重置吗?", + "resetTip": "确定要重置吗?", "icon": "图片", "noData": "暂无数据", "fontFamily": "字体", @@ -284,7 +341,6 @@ "routeModeBypassPrivate": "绕过私有路由地址", "routeModeConfig": "使用配置", "routeAddress": "路由地址", - "routeAddressDesc": "配置监听路由地址", "interfaceNameMode": "出站网卡", "interfaceNameModeClear": "清空", "interfaceNameModeFollow": "跟随配置", @@ -293,9 +349,23 @@ "interfaceNameDesc": "出站连接使用的网卡名称", "copyEnvVar": "复制环境变量", "memoryInfo": "内存信息", + "total": "总计", + "releaseMemory": "释放内存", + "memoryCoreHeapInuse": "堆内存使用中", + "memoryCoreHeapIdle": "堆内存空闲", + "memoryCoreStack": "协程栈", + "memoryCoreRuntime": "运行时开销", + "memoryCoreNotRunning": "内核未运行", + "memoryAppResident": "常驻内存", + "memoryAppShared": "应用及共享", + "memoryEstimateDesc": "基于进程常驻内存估算,可能与系统显示的数值不同。", + "memoryEstimateSharedDesc": "内核与应用运行在同一进程,内核部分按运行时统计估算,其余计入应用及共享内存。", + "memoryReleased": "内存已释放", + "memoryReleasedSize": "已释放 {size}", + "releaseMemoryFailed": "释放内存失败", "cancel": "取消", "fileIsUpdate": "文件有修改,是否保存修改", - "profileHasUpdate": "配置文件已经修改,是否关闭自动更新 ", + "profileHasUpdate": "配置文件已经修改,是否关闭自动更新?", "hasCacheChange": "是否缓存修改", "copySuccess": "复制成功", "copyLink": "复制链接", @@ -305,27 +375,27 @@ "listen": "监听", "undo": "撤销", "redo": "重做", + "lineWrap": "自动换行", "none": "无", - "basicConfig": "基础配置", - "basicConfigDesc": "全局修改基础配置", "advancedConfig": "进阶配置", - "advancedConfigDesc": "提供多样化配置", + "advancedConfigDesc": "网络、DNS、附加规则与脚本", "selectedCountTitle": "已选择 {count} 项", "addRule": "添加规则", "ruleName": "规则名称", "content": "内容", "subRule": "子规则", "ruleTarget": "规则目标", - "matchTargetTitle": "匹配目标", "matchTarget": "MATCH-TARGET", "followProfile": "跟随配置", - "matchTargetDesc": "目标为 MATCH-TARGET 的规则路由到这里,默认取本配置末尾 MATCH 规则的目标。", - "selectMatchTarget": "选择 MATCH-TARGET", "sourceIp": "源IP", "noResolve": "不解析IP", "saveChanges": "是否保存更改?", - "findProcessModeDesc": "开启后会有一定性能损耗", - "tabAnimationDesc": "仅在移动视图中有效", + "navigationBarStyle": "底栏", + "floating": "悬浮", + "docked": "固定", + "slide": "滑动", + "fade": "淡入", + "pureBlack": "纯黑", "colorSchemes": "配色方案", "palette": "调色板", "tonalSpotScheme": "调性点缀", @@ -348,6 +418,8 @@ "launchInterruptedTip": "应用上次在启动过程中意外退出。已跳过本次自动配置,你可以手动启动重试。", "clearData": "清除数据", "textScale": "文本缩放", + "textScalePreview": "应用内的文字将以这个大小显示", + "followSystem": "跟随系统", "internet": "互联网", "systemApp": "系统应用", "noNetworkApp": "无网络应用", @@ -361,7 +433,13 @@ "interval": "间隔", "existsTip": "{label}当前已存在", "maxLengthTip": "{label}最多{max}个字符", - "multipleValuesTip": "多个值使用逗号分隔", + "singleAdd": "单条添加", + "batchAdd": "批量添加", + "batchListInputTip": "每行一项,也可用逗号分隔", + "batchMapInputTip": "每行一条,键和值之间用空格分隔", + "batchPreviewTip": "将添加 {count} 项,跳过 {skipped} 项已存在", + "lineIssueTip": "第 {line} 行:{message}", + "singleValueTip": "{label}只能是一项", "deleteTip": "确定删除当前{label}吗?", "deleteMultipTip": "确定删除选中的{label}吗?", "nullTip": "暂无{label}", @@ -378,6 +456,7 @@ "import": "导入", "importFile": "通过文件导入", "importUrl": "通过URL导入", + "startFromScratch": "从零开始", "autoSetSystemDns": "自动设置系统DNS", "details": "{label}详情", "creationTime": "创建时间", @@ -396,7 +475,7 @@ "request": "请求", "connected": "已连接", "disconnected": "已断开", - "connecting": "连接中...", + "connecting": "连接中…", "restartCoreTip": "您确定要重启核心吗?", "forceRestartCoreTip": "您确定要强制重启核心吗?", "dnsHijacking": "DNS劫持", @@ -406,20 +485,25 @@ "crashlytics": "崩溃分析", "crashlyticsTip": "开启后,应用崩溃时自动上传不包含敏感信息的崩溃日志", "appendSystemDns": "追加系统DNS", - "appendSystemDnsTip": "强制为配置附加系统DNS", "editRule": "编辑规则", "overrideMode": "覆写模式", "standardModeDesc": "标准模式,覆写基础配置,提供简单追加规则能力", "scriptModeDesc": "脚本模式,使用外部扩展脚本,提供一键覆写配置的能力", "addedRules": "附加规则", "controlGlobalAddedRules": "控制全局附加规则", + "quickAdd": "快捷添加", + "rulePresetBlockQuic": "屏蔽 QUIC", + "rulePresetBlockStun": "屏蔽 STUN", + "rulePresetBlockDot": "屏蔽 DNS over TLS", + "rulePresetSystemServicesDirect": "Apple 与 Microsoft 直连", + "rulePresetBittorrentDirect": "BT 下载直连", + "rulePresetLanDirect": "局域网直连", "overrideScript": "覆写脚本", "goToConfigureScript": "前往配置脚本", "editGlobalRules": "编辑全局规则", - "externalFetch": "外部获取", "confirmForceCrashCore": "确定要强制崩溃核心?", "confirmClearAllData": "确定要清除所有数据?", - "loading": "加载中...", + "loading": "加载中…", "yearsAgo": "{count} 年前", "monthsAgo": "{count} 个月前", "daysAgo": "{count} 天前", @@ -435,26 +519,33 @@ "speedStatistics": "网速统计", "resetPageChangesTip": "当前页面存在更改,确定重置吗?", "overwriteTypeCustom": "自定义", - "overwriteTypeCustomDesc": "自定义模式,支持完全自定义修改代理组以及规则", + "overwriteTypeCustomDesc": "自定义模式,支持完全自定义修改代理、策略组以及规则", "unknownNetworkError": "未知网络错误", - "restoreException": "恢复异常", - "networkException": "网络异常,请检查连接后重试", + "backupFromNewerVersion": "该备份来自更高版本的应用,请先更新应用再恢复", + "networkTimeoutError": "请求超时,请检查网络或代理后重试", + "networkHostLookupError": "无法解析服务器地址,请确认链接正确且 DNS 可用", + "networkConnectionError": "无法连接到服务器,请检查网络连接或代理设置", + "networkTlsError": "安全连接失败,服务器证书可能无效,或连接被拦截", + "networkCancelledError": "请求已取消", + "networkAccessDeniedError": "服务器拒绝访问(HTTP {code}),链接可能已过期或凭据有误", + "networkNotFoundError": "该地址下没有内容(HTTP {code}),请确认链接是否正确", + "networkRateLimitedError": "请求过于频繁(HTTP 429),请稍后再试", + "networkServerError": "服务器出现问题(HTTP {code}),请稍后再试", + "networkBadResponseError": "服务器拒绝了请求(HTTP {code})", + "networkRequestFailed": "网络请求失败:{detail}", "invalidBackupFile": "无效备份文件", "pruneCache": "修剪缓存", "backupAndRestore": "备份与恢复", "backupAndRestoreDesc": "通过WebDAV或者文件同步数据", "restore": "恢复", "restoreSuccess": "恢复成功", - "restoreFromWebDAVDesc": "通过WebDAV恢复数据", - "restoreFromFileDesc": "通过文件恢复数据", "restoreOnlyConfig": "仅恢复配置文件", "restoreAllData": "恢复所有数据", "addProfile": "添加配置", "delayTest": "延迟测试", "proxyGroupEmpty": "策略组为空", - "proxyGroupNameEmpty": "策略组名称不能为空", "proxyGroupNameDuplicate": "策略组名称重复", - "confirmExitWindow": "确定要退出当前窗口吗?", + "confirmExitWindow": "确定要退出当前窗口吗?", "dataChangedSave": "检测到数据有更改,是否保存", "selectProxyProviders": "选择代理集", "proxyFilter": "节点过滤器", @@ -464,6 +555,8 @@ "excludeProxyFilter": "排除节点过滤器", "excludeType": "排除类型", "expectedStatus": "预期状态", + "strategy": "策略", + "tolerance": "容差", "selectProxies": "选择代理", "inputProxyGroupName": "输入策略组名称", "helperCorruptTip": "Helper 服务不可用,无法启用 TUN 模式,请重新安装 FlClash。", @@ -488,7 +581,7 @@ "basicStrategy": "基础策略", "editProxy": "编辑代理", "includeAllProxyProviders": "包含所有代理集", - "includeAllProxyProvidersTip": "开启后将覆盖引入的代理集", + "includeAllProxyProvidersTip": "开启后包含本配置的全部代理集:订阅自带的,以及任一策略组引用的配置和应用代理集", "addProxyProviders": "添加代理集", "includeAllProxies": "包含所有代理", "includeAllProxiesTip": "引入不包含策略组的所有代理,可在下方额外添加策略组", @@ -510,7 +603,7 @@ "ruleActionDomainWildcardDesc": "通配符匹配,仅支持*和?通配符", "ruleActionGeositeDesc": "匹配 Geosite 内的域名", "ruleActionIpCidrDesc": "匹配 IP 地址范围", - "ruleActionIpCidr6Desc": "匹配 IP 地址范围, IP-CIDR6 只是一个别名", + "ruleActionIpCidr6Desc": "匹配 IP 地址范围,IP-CIDR6 只是一个别名", "ruleActionIpSuffixDesc": "匹配 IP 后缀范围", "ruleActionIpAsnDesc": "匹配 IP 所属 ASN", "ruleActionGeoipDesc": "匹配 IP 所属国家代码", @@ -533,12 +626,12 @@ "ruleActionProcessNameWildcardDesc": "使用进程名称通配符匹配,仅支持*和?通配符", "ruleActionUidDesc": "匹配 Linux USER ID", "ruleActionNetworkDesc": "匹配TCP或者UDP", - "ruleActionDscpDesc": "匹配DSCP标记 (仅限 tproxy udp 入站)", + "ruleActionDscpDesc": "匹配DSCP标记(仅限 tproxy udp 入站)", "ruleActionRuleSetDesc": "引用规则集合,需配置rule-providers", "ruleActionAndDesc": "逻辑规则 AND", "ruleActionOrDesc": "逻辑规则 OR", "ruleActionNotDesc": "逻辑规则 NOT", - "ruleActionSubRuleDesc": "匹配至子规则,需要注意括号的使用", + "ruleActionSubRuleDesc": "匹配至子规则,需要注意括号的使用", "ruleActionMatchDesc": "匹配所有请求,无需条件", "subRuleEmpty": "子规则为空", "proxyProvidersNotEmpty": "代理集不能为空", @@ -550,17 +643,16 @@ "invalidSubRule": "{subRule} 是一个无效的SUB_RULE", "invalidPolicy": "{target} 是一个无效的策略", "invalidProxyProvider": "{providerName} 是一个无效的代理集", + "invalidRuleSet": "{ruleSet} 不是有效的规则集", + "invalidNetworkContent": "仅支持 tcp 或 udp", + "invalidRangeContent": "请输入数字或范围,如 80 或 8000-9000,多个用 / 分隔", + "invalidDscpContent": "DSCP 标记不能超过 63", "invalidProxy": "{proxyName} 是一个无效的代理", - "proxyGroupDetectedAbnormal": "检测到当前策略组异常", - "proxyProviderDetectedAbnormal": "检测到选中的代理集存在异常", - "proxyDetectedAbnormal": "检测到选中的代理存在异常", - "createProfile": "创建配置", "locationPermissionRequired": "需要位置权限", "locationPermissionGuide": "1. 打开 系统设置 > 隐私与安全性\n2. 选择 定位服务\n3. 在右侧列表中找到并勾选 {appName}\n\n完成设置后,返回应用即可正常使用。感谢您的配合。", "prerequisites": "前置条件", "ignoreBatteryOptimization": "忽略电池优化", "batteryOptimizationDesc": "为保证后台运行,请关闭本应用的电池优化。点击前往设置。", - "batteryOptimizationStatusTip": "由于系统限制,运行状态下无法正确获取电池优化状态", "locationPermission": "位置权限", "locationPermissionDesc": "根据系统要求,获取Wi-Fi名称需要您授予位置权限。Android 上请选择“始终允许”,否则应用在后台时无法获取 Wi-Fi 名称。", "excludeSsids": "排除SSIDs", @@ -573,7 +665,7 @@ "editSsid": "编辑SSID", "authorized": "已授权", "tapToAuthorize": "点击授权", - "suspended": "挂起中...", + "suspended": "挂起中…", "geoOptions": "Geo 选项", "geoAutoUpdate": "自动更新", "geoAutoUpdateInterval": "自动更新间隔", @@ -584,7 +676,6 @@ "geoSkipped": "{name} 已是最新版本", "geoUpdated": "{name} 已更新", "secondsCount": "{count} 秒", - "entriesCount": "{count} 个条目", "proxiesCount": "{count} 个代理", "rulesCount": "{count} 条规则", "changelogBreaking": "重大变更", @@ -600,7 +691,6 @@ "pinWindow": "窗口置顶", "unpinWindow": "取消置顶", "exitFullScreen": "退出全屏", - "toggleLabel": "切换标签", "torch": "手电筒", "pickFromAlbum": "从相册选择", "blockConnection": "阻止连接", @@ -611,11 +701,76 @@ "previousMatch": "上一个匹配", "nextMatch": "下一个匹配", "clearSearch": "清除搜索", + "noSearchResults": "没有匹配的结果", "addWidget": "添加组件", "showPassword": "显示密码", "hidePassword": "隐藏密码", "authorize": "授权", "installedAppsPermissionRequired": "需要读取应用列表权限", "installedAppsPermissionDesc": "当前系统在授权前不会提供已安装的应用列表,授权后即可配置分应用代理。", - "installedAppsPermissionDeniedMessage": "读取应用列表权限已被拒绝,无法获取已安装的应用。请前往系统设置手动开启。" + "installedAppsPermissionDeniedMessage": "读取应用列表权限已被拒绝,无法获取已安装的应用。请前往系统设置手动开启。", + "outboundIp": "出站 IP", + "ipAddress": "IP 地址", + "ipQualityLevel": "等级", + "ipQualityGood": "优", + "ipQualityNormal": "普通", + "ipQualityRisky": "风险", + "ipType": "类型", + "ipTypeResidential": "住宅", + "ipTypeMobile": "移动网络", + "ipTypeBusiness": "商业", + "ipTypeHosting": "机房", + "ipFlags": "命中标记", + "ipFlagProxy": "代理", + "ipFlagVpn": "VPN", + "ipFlagTor": "Tor", + "ipFlagAbuser": "滥用记录", + "ipOrganization": "组织", + "ipAsn": "ASN", + "ipQualitySource": "采用来源", + "ipQualitySources": "各来源", + "ipQualityFailed": "类型查询失败", + "ipQualityRetry": "重新查询", + "ipSourceNoType": "无法判定类型", + "ipSourceRateLimited": "限流", + "ipSourceIpMismatch": "出站 IP 不一致", + "hideIp": "隐藏 IP", + "editorUnavailable": "编辑器不可用", + "replace": "替换", + "replaceAll": "全部替换", + "cameraPermissionRequired": "需要相机权限", + "cameraPermissionDesc": "请在系统设置中允许访问相机以扫描二维码,或从相册选择二维码图片。", + "cameraUnavailable": "相机不可用", + "retry": "重试", + "invalidProfileQrcode": "该二维码不包含配置文件链接", + "dnsQueries": "DNS查询", + "recordType": "记录类型", + "answers": "应答", + "responseCode": "响应码", + "error": "错误", + "initiator": "发起方", + "cache": "缓存", + "proxyNode": "代理节点", + "yes": "是", + "no": "否", + "nonTextProviderFile": "该外部资源不是文本文件", + "addCustomProxy": "添加代理", + "proxyDefinition": "完整配置", + "proxyDefinitionNotMap": "配置必须是包含 name 和 type 的 YAML 映射", + "customProxiesEmpty": "未添加自定义代理,沿用配置文件自身的代理", + "overwriteIssueEmptyName": "名称为空", + "overwriteIssueReservedName": "{name} 是内置策略名,不能在此使用", + "overwriteIssueDuplicateName": "名称 {name} 已被其他代理或策略组使用", + "overwriteIssueCoreRejected": "内核无法解析该代理:{message}", + "overwriteIssueMissingProxies": "以下代理或策略不存在:{names}", + "overwriteIssueMissingProviders": "以下代理集不存在:{names}", + "overwriteIssueNoProxySource": "未选择任何代理或代理集,内核会拒绝该策略组", + "overwriteIssueGroupLoop": "策略组之间存在循环引用:{path}", + "overwriteIssuesSummary": "{count} 项存在问题,应用覆写可能失败", + "overwriteIssueSubscriptionGroupMissingProxies": "配置文件自身的策略组引用了自定义代理中已没有的代理:{names}", + "overwriteIssueProviderShadowed": "配置文件中已有名为 {name} 的外部资源,同名的应用级外部资源不会生效,请改名", + "providerInUse": "{label} 仍被 {profiles} 的自定义策略组或规则使用,请先在那里移除", + "providerSourceSubscription": "订阅", + "providerRenameShadowed": "{profiles} 的订阅里已有 {label},改名后这些配置会改用订阅里的那个,请换一个名称", + "appProviderShadowed": "同名的应用级项在此不生效" } diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 82895dc5..d2dc1e3c 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -16,6 +16,7 @@ import 'package:fl_clash/l10n/l10n.dart'; import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/providers/providers.dart'; import 'package:fl_clash/state.dart'; +import 'package:fl_clash/views/disclaimer.dart'; import 'package:fl_clash/views/navigation.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter/services.dart'; @@ -241,7 +242,7 @@ class Bootstrap { )) { return; } - final isDisclaimerAccepted = await dialogs.showDisclaimer(); + final isDisclaimerAccepted = await requestDisclaimerConsent(); if (!isDisclaimerAccepted) { await _container.read(systemActionProvider.notifier).handleExit(); } diff --git a/lib/common/common.dart b/lib/common/common.dart index 00ba8dd8..3698f7f2 100644 --- a/lib/common/common.dart +++ b/lib/common/common.dart @@ -44,6 +44,7 @@ export 'provider_reader.dart'; export 'proxy.dart'; export 'request.dart'; export 'scroll.dart'; +export 'search.dart'; export 'shape.dart'; export 'snowflake.dart'; export 'string.dart'; diff --git a/lib/common/compute.dart b/lib/common/compute.dart index 0a51d499..46fe34f8 100644 --- a/lib/common/compute.dart +++ b/lib/common/compute.dart @@ -16,23 +16,18 @@ List computeSort({ required Map selectedMap, required String testUrl, }) { - return List.from(proxies)..sort((a, b) { - final aDelayState = computeProxyDelayState( - proxyName: a.name, - testUrl: testUrl, - groups: groups, - selectedMap: selectedMap, - delayMap: delayMap, - ); - final bDelayState = computeProxyDelayState( - proxyName: b.name, - testUrl: testUrl, - groups: groups, - selectedMap: selectedMap, - delayMap: delayMap, - ); - return aDelayState.compareTo(bDelayState); - }); + final delayStates = { + for (final proxy in proxies) + proxy.name: computeProxyDelayState( + proxyName: proxy.name, + testUrl: testUrl, + groups: groups, + selectedMap: selectedMap, + delayMap: delayMap, + ), + }; + return List.of(proxies) + ..sort((a, b) => delayStates[a.name]!.compareTo(delayStates[b.name]!)); } List sortOfName(List proxies) { @@ -56,6 +51,58 @@ List computeSort({ }).toList(); } +/// Built-in adapters whose delay probe always fails, so a timeout says nothing. +const _unprobeableProxyTypes = { + 'Reject', + 'RejectDrop', + 'Pass', + 'PassRule', + 'Rematch', + 'Compatible', + 'Dns', +}; + +List computeHideTimeout({ + required List groups, + required List allGroups, + required DelayMap delayMap, + required Map selectedMap, + required String defaultTestUrl, +}) { + final realStates = {}; + final proxyTypes = { + for (final group in allGroups) + for (final proxy in group.all) proxy.name: proxy.type, + }; + return groups.map((group) { + final groupTestUrl = group.testUrl.takeFirstValid([defaultTestUrl]); + final groupWithNow = allGroups.getGroup(group.name) ?? group; + final selectedName = groupWithNow.getCurrentSelectedName( + selectedMap[group.name] ?? '', + ); + final visible = group.all.where((proxy) { + if (proxy.name == selectedName) { + return true; + } + final state = realStates.putIfAbsent( + proxy.name, + () => computeRealSelectedProxyState( + proxy.name, + groups: allGroups, + selectedMap: selectedMap, + ), + ); + if (_unprobeableProxyTypes.contains(proxyTypes[state.proxyName])) { + return true; + } + final testUrl = state.testUrl.takeFirstValid([groupTestUrl]); + final delay = delayMap[testUrl]?[state.proxyName]; + return delay == null || delay > 0; + }).toList(); + return group.copyWith(all: visible.isEmpty ? group.all : visible); + }).toList(); +} + SelectedProxyState getRealSelectedProxyState( SelectedProxyState state, { required List groups, diff --git a/lib/common/constant.dart b/lib/common/constant.dart index 940534e2..9b666cd8 100644 --- a/lib/common/constant.dart +++ b/lib/common/constant.dart @@ -83,6 +83,11 @@ const maxConcurrentDelayTests = 16; const animateDuration = Duration(milliseconds: 100); const midDuration = Duration(milliseconds: 200); const commonDuration = Duration(milliseconds: 300); + +/// How often a live Core feed is allowed to repaint. One batch costs about a +/// frame on a phone, and anything at or below the 200ms scroll-to-end +/// animation restarts it mid-flight, so the list jumps instead of animating. +const renderThrottleDuration = Duration(milliseconds: 300); const defaultUpdateDuration = Duration(days: 1); const MMDB = 'GEOIP.metadb'; const ASN = 'ASN.mmdb'; diff --git a/lib/common/datetime.dart b/lib/common/datetime.dart index ce398a73..fe4ca716 100644 --- a/lib/common/datetime.dart +++ b/lib/common/datetime.dart @@ -45,15 +45,15 @@ extension DateTimeExtension on DateTime { } String get show { - return toString().substring(0, 10); + return toLocal().toString().substring(0, 10); } String get showFull { - return toString().substring(0, 19); + return toLocal().toString().substring(0, 19); } String get showTime { - return toString().substring(10, 19); + return toLocal().toString().substring(10, 19); } } diff --git a/lib/common/link.dart b/lib/common/link.dart index 83243389..73283652 100644 --- a/lib/common/link.dart +++ b/lib/common/link.dart @@ -5,9 +5,35 @@ import 'package:flutter/foundation.dart'; import 'print.dart'; import 'protocol.dart'; +import 'string.dart'; typedef InstallConfigCallBack = void Function(String url); +String? profileUrlFromQrCodes(Iterable values) { + for (final value in values) { + final text = value?.trim(); + if (text == null || text.isEmpty) { + continue; + } + if (text.isUrl) { + return text; + } + final uri = Uri.tryParse(text); + if (uri == null || !protocolSchemes.contains(uri.scheme)) { + continue; + } + final url = _installConfigUrl(uri)?.trim(); + if (url != null && url.isUrl) { + return url; + } + } + return null; +} + +String? _installConfigUrl(Uri uri) { + return uri.host == 'install-config' ? uri.queryParameters['url'] : null; +} + class LinkManager { static LinkManager? _instance; StreamSubscription? subscription; @@ -46,12 +72,9 @@ class LinkManager { void _handle(Uri uri, Function(String url) installConfigCallBack) { commonPrint.log('onAppLink: $uri'); - if (uri.host == 'install-config') { - final parameters = uri.queryParameters; - final url = parameters['url']; - if (url != null) { - installConfigCallBack(url); - } + final url = _installConfigUrl(uri); + if (url != null) { + installConfigCallBack(url); } } diff --git a/lib/common/picker.dart b/lib/common/picker.dart index a6fad615..178ca68d 100644 --- a/lib/common/picker.dart +++ b/lib/common/picker.dart @@ -44,16 +44,19 @@ class Picker { if (xFile == null) { return null; } - final controller = MobileScannerController(); - final capture = await controller.analyzeImage( + // Not through a throwaway MobileScannerController: disposing one clears + // the platform scan window of a scanner page that is still open. + final capture = await MobileScannerPlatform.instance.analyzeImage( xFile.path, - formats: [BarcodeFormat.qrCode], + formats: const [BarcodeFormat.qrCode], ); - final result = capture?.barcodes.first.rawValue; - if (result == null || !result.isUrl) { + final url = profileUrlFromQrCodes( + capture?.barcodes.map((barcode) => barcode.rawValue) ?? const [], + ); + if (url == null) { throw MessageException(currentAppLocalizations.pleaseUploadValidQrcode); } - return result; + return url; } } diff --git a/lib/common/scroll.dart b/lib/common/scroll.dart index eb45c88a..92064945 100644 --- a/lib/common/scroll.dart +++ b/lib/common/scroll.dart @@ -5,6 +5,15 @@ import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/widgets/scroll.dart'; import 'package:material_ui/material_ui.dart'; +bool isTouchPlatform(TargetPlatform platform) => switch (platform) { + TargetPlatform.android || + TargetPlatform.iOS || + TargetPlatform.fuchsia => true, + TargetPlatform.linux || + TargetPlatform.macOS || + TargetPlatform.windows => false, +}; + class BaseScrollBehavior extends MaterialScrollBehavior { const BaseScrollBehavior({this.scrollbarPadding = EdgeInsets.zero}); @@ -20,18 +29,8 @@ class BaseScrollBehavior extends MaterialScrollBehavior { PointerDeviceKind.unknown, }; - bool showScrollbar(BuildContext context) { - switch (getPlatform(context)) { - case TargetPlatform.linux: - case TargetPlatform.macOS: - case TargetPlatform.windows: - return true; - case TargetPlatform.android: - case TargetPlatform.fuchsia: - case TargetPlatform.iOS: - return false; - } - } + bool showScrollbar(BuildContext context) => + !isTouchPlatform(getPlatform(context)); @override Widget buildScrollbar( @@ -43,7 +42,7 @@ class BaseScrollBehavior extends MaterialScrollBehavior { !showScrollbar(context)) { return child; } - return CommonScrollBar( + return CommonScrollBar.ambient( controller: details.controller, padding: scrollbarPadding, child: child, diff --git a/lib/common/search.dart b/lib/common/search.dart new file mode 100644 index 00000000..d3066edc --- /dev/null +++ b/lib/common/search.dart @@ -0,0 +1,59 @@ +final _termSeparator = RegExp(r'\s+'); + +class SearchQuery { + final List terms; + + SearchQuery(String text) + : terms = text + .toLowerCase() + .split(_termSeparator) + .where((term) => term.isNotEmpty) + .toList(growable: false); + + bool get isEmpty => terms.isEmpty; + + bool get isNotEmpty => terms.isNotEmpty; + + // Terms hold no whitespace, so the newline keeps one from spanning fields. + static String textOf(Iterable fields) { + return fields.nonNulls.join('\n').toLowerCase(); + } + + bool matches(Iterable fields) { + if (terms.isEmpty) { + return true; + } + return matchesText(textOf(fields)); + } + + bool matchesText(String text) => terms.every(text.contains); +} + +extension SearchIterableExt on Iterable { + /// [texts] caches each item's text by identity, so it serves one [fieldsOf]. + Iterable whereMatches( + SearchQuery query, + Iterable Function(T item) fieldsOf, { + Expando? texts, + }) { + if (query.isEmpty) { + return this; + } + return where((item) { + if (texts == null || !_isExpandoKey(item)) { + return query.matches(fieldsOf(item)); + } + return query.matchesText( + texts[item as Object] ??= SearchQuery.textOf(fieldsOf(item)), + ); + }); + } +} + +bool _isExpandoKey(Object? item) { + return item != null && + item is! String && + item is! num && + item is! bool && + item is! Record; +} diff --git a/lib/common/task_pool.dart b/lib/common/task_pool.dart index 8ddb5a08..e87c8f51 100644 --- a/lib/common/task_pool.dart +++ b/lib/common/task_pool.dart @@ -13,6 +13,8 @@ class TaskPool { int get pendingCount => _waiting.length; + int get idleSlots => _waiting.isEmpty ? concurrency - _active : 0; + Future run(Future Function() task) async { if (_active >= concurrency || _waiting.isNotEmpty) { final waiter = Completer(); diff --git a/lib/enum/enum.dart b/lib/enum/enum.dart index 55d2c89e..0d7918f7 100644 --- a/lib/enum/enum.dart +++ b/lib/enum/enum.dart @@ -108,6 +108,8 @@ extension GroupTypeExtension on GroupType { enum UsedProxy { GLOBAL, DIRECT, REJECT } +enum DelayTestPhase { queued, running } + extension UsedProxyExtension on UsedProxy { static List get valueList => UsedProxy.values.map((e) => e.toString().split('.').last).toList(); @@ -121,15 +123,46 @@ enum ViewMode { mobile, laptop, desktop } enum LogLevel { debug, info, warning, error, silent } -extension LogLevelExt on LogLevel { - Color? color(BuildContext context) { +enum RecordTone { muted, neutral, warning, error } + +extension RecordToneExt on RecordTone { + Color? accentColor(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return switch (this) { - LogLevel.silent => colorScheme.outline, - LogLevel.debug => colorScheme.onSurfaceVariant, - LogLevel.info => null, - LogLevel.warning => colorScheme.tertiary, - LogLevel.error => colorScheme.error, + RecordTone.warning => colorScheme.tertiary, + RecordTone.error => colorScheme.error, + RecordTone.muted || RecordTone.neutral => null, + }; + } + + Color? tintColor(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return switch (this) { + RecordTone.warning => colorScheme.tertiaryContainer.withValues( + alpha: 0.2, + ), + RecordTone.error => colorScheme.errorContainer.withValues(alpha: 0.2), + RecordTone.muted || RecordTone.neutral => null, + }; + } + + Color labelColor(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return switch (this) { + RecordTone.muted => colorScheme.outline, + RecordTone.neutral => colorScheme.onSurfaceVariant, + RecordTone.warning => colorScheme.onTertiaryContainer, + RecordTone.error => colorScheme.onErrorContainer, + }; + } + + Color labelContainerColor(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return switch (this) { + RecordTone.muted => colorScheme.surfaceContainerHigh, + RecordTone.neutral => colorScheme.surfaceContainerHighest, + RecordTone.warning => colorScheme.tertiaryContainer, + RecordTone.error => colorScheme.errorContainer, }; } } @@ -344,7 +377,7 @@ enum HotAction { exit, } -enum ProxiesIconStyle { none, standard, icon } +enum ProxiesIconStyle { filled, plain, hidden } enum FontFamily { twEmoji('Twemoji'), @@ -662,6 +695,7 @@ enum LoadingTag { access, proxies, batteryOptimization, + checkUpdate, } enum CoreStatus { connecting, connected, disconnected } diff --git a/lib/features/connection/connection.dart b/lib/features/connection/connection.dart index e572200b..97937f74 100644 --- a/lib/features/connection/connection.dart +++ b/lib/features/connection/connection.dart @@ -1,2 +1,3 @@ export 'tracker_info_item.dart'; export 'tracker_info_list.dart'; +export 'tracker_speed_ranker.dart'; diff --git a/lib/features/connection/tracker_info_item.dart b/lib/features/connection/tracker_info_item.dart index e1b9a0f9..d76ae660 100644 --- a/lib/features/connection/tracker_info_item.dart +++ b/lib/features/connection/tracker_info_item.dart @@ -1,64 +1,47 @@ import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; +import 'package:fl_clash/icons/icons.dart'; import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/providers/config.dart'; import 'package:fl_clash/widgets/widgets.dart'; -import 'package:flutter/services.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +String _ruleText(TrackerInfo trackerInfo) { + final rule = trackerInfo.rule; + final rulePayload = trackerInfo.rulePayload; + if (rulePayload.isNotEmpty) { + return '$rule($rulePayload)'; + } + return rule; +} + +String _endpointText(String ip, String port) { + if (ip.isEmpty) { + return ''; + } + if (port.isNotEmpty) { + return '$ip:$port'; + } + return ip; +} + class TrackerInfoItem extends ConsumerWidget { final TrackerInfo trackerInfo; + final bool isLive; final Function(String)? onClickKeyword; - final Widget? trailing; + final Widget? action; final String detailTitle; const TrackerInfoItem({ super.key, required this.trackerInfo, + this.isLive = false, this.onClickKeyword, - this.trailing, + this.action, required this.detailTitle, }); - Widget _buildMeta(BuildContext context) { - final traffic = Traffic(up: trackerInfo.upload, down: trackerInfo.download); - final chains = trackerInfo.chains; - final metaText = - '${trackerInfo.start.getLastUpdateTimeDesc(context)} · ${traffic.desc}'; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(top: 2), - child: Text( - metaText, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: context.textTheme.bodySmall?.copyWith( - color: context.colorScheme.onSurfaceVariant, - ), - ), - ), - if (chains.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 6, bottom: 0), - child: Wrap( - spacing: 6, - runSpacing: 4, - children: [ - for (final chain in chains) - CommonChip( - label: chain, - onPressed: () => onClickKeyword?.call(chain), - ), - ], - ), - ), - ], - ); - } - @override Widget build(BuildContext context, ref) { final showIcon = ref.watch( @@ -67,48 +50,155 @@ class TrackerInfoItem extends ConsumerWidget { state.findProcessMode == FindProcessMode.always && system.isAndroid, ), ); - final process = trackerInfo.metadata.process; - final icon = showIcon - ? GestureDetector( - onTap: () { - if (process.isEmpty) return; - onClickKeyword?.call(process); - }, - child: Padding( - padding: const EdgeInsetsGeometry.only(top: 6), - child: PackageIcon(packageName: process, size: 44), - ), - ) - : null; - return ListItem( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ).copyWith(bottom: 12), - minVerticalPadding: 0, - horizontalTitleGap: 12, - tileTitleAlignment: ListTileTitleAlignment.top, + return RecordListItem( onTap: () { showExtend( context, builder: (_) { - return AdaptiveSheetScaffold( - sheetTransparentToolBar: true, + return CommonScaffold( body: TrackerInfoDetailView(trackerInfo: trackerInfo), title: detailTitle, ); }, ); }, - leading: icon, - title: Text( - trackerInfo.desc, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: context.textTheme.bodyLarge, + header: _buildHeader(context), + body: _buildBody(showIcon: showIcon), + ); + } + + Widget _buildBody({required bool showIcon}) { + final process = trackerInfo.metadata.process; + final body = _TrackerInfoBody( + trackerInfo: trackerInfo, + onClickKeyword: onClickKeyword, + ); + if (!showIcon || process.isEmpty) { + return body; + } + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 12, + children: [ + GestureDetector( + onTap: () => onClickKeyword?.call(process), + child: PackageIcon(packageName: process, size: 40), + ), + Expanded(child: body), + ], + ); + } + + Widget _buildHeader(BuildContext context) { + final network = Text( + trackerInfo.metadata.network.toUpperCase(), + style: const TextStyle(fontWeight: FontWeight.w500), + ); + if (!isLive) { + return RecordHeader( + trailing: action, + children: [RecordTimestamp(trackerInfo.start.showFull), network], + ); + } + final color = context.colorScheme.onSurfaceVariant; + WidgetSpan arrow(Glyph glyph) => WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: GlyphIcon(glyph, size: 12, color: color), + ); + return RecordHeader( + trailing: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + Text.rich( + TextSpan( + children: [ + arrow(AppGlyphs.arrowUp), + TextSpan( + text: ' ${(trackerInfo.uploadSpeed ?? 0).traffic.show}/s ', + ), + arrow(AppGlyphs.arrowDown), + TextSpan( + text: ' ${(trackerInfo.downloadSpeed ?? 0).traffic.show}/s', + ), + ], + ), + ), + ?action, + ], ), - subtitle: _buildMeta(context), - trailing: trailing, + children: [ + Text(trackerInfo.start.getLastUpdateTimeDesc(context)), + network, + ], + ); + } +} + +class _TrackerInfoBody extends StatelessWidget { + final TrackerInfo trackerInfo; + final Function(String)? onClickKeyword; + + const _TrackerInfoBody({required this.trackerInfo, this.onClickKeyword}); + + @override + Widget build(BuildContext context) { + final colorScheme = context.colorScheme; + final styles = RecordTextStyles.of(context); + final metadata = trackerInfo.metadata; + final rule = _ruleText(trackerInfo); + final source = [ + trackerInfo.progressText, + _endpointText(metadata.sourceIP, metadata.sourcePort), + ].where((text) => text.isNotEmpty).join(' · '); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 4, + children: [ + Text.rich( + TextSpan( + children: [ + TextSpan( + text: _endpointText( + trackerInfo.title, + metadata.destinationPort, + ), + style: styles.primary?.copyWith(fontWeight: FontWeight.w500), + ), + if (metadata.host.isNotEmpty && metadata.destinationIP.isNotEmpty) + TextSpan( + text: ' ${metadata.destinationIP}', + style: styles.muted, + ), + ], + ), + ), + Wrap( + spacing: 6, + runSpacing: 4, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + if (rule.isNotEmpty) Text(rule, style: styles.secondary), + for (final (index, chain) in trackerInfo.chains.reversed.indexed) + Row( + mainAxisSize: MainAxisSize.min, + spacing: 6, + children: [ + if (index > 0 || rule.isNotEmpty) const RecordArrow(), + Flexible( + child: TonalChip( + label: chain, + color: colorScheme.secondaryContainer, + foregroundColor: colorScheme.onSecondaryContainer, + onPressed: () => onClickKeyword?.call(chain), + ), + ), + ], + ), + ], + ), + if (source.isNotEmpty) Text(source, style: styles.muted), + ], ); } } @@ -118,52 +208,24 @@ class TrackerInfoDetailView extends StatelessWidget { const TrackerInfoDetailView({super.key, required this.trackerInfo}); - String _getRuleText() { - final rule = trackerInfo.rule; - final rulePayload = trackerInfo.rulePayload; - if (rulePayload.isNotEmpty) { - return '$rule($rulePayload)'; - } - return rule; - } - - String _getProcessText() { - final process = trackerInfo.metadata.process; - final uid = trackerInfo.metadata.uid; - if (uid != 0) { - return '$process($uid)'; - } - return process; - } - - String _getEndpointText(String ip, String port) { - if (ip.isEmpty) { - return ''; - } - if (port.isNotEmpty) { - return '$ip:$port'; - } - return ip; - } - Widget _buildChains(BuildContext context) { - return DecorationListItem( - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 20, + return DetailRow( + title: context.appLocalizations.proxyChains, + value: Wrap( + spacing: 6, + runSpacing: 4, + alignment: WrapAlignment.end, + crossAxisAlignment: WrapCrossAlignment.center, children: [ - Text(context.appLocalizations.proxyChains), - Flexible( - child: Wrap( + for (final (index, chain) in trackerInfo.chains.reversed.indexed) + Row( + mainAxisSize: MainAxisSize.min, spacing: 6, - runSpacing: 4, - alignment: WrapAlignment.end, children: [ - for (final chain in trackerInfo.chains) MetaChip(label: chain), + if (index > 0) const RecordArrow(), + Flexible(child: MetaChip(label: chain)), ], ), - ), ], ), ); @@ -172,7 +234,7 @@ class TrackerInfoDetailView extends StatelessWidget { List _buildRows(List<(String, String)> entries) { return [ for (final (title, value) in entries) - if (value.isNotEmpty) _DetailRow(title: title, value: value), + if (value.isNotEmpty) DetailRow.text(title: title, value: value), ]; } @@ -183,15 +245,15 @@ class TrackerInfoDetailView extends StatelessWidget { return ListView( padding: const EdgeInsets.symmetric( horizontal: 16, - ).copyWith(bottom: 20, top: context.sheetTopPadding), + ).copyWith(bottom: 20, top: context.contentTopPadding), children: [ generateSectionV3( title: appLocalizations.basicInfo, items: _buildRows([ (appLocalizations.creationTime, trackerInfo.start.showFull), (appLocalizations.networkType, metadata.network), - (appLocalizations.process, _getProcessText()), - (appLocalizations.rule, _getRuleText()), + (appLocalizations.process, trackerInfo.progressText), + (appLocalizations.rule, _ruleText(trackerInfo)), (appLocalizations.upload, trackerInfo.upload.traffic.show), (appLocalizations.download, trackerInfo.download.traffic.show), ]), @@ -202,14 +264,11 @@ class TrackerInfoDetailView extends StatelessWidget { (appLocalizations.host, metadata.host), ( appLocalizations.source, - _getEndpointText(metadata.sourceIP, metadata.sourcePort), + _endpointText(metadata.sourceIP, metadata.sourcePort), ), ( appLocalizations.destination, - _getEndpointText( - metadata.destinationIP, - metadata.destinationPort, - ), + _endpointText(metadata.destinationIP, metadata.destinationPort), ), ( appLocalizations.destinationGeoIP, @@ -234,40 +293,3 @@ class TrackerInfoDetailView extends StatelessWidget { ); } } - -class _DetailRow extends StatelessWidget { - final String title; - final String value; - - const _DetailRow({required this.title, required this.value}); - - Future _copy(BuildContext context) async { - await Clipboard.setData(ClipboardData(text: value)); - if (!context.mounted) return; - context.showNotifier(context.appLocalizations.copySuccess); - } - - @override - Widget build(BuildContext context) { - return DecorationListItem( - onPressed: () => _copy(context), - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 20, - children: [ - Text(title), - Flexible( - child: Text( - value, - textAlign: TextAlign.end, - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceVariant, - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/features/connection/tracker_info_list.dart b/lib/features/connection/tracker_info_list.dart index 14d68126..e407bade 100644 --- a/lib/features/connection/tracker_info_list.dart +++ b/lib/features/connection/tracker_info_list.dart @@ -49,7 +49,7 @@ class TrackerInfoList extends StatelessWidget { final bool shrinkWrap; final ScrollPhysics? physics; final EdgeInsetsGeometry? padding; - final Widget? Function(TrackerInfo trackerInfo)? trailingBuilder; + final Widget? Function(TrackerInfo trackerInfo)? actionBuilder; const TrackerInfoList({ super.key, @@ -60,7 +60,7 @@ class TrackerInfoList extends StatelessWidget { this.shrinkWrap = false, this.physics, this.padding, - this.trailingBuilder, + this.actionBuilder, }); @override @@ -76,8 +76,9 @@ class TrackerInfoList extends StatelessWidget { itemBuilder: (_, index) => _buildTrackerInfoItem( context, trackerInfos[index], + isLive: false, detailTitle: detailTitle, - trailingBuilder: trailingBuilder, + actionBuilder: actionBuilder, ), ); } @@ -90,7 +91,7 @@ class TrackerInfoAnimatedList extends StatelessWidget { final String detailTitle; final ScrollController? controller; final EdgeInsetsGeometry? padding; - final Widget? Function(TrackerInfo trackerInfo)? trailingBuilder; + final Widget? Function(TrackerInfo trackerInfo)? actionBuilder; const TrackerInfoAnimatedList({ super.key, @@ -98,7 +99,7 @@ class TrackerInfoAnimatedList extends StatelessWidget { required this.detailTitle, this.controller, this.padding, - this.trailingBuilder, + this.actionBuilder, }); @override @@ -112,8 +113,9 @@ class TrackerInfoAnimatedList extends StatelessWidget { itemBuilder: (context, trackerInfo) => _buildTrackerInfoItem( context, trackerInfo, + isLive: true, detailTitle: detailTitle, - trailingBuilder: trailingBuilder, + actionBuilder: actionBuilder, ), ); } @@ -122,16 +124,18 @@ class TrackerInfoAnimatedList extends StatelessWidget { Widget _buildTrackerInfoItem( BuildContext context, TrackerInfo trackerInfo, { + required bool isLive, required String detailTitle, - required Widget? Function(TrackerInfo trackerInfo)? trailingBuilder, + required Widget? Function(TrackerInfo trackerInfo)? actionBuilder, }) { return TrackerInfoItem( key: Key(trackerInfo.id), trackerInfo: trackerInfo, + isLive: isLive, onClickKeyword: (value) { context.commonScaffoldState?.addKeyword(value); }, - trailing: trailingBuilder?.call(trackerInfo), + action: actionBuilder?.call(trackerInfo), detailTitle: detailTitle, ); } diff --git a/lib/features/connection/tracker_speed_ranker.dart b/lib/features/connection/tracker_speed_ranker.dart new file mode 100644 index 00000000..cce2df2a --- /dev/null +++ b/lib/features/connection/tracker_speed_ranker.dart @@ -0,0 +1,115 @@ +import 'dart:math'; + +import 'package:fl_clash/models/models.dart'; + +class _SpeedSample { + final int upload; + final int download; + final DateTime at; + final int uploadSpeed; + final int downloadSpeed; + final double rankSpeed; + + const _SpeedSample({ + required this.upload, + required this.download, + required this.at, + required this.uploadSpeed, + required this.downloadSpeed, + required this.rankSpeed, + }); +} + +/// Derives per-connection speed from successive cumulative snapshots and +/// orders connections by it without reshuffling the list every poll. +class TrackerSpeedRanker { + // Closing a connection triggers an out-of-band refresh; a delta over a few + // milliseconds would read as a spike, so such samples keep the last speed. + static const _minSampleGap = Duration(milliseconds: 500); + static const _smoothing = 0.5; + + final _samples = {}; + var _positions = const {}; + + List rank(List trackerInfos, DateTime now) { + final samples = { + for (final trackerInfo in trackerInfos) + trackerInfo.id: _sample(trackerInfo, now), + }; + _samples + ..clear() + ..addAll(samples); + + int bucketOf(TrackerInfo trackerInfo) { + final speed = samples[trackerInfo.id]!.rankSpeed; + return speed < 1 ? 0 : (log(speed) / ln2).floor() + 1; + } + + final ranked = + [ + for (final trackerInfo in trackerInfos) + trackerInfo.copyWith( + uploadSpeed: samples[trackerInfo.id]!.uploadSpeed, + downloadSpeed: samples[trackerInfo.id]!.downloadSpeed, + ), + ]..sort((a, b) { + final bucketA = bucketOf(a); + final bucket = bucketOf(b).compareTo(bucketA); + if (bucket != 0) { + return bucket; + } + if (bucketA > 0) { + final position = (_positions[a.id] ?? trackerInfos.length) + .compareTo(_positions[b.id] ?? trackerInfos.length); + if (position != 0) { + return position; + } + } + final traffic = (b.upload + b.download).compareTo( + a.upload + a.download, + ); + if (traffic != 0) { + return traffic; + } + final start = b.start.compareTo(a.start); + return start != 0 ? start : a.id.compareTo(b.id); + }); + _positions = { + for (final (index, trackerInfo) in ranked.indexed) trackerInfo.id: index, + }; + return ranked; + } + + _SpeedSample _sample(TrackerInfo trackerInfo, DateTime now) { + final previous = _samples[trackerInfo.id]; + if (previous == null) { + return _SpeedSample( + upload: trackerInfo.upload, + download: trackerInfo.download, + at: now, + uploadSpeed: 0, + downloadSpeed: 0, + rankSpeed: 0, + ); + } + final elapsed = now.difference(previous.at); + if (elapsed < _minSampleGap) { + return previous; + } + final seconds = elapsed.inMicroseconds / Duration.microsecondsPerSecond; + final uploadSpeed = max(0, trackerInfo.upload - previous.upload) / seconds; + final downloadSpeed = + max(0, trackerInfo.download - previous.download) / seconds; + final rankSpeed = + previous.rankSpeed + + (uploadSpeed + downloadSpeed - previous.rankSpeed) * _smoothing; + return _SpeedSample( + upload: trackerInfo.upload, + download: trackerInfo.download, + at: now, + uploadSpeed: uploadSpeed.round(), + downloadSpeed: downloadSpeed.round(), + rankSpeed: rankSpeed < 1 ? 0 : rankSpeed, + ); + } +} diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index bbff2f9e..b91d6365 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -20,28 +20,28 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; - static String m0(code) => + static String m0(count, skipped) => + "${count} to add, ${skipped} skipped as existing"; + + static String m1(code) => "Windows refused to run FlClashCore.exe (error ${code}). An app control policy such as Smart App Control or AppLocker blocks unsigned programs; allow FlClash in that policy or turn it off, then try again."; - static String m1(name) => + static String m2(name) => "The app failed to finish launching twice in a row. To break the loop, the profile ${name} has been deselected and automatic setup was skipped. You can select it again at any time."; - static String m2(url) => "Do you want to create a profile from ${url}?"; + static String m3(url) => "Do you want to create a profile from ${url}?"; - static String m3(count) => + static String m4(count) => "${Intl.plural(count, one: '1 day ago', other: '${count} days ago')}"; - static String m4(label) => + static String m5(label) => "Are you sure you want to delete the selected ${label}?"; - static String m5(label) => "Are you sure you want to delete this ${label}?"; + static String m6(label) => "Are you sure you want to delete this ${label}?"; - static String m6(label) => "${label} details"; + static String m7(label) => "${label} details"; - static String m7(label) => "${label} cannot be empty"; - - static String m8(count) => - "${Intl.plural(count, one: '1 entry', other: '${count} entries')}"; + static String m8(label) => "${label} cannot be empty"; static String m9(label) => "${label} already exists"; @@ -49,52 +49,113 @@ class MessageLookup extends MessageLookupByLibrary { static String m11(name) => "${name} updated"; - static String m12(count) => + static String m12(action) => + "Already used by “${action}”. Saving moves it here."; + + static String m13(modifiers) => "Include at least one of ${modifiers}"; + + static String m14(count) => "${Intl.plural(count, one: '1 hour ago', other: '${count} hours ago')}"; - static String m13(count) => + static String m15(count) => "${Intl.plural(count, one: '1 hour', other: '${count} hours')}"; - static String m14(target) => "${target} is an invalid policy"; + static String m16(target) => "${target} is an invalid policy"; - static String m15(proxyName) => "${proxyName} is an invalid proxy"; + static String m17(proxyName) => "${proxyName} is an invalid proxy"; - static String m16(providerName) => + static String m18(providerName) => "${providerName} is an invalid proxy provider"; - static String m17(subRule) => "${subRule} is an invalid SUB_RULE"; + static String m19(ruleSet) => "${ruleSet} is an invalid rule set"; - static String m18(appName) => + static String m20(subRule) => "${subRule} is an invalid SUB_RULE"; + + static String m21(line, message) => "Line ${line}: ${message}"; + + static String m22(appName) => "1. Open System Settings > Privacy & Security\n2. Choose Location Services\n3. Find and check ${appName} in the list\n\nWhen you are done, return to the app to continue. Thank you for your cooperation."; - static String m19(label, max) => "${label} must be at most ${max} characters"; + static String m23(label, max) => "${label} must be at most ${max} characters"; - static String m20(count) => - "${Intl.plural(count, one: '1 minute ago', other: '${count} minutes ago')}"; - - static String m21(count) => - "${Intl.plural(count, one: '1 month ago', other: '${count} months ago')}"; - - static String m22(label) => "No ${label} yet"; - - static String m23(label) => "${label} must be a number"; - - static String m24(label) => "${label} must be between 1024 and 49151"; + static String m24(size) => "Released ${size}"; static String m25(count) => - "${Intl.plural(count, one: '1 proxy', other: '${count} proxies')}"; + "${Intl.plural(count, one: '1 minute ago', other: '${count} minutes ago')}"; static String m26(count) => + "${Intl.plural(count, one: '1 month ago', other: '${count} months ago')}"; + + static String m27(code) => + "The server denied access (HTTP ${code}). The link may have expired, or the credentials are wrong"; + + static String m28(code) => "The server rejected the request (HTTP ${code})"; + + static String m29(code) => + "Nothing was found at this address (HTTP ${code}). Check that the URL is correct"; + + static String m30(detail) => "Network request failed: ${detail}"; + + static String m31(code) => + "The server ran into a problem (HTTP ${code}). Try again later"; + + static String m32(label) => "No ${label} yet"; + + static String m33(label) => "${label} must be a number"; + + static String m34(message) => "The core cannot parse this proxy: ${message}"; + + static String m35(name) => + "The name ${name} is already used by another proxy or proxy group"; + + static String m36(path) => + "Proxy groups reference each other in a loop: ${path}"; + + static String m37(names) => "These proxy providers do not exist: ${names}"; + + static String m38(names) => + "These proxies or policies do not exist: ${names}"; + + static String m39(name) => + "The profile already has a provider named ${name}, so the app-level one is not used. Rename it to use it"; + + static String m40(name) => + "${name} is a built-in policy name and cannot be used here"; + + static String m41(names) => + "The profile\'s own proxy groups name proxies that the custom proxies no longer include: ${names}"; + + static String m42(count) => + "${count} items have problems, and applying this override may fail"; + + static String m43(label) => "${label} must be between 1024 and 49151"; + + static String m44(label, profiles) => + "${label} is still used by the custom proxy groups or rules of ${profiles}. Remove it there first"; + + static String m45(profiles, label) => + "The subscriptions of ${profiles} already have ${label}, so those profiles would switch to theirs. Choose another name"; + + static String m46(count) => + "${Intl.plural(count, one: '1 proxy', other: '${count} proxies')}"; + + static String m47(count) => "${Intl.plural(count, one: '1 rule', other: '${count} rules')}"; - static String m27(count) => + static String m48(appName) => "${appName} (Safe mode)"; + + static String m49(count) => "${Intl.plural(count, one: '1 second', other: '${count} seconds')}"; - static String m28(count) => "${count} selected"; + static String m50(count) => "${count} selected"; - static String m29(label) => "${label} must be a URL"; + static String m51(time) => "Checked at ${time}"; - static String m30(count) => + static String m52(label) => "${label} must be a single item"; + + static String m53(label) => "${label} must be a URL"; + + static String m54(count) => "${Intl.plural(count, one: '1 year ago', other: '${count} years ago')}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -118,12 +179,23 @@ class MessageLookup extends MessageLookupByLibrary { ), "account": MessageLookupByLibrary.simpleMessage("Account"), "action": MessageLookupByLibrary.simpleMessage("Action"), + "actionDelayTest": MessageLookupByLibrary.simpleMessage("Test all delays"), + "actionDirectMode": MessageLookupByLibrary.simpleMessage("Direct mode"), + "actionGlobalMode": MessageLookupByLibrary.simpleMessage("Global mode"), "actionMode": MessageLookupByLibrary.simpleMessage("Switch mode"), "actionProxy": MessageLookupByLibrary.simpleMessage("System proxy"), + "actionRuleMode": MessageLookupByLibrary.simpleMessage("Rule mode"), "actionStart": MessageLookupByLibrary.simpleMessage("Start/Stop"), "actionTun": MessageLookupByLibrary.simpleMessage("TUN"), + "actionUpdateProfiles": MessageLookupByLibrary.simpleMessage( + "Update profiles", + ), "actionView": MessageLookupByLibrary.simpleMessage("Show/Hide"), "add": MessageLookupByLibrary.simpleMessage("Add"), + "addCustomProxy": MessageLookupByLibrary.simpleMessage("Add proxy"), + "addOverrideEntry": MessageLookupByLibrary.simpleMessage( + "Add override entry", + ), "addProfile": MessageLookupByLibrary.simpleMessage("Add profile"), "addProxies": MessageLookupByLibrary.simpleMessage("Add proxies"), "addProxyGroup": MessageLookupByLibrary.simpleMessage("Add proxy group"), @@ -148,33 +220,31 @@ class MessageLookup extends MessageLookupByLibrary { "Advanced configuration", ), "advancedConfigDesc": MessageLookupByLibrary.simpleMessage( - "Provides diverse configuration options", + "Network, DNS, added rules, and scripts", ), "agree": MessageLookupByLibrary.simpleMessage("Agree"), "allowBypass": MessageLookupByLibrary.simpleMessage( "Allow apps to bypass VPN", ), - "allowBypassDesc": MessageLookupByLibrary.simpleMessage( - "When enabled, some apps can bypass the VPN", - ), "allowLan": MessageLookupByLibrary.simpleMessage("Allow LAN"), - "allowLanDesc": MessageLookupByLibrary.simpleMessage( - "Allow proxy access over the LAN", - ), + "answers": MessageLookupByLibrary.simpleMessage("Answers"), "app": MessageLookupByLibrary.simpleMessage("App"), "appAccessControl": MessageLookupByLibrary.simpleMessage( "App access control", ), + "appIconDesign": MessageLookupByLibrary.simpleMessage("App icon design"), + "appProviderShadowed": MessageLookupByLibrary.simpleMessage( + "The app-level one of this name is not used here", + ), + "appProxyProviders": MessageLookupByLibrary.simpleMessage( + "App proxy providers", + ), + "appRuleProviders": MessageLookupByLibrary.simpleMessage( + "App rule providers", + ), "appendSystemDns": MessageLookupByLibrary.simpleMessage( "Append system DNS", ), - "appendSystemDnsTip": MessageLookupByLibrary.simpleMessage( - "Force-append the system DNS to the configuration", - ), - "application": MessageLookupByLibrary.simpleMessage("Application"), - "applicationDesc": MessageLookupByLibrary.simpleMessage( - "Adjust application settings", - ), "authentication": MessageLookupByLibrary.simpleMessage("Authentication"), "authenticationDesc": MessageLookupByLibrary.simpleMessage( "Require credentials on the local proxy port to keep other local apps from using it", @@ -188,9 +258,6 @@ class MessageLookup extends MessageLookupByLibrary { "autoCheckUpdate": MessageLookupByLibrary.simpleMessage( "Auto check for updates", ), - "autoCheckUpdateDesc": MessageLookupByLibrary.simpleMessage( - "Check for updates automatically when the app starts", - ), "autoCloseConnections": MessageLookupByLibrary.simpleMessage( "Auto close connections", ), @@ -220,19 +287,24 @@ class MessageLookup extends MessageLookupByLibrary { "backupAndRestoreDesc": MessageLookupByLibrary.simpleMessage( "Sync data via WebDAV or files", ), - "backupSuccess": MessageLookupByLibrary.simpleMessage("Backup successful"), - "basicConfig": MessageLookupByLibrary.simpleMessage("Basic configuration"), - "basicConfigDesc": MessageLookupByLibrary.simpleMessage( - "Modify the basic configuration globally", + "backupFromNewerVersion": MessageLookupByLibrary.simpleMessage( + "This backup comes from a newer version of the app. Update the app before restoring it", ), + "backupSuccess": MessageLookupByLibrary.simpleMessage("Backup successful"), "basicInfo": MessageLookupByLibrary.simpleMessage("Basic info"), "basicStrategy": MessageLookupByLibrary.simpleMessage("Basic strategies"), + "batchAdd": MessageLookupByLibrary.simpleMessage("Batch add"), + "batchListInputTip": MessageLookupByLibrary.simpleMessage( + "One item per line, or separated by commas", + ), + "batchMapInputTip": MessageLookupByLibrary.simpleMessage( + "One entry per line: key, a space, then value", + ), + "batchPreviewTip": m0, "batteryOptimizationDesc": MessageLookupByLibrary.simpleMessage( "To keep the app running in the background, disable battery optimization for it. Tap to open settings.", ), - "batteryOptimizationStatusTip": MessageLookupByLibrary.simpleMessage( - "Due to system limitations, the battery optimization status cannot be read correctly while running", - ), + "behavior": MessageLookupByLibrary.simpleMessage("Behavior"), "bind": MessageLookupByLibrary.simpleMessage("Bind"), "blacklistMode": MessageLookupByLibrary.simpleMessage("Blacklist mode"), "blockConnection": MessageLookupByLibrary.simpleMessage("Block connection"), @@ -240,9 +312,21 @@ class MessageLookup extends MessageLookupByLibrary { "bypassDomainDesc": MessageLookupByLibrary.simpleMessage( "Only takes effect while the system proxy is enabled", ), + "cache": MessageLookupByLibrary.simpleMessage("Cache"), + "cacheAlgorithm": MessageLookupByLibrary.simpleMessage("Cache algorithm"), "cacheCorrupt": MessageLookupByLibrary.simpleMessage( "The cache is corrupted. Clear it?", ), + "cacheMaxSize": MessageLookupByLibrary.simpleMessage("Cache size"), + "cameraPermissionDesc": MessageLookupByLibrary.simpleMessage( + "Allow camera access in system settings to scan QR codes, or choose a QR code image from the album.", + ), + "cameraPermissionRequired": MessageLookupByLibrary.simpleMessage( + "Camera permission required", + ), + "cameraUnavailable": MessageLookupByLibrary.simpleMessage( + "Camera unavailable", + ), "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), "cancelSelectAll": MessageLookupByLibrary.simpleMessage("Deselect all"), "changeProxyFailedTip": MessageLookupByLibrary.simpleMessage( @@ -301,12 +385,9 @@ class MessageLookup extends MessageLookupByLibrary { "Confirming will overwrite existing data", ), "connected": MessageLookupByLibrary.simpleMessage("Connected"), - "connecting": MessageLookupByLibrary.simpleMessage("Connecting..."), + "connecting": MessageLookupByLibrary.simpleMessage("Connecting…"), "connection": MessageLookupByLibrary.simpleMessage("Connection"), "connections": MessageLookupByLibrary.simpleMessage("Connections"), - "connectionsDesc": MessageLookupByLibrary.simpleMessage( - "View current connection data", - ), "connectivity": MessageLookupByLibrary.simpleMessage("Connectivity: "), "content": MessageLookupByLibrary.simpleMessage("Content"), "contentNotEmpty": MessageLookupByLibrary.simpleMessage( @@ -323,24 +404,26 @@ class MessageLookup extends MessageLookupByLibrary { "copyLink": MessageLookupByLibrary.simpleMessage("Copy link"), "copySuccess": MessageLookupByLibrary.simpleMessage("Copied successfully"), "core": MessageLookupByLibrary.simpleMessage("Core"), - "coreBlockedByPolicyTip": m0, + "coreBlockedByPolicyTip": m1, "coreBlockedBySmartAppControlTip": MessageLookupByLibrary.simpleMessage( "Windows Smart App Control blocked FlClashCore.exe because it is not signed. Open Windows Security → App & browser control → Smart App Control settings, choose Off, then start FlClash again. Smart App Control cannot be turned back on without reinstalling Windows.", ), "coreStatus": MessageLookupByLibrary.simpleMessage("Core status"), "country": MessageLookupByLibrary.simpleMessage("Region"), "crashDetected": MessageLookupByLibrary.simpleMessage("Crash detected"), - "crashDetectedTip": m1, + "crashDetectedTip": m2, "crashTest": MessageLookupByLibrary.simpleMessage("Crash test"), "crashlytics": MessageLookupByLibrary.simpleMessage("Crash analytics"), "crashlyticsTip": MessageLookupByLibrary.simpleMessage( "When enabled, crash logs without sensitive information are uploaded automatically when the app crashes", ), "create": MessageLookupByLibrary.simpleMessage("Create"), - "createProfile": MessageLookupByLibrary.simpleMessage("Create profile"), - "createProfileFromUrlTip": m2, + "createProfileFromUrlTip": m3, "creationTime": MessageLookupByLibrary.simpleMessage("Creation time"), "custom": MessageLookupByLibrary.simpleMessage("Custom"), + "customProxiesEmpty": MessageLookupByLibrary.simpleMessage( + "No custom proxies, so the profile\'s own proxies are used", + ), "cut": MessageLookupByLibrary.simpleMessage("Cut"), "dark": MessageLookupByLibrary.simpleMessage("Dark"), "dashboard": MessageLookupByLibrary.simpleMessage("Dashboard"), @@ -356,19 +439,13 @@ class MessageLookup extends MessageLookupByLibrary { "databaseWriteFailedTip": MessageLookupByLibrary.simpleMessage( "Failed to save the change; it has been rolled back", ), - "daysAgo": m3, - "defaultNameserver": MessageLookupByLibrary.simpleMessage( - "Default nameserver", - ), - "defaultNameserverDesc": MessageLookupByLibrary.simpleMessage( - "Used to resolve DNS servers", - ), + "daysAgo": m4, "defaultText": MessageLookupByLibrary.simpleMessage("Default"), "delay": MessageLookupByLibrary.simpleMessage("Delay"), "delayTest": MessageLookupByLibrary.simpleMessage("Delay test"), "delete": MessageLookupByLibrary.simpleMessage("Delete"), - "deleteMultipTip": m4, - "deleteTip": m5, + "deleteMultipTip": m5, + "deleteTip": m6, "desc": MessageLookupByLibrary.simpleMessage( "A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.", ), @@ -379,7 +456,7 @@ class MessageLookup extends MessageLookupByLibrary { "destinationIPASN": MessageLookupByLibrary.simpleMessage( "Destination IP ASN", ), - "details": m6, + "details": m7, "detectionTip": MessageLookupByLibrary.simpleMessage( "Relies on a third-party API; for reference only", ), @@ -387,21 +464,110 @@ class MessageLookup extends MessageLookupByLibrary { "developerModeEnableTip": MessageLookupByLibrary.simpleMessage( "Developer mode is enabled.", ), + "dialerProxy": MessageLookupByLibrary.simpleMessage("Dialer proxy"), + "dialerProxyDesc": MessageLookupByLibrary.simpleMessage( + "The outbound used to reach the NTP server", + ), "direct": MessageLookupByLibrary.simpleMessage("Direct"), "disableUDP": MessageLookupByLibrary.simpleMessage("Disable UDP"), + "disabled": MessageLookupByLibrary.simpleMessage("Disabled"), + "discardChanges": MessageLookupByLibrary.simpleMessage( + "Discard the changes?", + ), "disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"), + "disclaimerAcceptContent": MessageLookupByLibrary.simpleMessage( + "By installing, copying, or using the Software, you are deemed to have read and agreed to this entire statement. If you disagree with any of its terms, stop using and uninstall the Software immediately.", + ), + "disclaimerAcceptTitle": MessageLookupByLibrary.simpleMessage("Acceptance"), + "disclaimerAnalyticsContent": MessageLookupByLibrary.simpleMessage( + "Basic app usage statistics are collected automatically with Firebase.\n\nWhat is collected: basic events such as first launch, app opens and session length, and app updates; an app instance ID; the device model, OS version, and system language; and an approximate country- or region-level location inferred from the IP address.\n\nPurpose: only to understand the number of active devices, version distribution, and OS compatibility. The developers do not use this data for advertising, do not sell it, and do not link it to your subscriptions or configurations.", + ), + "disclaimerAnalyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Analytics (usage statistics)", + ), + "disclaimerAndroidOnly": MessageLookupByLibrary.simpleMessage( + "Android only", + ), + "disclaimerChangesContent": MessageLookupByLibrary.simpleMessage( + "The developers may revise this statement with any release, and the revision takes effect when that release is published. Continuing to use the Software after updating means you accept the revised statement.", + ), + "disclaimerChangesTitle": MessageLookupByLibrary.simpleMessage( + "Changes to this statement", + ), + "disclaimerCrashlyticsContent": MessageLookupByLibrary.simpleMessage( + "When the app crashes, a crash report is uploaded automatically.\n\nWhat is collected: the crash stack trace and error message, the time of the crash, the app version and build number, the device brand and model, the Android version, screen orientation, free memory and storage, whether the device is rooted, and a random installation ID that is created on install and reset on reinstall.\n\nPurpose: only to locate and fix crashes.\n\nYou can turn it off at any time under \"Tools > General > Crash analytics\".", + ), + "disclaimerCrashlyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Crashlytics (crash analytics)", + ), + "disclaimerDataProcessingContent": MessageLookupByLibrary.simpleMessage( + "This data is processed and stored by Google on our behalf, may be transferred to servers outside your country or region (such as in the United States), and is governed by the Google Privacy Policy and the Firebase privacy and security documentation. Crash reports are kept for up to 90 days; statistics are kept under the Firebase default retention policy.", + ), "disclaimerDesc": MessageLookupByLibrary.simpleMessage( - "This software is intended only for non-commercial uses such as learning and research. Using it for any commercial purpose is strictly prohibited; any commercial activity is unrelated to this software.", + "Before using FlClash (\"the Software\"), please read this statement carefully and make sure you understand all of it. Tapping \"Agree\" means you have read, understood, and accept every term below. If you do not agree, tap \"Exit\" and stop using the Software.", + ), + "disclaimerFirebasePrivacy": MessageLookupByLibrary.simpleMessage( + "Firebase privacy and security", + ), + "disclaimerGooglePrivacy": MessageLookupByLibrary.simpleMessage( + "Google Privacy Policy", + ), + "disclaimerLiabilityContent": MessageLookupByLibrary.simpleMessage( + "To the maximum extent permitted by applicable law, neither the developers nor any contributor shall be liable for any direct, indirect, incidental, special, punitive, or consequential damages arising from the use of or inability to use the Software, including but not limited to data loss, device damage, network failures, business interruption, lost profits, or any resulting legal dispute, even if advised of the possibility of such damages.", + ), + "disclaimerLiabilityTitle": MessageLookupByLibrary.simpleMessage( + "Limitation of liability", + ), + "disclaimerLicenseContent": MessageLookupByLibrary.simpleMessage( + "The Software is open source under the GPL-3.0 license. You may use, modify, and distribute it freely as long as you comply with that license, which requires derivative works to be released under GPL-3.0 as well and the original copyright notices to be kept.\n\nThird-party components in the Software, including the Clash.Meta core, follow their own licenses. The original authors are not responsible for any issue arising from modified or redistributed versions.", + ), + "disclaimerLicenseTitle": MessageLookupByLibrary.simpleMessage( + "Open-source license", + ), + "disclaimerPrivacyContent": MessageLookupByLibrary.simpleMessage( + "The Software does not collect or upload your subscription URLs, node details, configuration content, visited websites, connection records, traffic content, or logs. This data stays on your device and the developers have no access to it.\n\nThe Software only reaches the network when you use a feature that needs it, such as fetching the subscription URL you provided when updating a profile, or contacting GitHub when checking for updates.\n\nThe desktop versions (Windows, macOS, Linux) include no analytics or crash reporting service. The Android version includes the following two Google Firebase services to improve stability:", + ), + "disclaimerPrivacyTitle": MessageLookupByLibrary.simpleMessage( + "Data collection and privacy", + ), + "disclaimerResponsibilityContent": MessageLookupByLibrary.simpleMessage( + "You are responsible for making sure that using the Software is lawful where you live, and you alone bear the legal responsibility for everything you do with it and its consequences.\n\nThe subscriptions, nodes, and configurations you import are your own choice. Whether their source is lawful, their content is safe, and their service is reliable is a matter between you and their providers.", + ), + "disclaimerResponsibilityTitle": MessageLookupByLibrary.simpleMessage( + "Your responsibility", + ), + "disclaimerSoftwareContent": MessageLookupByLibrary.simpleMessage( + "The Software is an open-source network proxy client built on the Clash.Meta (mihomo) core. It only provides local tooling such as configuration management, rule-based routing, and traffic forwarding.\n\nThe Software itself does not provide any proxy server, node, subscription, or network access service, and has no partnership, agency, or guarantee relationship with any provider of such services.", + ), + "disclaimerSoftwareTitle": MessageLookupByLibrary.simpleMessage( + "Nature of the software", + ), + "disclaimerThirdPartyContent": MessageLookupByLibrary.simpleMessage( + "Subscription links, configuration files, rule sets, scripts, external resources, and external links are all provided by third parties. The developers cannot and do not review or guarantee their legality, accuracy, security, or availability.\n\nAny data leak, financial loss, account ban, or other loss caused by third-party content is to be settled between you and the third party; the developers bear no responsibility for it.", + ), + "disclaimerThirdPartyTitle": MessageLookupByLibrary.simpleMessage( + "Third-party content", + ), + "disclaimerUsageContent": MessageLookupByLibrary.simpleMessage( + "The Software is intended only for non-commercial uses such as learning, exchange, and technical research. Using it for any commercial purpose is strictly prohibited, including but not limited to paid distribution, bundled sales, use as part of a commercial service, or doing business in the name of the Software. Any commercial activity is unrelated to the Software and its developers.\n\nUsing the Software for anything that violates the laws and regulations of your country or region is strictly prohibited, including but not limited to bypassing lawfully imposed network access restrictions, spreading illegal content, launching network attacks, or infringing the lawful rights of others.", + ), + "disclaimerUsageTitle": MessageLookupByLibrary.simpleMessage( + "Restrictions on use", + ), + "disclaimerWarrantyContent": MessageLookupByLibrary.simpleMessage( + "The Software is provided \"as is\" and \"as available\", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, non-infringement, uninterrupted availability, freedom from errors, or freedom from security vulnerabilities.\n\nThe developers do not guarantee that the Software will meet your needs or that it will run without interruption or error.", + ), + "disclaimerWarrantyTitle": MessageLookupByLibrary.simpleMessage( + "No warranty", ), "disconnected": MessageLookupByLibrary.simpleMessage("Disconnected"), "discoverNewVersion": MessageLookupByLibrary.simpleMessage( "New version found", ), - "dnsDesc": MessageLookupByLibrary.simpleMessage( - "Update DNS-related settings", - ), "dnsHijacking": MessageLookupByLibrary.simpleMessage("DNS hijacking"), "dnsMode": MessageLookupByLibrary.simpleMessage("DNS mode"), + "dnsQueries": MessageLookupByLibrary.simpleMessage("DNS queries"), + "docked": MessageLookupByLibrary.simpleMessage("Docked"), "domain": MessageLookupByLibrary.simpleMessage("Domain"), "download": MessageLookupByLibrary.simpleMessage("Download"), "edit": MessageLookupByLibrary.simpleMessage("Edit"), @@ -412,10 +578,14 @@ class MessageLookup extends MessageLookupByLibrary { "editProxyGroup": MessageLookupByLibrary.simpleMessage("Edit proxy group"), "editRule": MessageLookupByLibrary.simpleMessage("Edit rule"), "editSsid": MessageLookupByLibrary.simpleMessage("Edit SSID"), - "emptyTip": m7, + "editorUnavailable": MessageLookupByLibrary.simpleMessage( + "Editor unavailable", + ), + "emptyTip": m8, "en": MessageLookupByLibrary.simpleMessage("English"), + "enabled": MessageLookupByLibrary.simpleMessage("Enabled"), "entries": MessageLookupByLibrary.simpleMessage(" entries"), - "entriesCount": m8, + "error": MessageLookupByLibrary.simpleMessage("Error"), "exclude": MessageLookupByLibrary.simpleMessage("Hide from recent tasks"), "excludeDesc": MessageLookupByLibrary.simpleMessage( "Hide the app from recent tasks while it is in the background", @@ -444,14 +614,20 @@ class MessageLookup extends MessageLookupByLibrary { "externalControllerDesc": MessageLookupByLibrary.simpleMessage( "When enabled, the Clash core can be controlled on port 9090", ), - "externalFetch": MessageLookupByLibrary.simpleMessage("External fetch"), "externalLink": MessageLookupByLibrary.simpleMessage("External link"), + "fade": MessageLookupByLibrary.simpleMessage("Fade"), "fakeipFilter": MessageLookupByLibrary.simpleMessage("Fake-IP filter"), - "fakeipRange": MessageLookupByLibrary.simpleMessage("Fake-IP range"), - "fallback": MessageLookupByLibrary.simpleMessage("Fallback"), - "fallbackDesc": MessageLookupByLibrary.simpleMessage( - "Usually an overseas DNS", + "fakeipFilterMode": MessageLookupByLibrary.simpleMessage( + "Fake-IP filter mode", ), + "fakeipFilterModeDesc": MessageLookupByLibrary.simpleMessage( + "blacklist excludes matches, whitelist fakes only matches, rule matches as rules", + ), + "fakeipRange": MessageLookupByLibrary.simpleMessage("Fake-IP range"), + "fakeipRange6": MessageLookupByLibrary.simpleMessage( + "Fake-IP range (IPv6)", + ), + "fakeipTtl": MessageLookupByLibrary.simpleMessage("Fake-IP TTL"), "fallbackFilter": MessageLookupByLibrary.simpleMessage("Fallback filter"), "fidelityScheme": MessageLookupByLibrary.simpleMessage("Fidelity"), "file": MessageLookupByLibrary.simpleMessage("File"), @@ -461,15 +637,16 @@ class MessageLookup extends MessageLookupByLibrary { "fileIsUpdate": MessageLookupByLibrary.simpleMessage( "The file has been modified. Save the changes?", ), + "filter": MessageLookupByLibrary.simpleMessage("Filter"), "findProcessMode": MessageLookupByLibrary.simpleMessage("Find process"), - "findProcessModeDesc": MessageLookupByLibrary.simpleMessage( - "Enabling causes some performance loss", - ), + "floating": MessageLookupByLibrary.simpleMessage("Floating"), "followProfile": MessageLookupByLibrary.simpleMessage("Follow profile"), + "followSystem": MessageLookupByLibrary.simpleMessage("Follow system"), "fontFamily": MessageLookupByLibrary.simpleMessage("Font family"), "forceRestartCoreTip": MessageLookupByLibrary.simpleMessage( "Are you sure you want to force restart the core?", ), + "format": MessageLookupByLibrary.simpleMessage("Format"), "fruitSaladScheme": MessageLookupByLibrary.simpleMessage("Fruit salad"), "general": MessageLookupByLibrary.simpleMessage("General"), "geoAutoUpdate": MessageLookupByLibrary.simpleMessage("Auto update"), @@ -486,10 +663,6 @@ class MessageLookup extends MessageLookupByLibrary { "geodataLoader": MessageLookupByLibrary.simpleMessage( "Geo low-memory mode", ), - "geodataLoaderDesc": MessageLookupByLibrary.simpleMessage( - "Use the low-memory Geo loader", - ), - "geoipCode": MessageLookupByLibrary.simpleMessage("GeoIP code"), "global": MessageLookupByLibrary.simpleMessage("Global"), "go": MessageLookupByLibrary.simpleMessage("Go"), "goDownload": MessageLookupByLibrary.simpleMessage("Download"), @@ -503,22 +676,36 @@ class MessageLookup extends MessageLookupByLibrary { "Helper service unavailable; TUN mode cannot be enabled. Reinstall FlClash to restore it.", ), "hideFromList": MessageLookupByLibrary.simpleMessage("Hide from list"), + "hideIp": MessageLookupByLibrary.simpleMessage("Hide IP"), "hidePassword": MessageLookupByLibrary.simpleMessage("Hide password"), + "hideTimeoutProxies": MessageLookupByLibrary.simpleMessage( + "Hide timed-out nodes", + ), + "hideTimeoutProxiesDesc": MessageLookupByLibrary.simpleMessage( + "Leave out nodes whose last delay test timed out", + ), "host": MessageLookupByLibrary.simpleMessage("Host"), - "hostsDesc": MessageLookupByLibrary.simpleMessage("Append hosts"), - "hotkeyConflict": MessageLookupByLibrary.simpleMessage("Hotkey conflict"), + "hotkeyConflictWith": m12, + "hotkeyDesc": MessageLookupByLibrary.simpleMessage( + "Global hotkeys work even while the window is hidden. Tap an action to record its key combination.", + ), "hotkeyManagement": MessageLookupByLibrary.simpleMessage( "Hotkey management", ), - "hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage( - "Control the app with the keyboard", + "hotkeyNeedsModifier": m13, + "hotkeyNotSet": MessageLookupByLibrary.simpleMessage("Not set"), + "hotkeyUnavailable": MessageLookupByLibrary.simpleMessage( + "Not registered, it may be taken by another app", ), "hours": MessageLookupByLibrary.simpleMessage("hours"), - "hoursAgo": m12, - "hoursCount": m13, + "hoursAgo": m14, + "hoursCount": m15, "icon": MessageLookupByLibrary.simpleMessage("Icon"), "iconRecords": MessageLookupByLibrary.simpleMessage("Icon records"), "iconStyle": MessageLookupByLibrary.simpleMessage("Icon style"), + "iconStyleFilled": MessageLookupByLibrary.simpleMessage("Filled"), + "iconStyleHidden": MessageLookupByLibrary.simpleMessage("Hidden"), + "iconStylePlain": MessageLookupByLibrary.simpleMessage("Plain"), "iconUrl": MessageLookupByLibrary.simpleMessage("Icon URL"), "ignoreBatteryOptimization": MessageLookupByLibrary.simpleMessage( "Ignore battery optimization", @@ -538,13 +725,11 @@ class MessageLookup extends MessageLookupByLibrary { "Include all proxy providers", ), "includeAllProxyProvidersTip": MessageLookupByLibrary.simpleMessage( - "When enabled, the imported proxy providers are overridden", + "When enabled, the group takes every proxy provider of this profile: the subscription\'s own, plus the profiles and app proxy providers any proxy group uses", ), "infiniteTime": MessageLookupByLibrary.simpleMessage("Never expires"), "init": MessageLookupByLibrary.simpleMessage("Init"), - "inputCorrectHotkey": MessageLookupByLibrary.simpleMessage( - "Please enter a valid hotkey", - ), + "initiator": MessageLookupByLibrary.simpleMessage("Initiator"), "inputProxyGroupName": MessageLookupByLibrary.simpleMessage( "Enter the proxy group name", ), @@ -581,17 +766,58 @@ class MessageLookup extends MessageLookupByLibrary { "invalidBackupFile": MessageLookupByLibrary.simpleMessage( "Invalid backup file", ), - "invalidPolicy": m14, - "invalidProxy": m15, - "invalidProxyProvider": m16, - "invalidSubRule": m17, - "ipcidr": MessageLookupByLibrary.simpleMessage("IP/CIDR"), + "invalidDscpContent": MessageLookupByLibrary.simpleMessage( + "A DSCP mark cannot exceed 63", + ), + "invalidNetworkContent": MessageLookupByLibrary.simpleMessage( + "Only tcp or udp is supported", + ), + "invalidPolicy": m16, + "invalidProfileQrcode": MessageLookupByLibrary.simpleMessage( + "This QR code doesn\'t contain a profile link", + ), + "invalidProxy": m17, + "invalidProxyProvider": m18, + "invalidRangeContent": MessageLookupByLibrary.simpleMessage( + "Enter numbers or ranges such as 80 or 8000-9000, separated by /", + ), + "invalidRuleSet": m19, + "invalidSubRule": m20, + "ipAddress": MessageLookupByLibrary.simpleMessage("IP address"), + "ipAsn": MessageLookupByLibrary.simpleMessage("ASN"), + "ipFlagAbuser": MessageLookupByLibrary.simpleMessage("Abuse history"), + "ipFlagProxy": MessageLookupByLibrary.simpleMessage("Proxy"), + "ipFlagTor": MessageLookupByLibrary.simpleMessage("Tor"), + "ipFlagVpn": MessageLookupByLibrary.simpleMessage("VPN"), + "ipFlags": MessageLookupByLibrary.simpleMessage("Flags"), + "ipOrganization": MessageLookupByLibrary.simpleMessage("Organization"), + "ipQualityFailed": MessageLookupByLibrary.simpleMessage( + "Couldn\'t determine the IP type", + ), + "ipQualityGood": MessageLookupByLibrary.simpleMessage("Good"), + "ipQualityLevel": MessageLookupByLibrary.simpleMessage("Level"), + "ipQualityNormal": MessageLookupByLibrary.simpleMessage("Normal"), + "ipQualityRetry": MessageLookupByLibrary.simpleMessage("Check again"), + "ipQualityRisky": MessageLookupByLibrary.simpleMessage("Risky"), + "ipQualitySource": MessageLookupByLibrary.simpleMessage("Answered by"), + "ipQualitySources": MessageLookupByLibrary.simpleMessage("Sources"), + "ipSourceIpMismatch": MessageLookupByLibrary.simpleMessage( + "Different outbound IP", + ), + "ipSourceNoType": MessageLookupByLibrary.simpleMessage("No type"), + "ipSourceRateLimited": MessageLookupByLibrary.simpleMessage("Rate limited"), + "ipType": MessageLookupByLibrary.simpleMessage("Type"), + "ipTypeBusiness": MessageLookupByLibrary.simpleMessage("Business"), + "ipTypeHosting": MessageLookupByLibrary.simpleMessage("Data center"), + "ipTypeMobile": MessageLookupByLibrary.simpleMessage("Mobile network"), + "ipTypeResidential": MessageLookupByLibrary.simpleMessage("Residential"), "ipv6Desc": MessageLookupByLibrary.simpleMessage( "When enabled, IPv6 traffic can be received", ), "ipv6InboundDesc": MessageLookupByLibrary.simpleMessage( "Allow IPv6 inbound", ), + "ipv6Timeout": MessageLookupByLibrary.simpleMessage("IPv6 timeout (ms)"), "ja": MessageLookupByLibrary.simpleMessage("Japanese"), "justNow": MessageLookupByLibrary.simpleMessage("Just now"), "keepAliveIntervalDesc": MessageLookupByLibrary.simpleMessage( @@ -607,13 +833,17 @@ class MessageLookup extends MessageLookupByLibrary { ), "layout": MessageLookupByLibrary.simpleMessage("Layout"), "light": MessageLookupByLibrary.simpleMessage("Light"), + "lineIssueTip": m21, + "lineWrap": MessageLookupByLibrary.simpleMessage("Word wrap"), "list": MessageLookupByLibrary.simpleMessage("List"), "listen": MessageLookupByLibrary.simpleMessage("Listen"), - "loading": MessageLookupByLibrary.simpleMessage("Loading..."), - "local": MessageLookupByLibrary.simpleMessage("Local"), - "localBackupDesc": MessageLookupByLibrary.simpleMessage( - "Back up data locally", + "listenRoutingMark": MessageLookupByLibrary.simpleMessage( + "Listen routing mark", ), + "listenRoutingMarkDesc": MessageLookupByLibrary.simpleMessage("Linux only"), + "liveConnections": MessageLookupByLibrary.simpleMessage("Live connections"), + "loading": MessageLookupByLibrary.simpleMessage("Loading…"), + "local": MessageLookupByLibrary.simpleMessage("Local"), "locationPermission": MessageLookupByLibrary.simpleMessage( "Location permission", ), @@ -623,7 +853,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationPermissionDesc": MessageLookupByLibrary.simpleMessage( "The system requires location permission to read the Wi-Fi name. On Android choose \"Allow all the time\", otherwise the Wi-Fi name cannot be read while the app is in the background.", ), - "locationPermissionGuide": m18, + "locationPermissionGuide": m22, "locationPermissionRequired": MessageLookupByLibrary.simpleMessage( "Location permission required", ), @@ -634,23 +864,39 @@ class MessageLookup extends MessageLookupByLibrary { "Disabling hides the log entry point", ), "logs": MessageLookupByLibrary.simpleMessage("Logs"), - "logsDesc": MessageLookupByLibrary.simpleMessage("Captured log records"), - "logsTest": MessageLookupByLibrary.simpleMessage("Logs test"), - "loopback": MessageLookupByLibrary.simpleMessage("Loopback unlock tool"), - "loopbackDesc": MessageLookupByLibrary.simpleMessage( - "Used for UWP loopback exemption", + "logsAndDiagnostics": MessageLookupByLibrary.simpleMessage( + "Logs and diagnostics", ), + "logsTest": MessageLookupByLibrary.simpleMessage("Logs test"), + "loopback": MessageLookupByLibrary.simpleMessage("UWP loopback exemption"), "loose": MessageLookupByLibrary.simpleMessage("Loose"), "matchSourceIp": MessageLookupByLibrary.simpleMessage("Match source IP"), "matchTarget": MessageLookupByLibrary.simpleMessage("MATCH-TARGET"), - "matchTargetDesc": MessageLookupByLibrary.simpleMessage( - "Where rules targeting MATCH-TARGET go. Defaults to the target of the final MATCH rule in this profile.", - ), - "matchTargetTitle": MessageLookupByLibrary.simpleMessage("Match target"), "maxFailedTimes": MessageLookupByLibrary.simpleMessage("Max failures"), - "maxLengthTip": m19, + "maxLengthTip": m23, "maximize": MessageLookupByLibrary.simpleMessage("Maximize"), + "memoryAppResident": MessageLookupByLibrary.simpleMessage( + "Resident memory", + ), + "memoryAppShared": MessageLookupByLibrary.simpleMessage("App & shared"), + "memoryCoreHeapIdle": MessageLookupByLibrary.simpleMessage("Heap idle"), + "memoryCoreHeapInuse": MessageLookupByLibrary.simpleMessage("Heap in use"), + "memoryCoreNotRunning": MessageLookupByLibrary.simpleMessage( + "Core is not running", + ), + "memoryCoreRuntime": MessageLookupByLibrary.simpleMessage( + "Runtime overhead", + ), + "memoryCoreStack": MessageLookupByLibrary.simpleMessage("Goroutine stacks"), + "memoryEstimateDesc": MessageLookupByLibrary.simpleMessage( + "Estimated from process resident memory; it may differ from what the system reports.", + ), + "memoryEstimateSharedDesc": MessageLookupByLibrary.simpleMessage( + "The Core runs inside the app process. Its share is estimated from runtime stats, and the rest counts as app and shared memory.", + ), "memoryInfo": MessageLookupByLibrary.simpleMessage("Memory info"), + "memoryReleased": MessageLookupByLibrary.simpleMessage("Memory released"), + "memoryReleasedSize": m24, "messageTest": MessageLookupByLibrary.simpleMessage("Message test"), "messageTestTip": MessageLookupByLibrary.simpleMessage( "This is a message.", @@ -658,45 +904,47 @@ class MessageLookup extends MessageLookupByLibrary { "min": MessageLookupByLibrary.simpleMessage("Minimal"), "minimize": MessageLookupByLibrary.simpleMessage("Minimize"), "minimizeOnExit": MessageLookupByLibrary.simpleMessage("Minimize on exit"), - "minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage( - "Override the default system exit behavior", - ), - "minutesAgo": m20, + "minutesAgo": m25, "mixedPort": MessageLookupByLibrary.simpleMessage("Mixed port"), "mode": MessageLookupByLibrary.simpleMessage("Mode"), "monochromeScheme": MessageLookupByLibrary.simpleMessage("Monochrome"), - "monthsAgo": m21, + "monthsAgo": m26, "more": MessageLookupByLibrary.simpleMessage("More"), - "multipleValuesTip": MessageLookupByLibrary.simpleMessage( - "Separate multiple values with commas", - ), "name": MessageLookupByLibrary.simpleMessage("Name"), - "nameserver": MessageLookupByLibrary.simpleMessage("Nameserver"), - "nameserverDesc": MessageLookupByLibrary.simpleMessage( - "Used to resolve domains", - ), - "nameserverPolicy": MessageLookupByLibrary.simpleMessage( - "Nameserver policy", - ), - "nameserverPolicyDesc": MessageLookupByLibrary.simpleMessage( - "Specify the nameserver policy for matching domains", - ), + "navigationBarStyle": MessageLookupByLibrary.simpleMessage("Bottom bar"), "network": MessageLookupByLibrary.simpleMessage("Network"), - "networkDesc": MessageLookupByLibrary.simpleMessage( - "Adjust network-related settings", + "networkAccessDeniedError": m27, + "networkBadResponseError": m28, + "networkCancelledError": MessageLookupByLibrary.simpleMessage( + "The request was cancelled", + ), + "networkConnectionError": MessageLookupByLibrary.simpleMessage( + "Couldn\'t connect to the server. Check your network connection or proxy settings", ), "networkDetection": MessageLookupByLibrary.simpleMessage( "Network detection", ), - "networkException": MessageLookupByLibrary.simpleMessage( - "Network error, please check your connection and try again", + "networkHostLookupError": MessageLookupByLibrary.simpleMessage( + "Couldn\'t resolve the server address. Check that the URL is correct and DNS is working", ), + "networkNotFoundError": m29, + "networkRateLimitedError": MessageLookupByLibrary.simpleMessage( + "Too many requests (HTTP 429). Wait a moment and try again", + ), + "networkRequestFailed": m30, + "networkServerError": m31, "networkSpeed": MessageLookupByLibrary.simpleMessage("Network speed"), + "networkTimeoutError": MessageLookupByLibrary.simpleMessage( + "The request timed out. Check your network or proxy, then try again", + ), + "networkTlsError": MessageLookupByLibrary.simpleMessage( + "Secure connection failed. The server\'s certificate may be invalid, or the connection is being intercepted", + ), "networkType": MessageLookupByLibrary.simpleMessage("Network type"), "neutralScheme": MessageLookupByLibrary.simpleMessage("Neutral"), "nextMatch": MessageLookupByLibrary.simpleMessage("Next match"), + "no": MessageLookupByLibrary.simpleMessage("No"), "noData": MessageLookupByLibrary.simpleMessage("No data"), - "noHotKey": MessageLookupByLibrary.simpleMessage("No hotkeys yet"), "noInfo": MessageLookupByLibrary.simpleMessage("No info"), "noLongerRemind": MessageLookupByLibrary.simpleMessage( "Don\'t remind me again", @@ -708,43 +956,66 @@ class MessageLookup extends MessageLookupByLibrary { "noResolveHostname": MessageLookupByLibrary.simpleMessage( "Don\'t resolve hostname", ), + "noSearchResults": MessageLookupByLibrary.simpleMessage( + "No matching results", + ), + "nonTextProviderFile": MessageLookupByLibrary.simpleMessage( + "This external resource is not a text file", + ), "none": MessageLookupByLibrary.simpleMessage("None"), "notSelectedTip": MessageLookupByLibrary.simpleMessage( "The current proxy group cannot be selected", ), - "nullProfileDesc": MessageLookupByLibrary.simpleMessage( - "No profiles yet, please add one first", + "ntpInterval": MessageLookupByLibrary.simpleMessage( + "Sync interval (minutes)", ), - "nullTip": m22, - "numberTip": m23, + "ntpStatusDesc": MessageLookupByLibrary.simpleMessage( + "Take the time from an NTP server instead of the system clock", + ), + "nullProfileDesc": MessageLookupByLibrary.simpleMessage( + "Add a profile to get started", + ), + "nullTip": m32, + "numberTip": m33, "onDemand": MessageLookupByLibrary.simpleMessage("On demand"), "onDemandDesc": MessageLookupByLibrary.simpleMessage( "Configure the app\'s running state for specific scenarios", ), - "onlyIcon": MessageLookupByLibrary.simpleMessage("Icon only"), "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage( "Only count proxy traffic", ), - "onlyStatisticsProxyDesc": MessageLookupByLibrary.simpleMessage( - "When enabled, only proxy traffic is counted", - ), "optional": MessageLookupByLibrary.simpleMessage("Optional"), "options": MessageLookupByLibrary.simpleMessage("Options"), "other": MessageLookupByLibrary.simpleMessage("Other"), "otherContributors": MessageLookupByLibrary.simpleMessage( "Other contributors", ), + "outboundIp": MessageLookupByLibrary.simpleMessage("Outbound IP"), "outboundMode": MessageLookupByLibrary.simpleMessage("Outbound mode"), "override": MessageLookupByLibrary.simpleMessage("Override"), "overrideDns": MessageLookupByLibrary.simpleMessage("Override DNS"), - "overrideDnsDesc": MessageLookupByLibrary.simpleMessage( - "When enabled, the DNS options in the profile are overridden", - ), + "overrideEntries": MessageLookupByLibrary.simpleMessage("Override entries"), "overrideMode": MessageLookupByLibrary.simpleMessage("Override mode"), + "overrideNtp": MessageLookupByLibrary.simpleMessage("Override NTP"), "overrideScript": MessageLookupByLibrary.simpleMessage("Override script"), + "overwriteIssueCoreRejected": m34, + "overwriteIssueDuplicateName": m35, + "overwriteIssueEmptyName": MessageLookupByLibrary.simpleMessage( + "The name is empty", + ), + "overwriteIssueGroupLoop": m36, + "overwriteIssueMissingProviders": m37, + "overwriteIssueMissingProxies": m38, + "overwriteIssueNoProxySource": MessageLookupByLibrary.simpleMessage( + "No proxies or proxy providers are selected, so the core rejects this group", + ), + "overwriteIssueProviderShadowed": m39, + "overwriteIssueReservedName": m40, + "overwriteIssueSubscriptionGroupMissingProxies": m41, + "overwriteIssuesSummary": m42, "overwriteTypeCustom": MessageLookupByLibrary.simpleMessage("Custom"), "overwriteTypeCustomDesc": MessageLookupByLibrary.simpleMessage( - "Custom mode: fully customize proxy groups and rules", + "Custom mode: fully customize proxies, proxy groups and rules", ), "palette": MessageLookupByLibrary.simpleMessage("Palette"), "password": MessageLookupByLibrary.simpleMessage("Password"), @@ -764,12 +1035,11 @@ class MessageLookup extends MessageLookupByLibrary { "portConflictTip": MessageLookupByLibrary.simpleMessage( "Please enter a different port", ), - "portTip": m24, - "preferH3Desc": MessageLookupByLibrary.simpleMessage( - "Prefer HTTP/3 for DoH", - ), + "portTip": m43, "prerequisites": MessageLookupByLibrary.simpleMessage("Prerequisites"), - "pressKeyboard": MessageLookupByLibrary.simpleMessage("Please press a key"), + "pressKeyboard": MessageLookupByLibrary.simpleMessage( + "Press a key combination", + ), "preview": MessageLookupByLibrary.simpleMessage("Preview"), "previousMatch": MessageLookupByLibrary.simpleMessage("Previous match"), "process": MessageLookupByLibrary.simpleMessage("Process"), @@ -795,35 +1065,34 @@ class MessageLookup extends MessageLookupByLibrary { "profiles": MessageLookupByLibrary.simpleMessage("Profiles"), "profilesSort": MessageLookupByLibrary.simpleMessage("Sort profiles"), "project": MessageLookupByLibrary.simpleMessage("Project"), + "providerInUse": m44, + "providerRenameShadowed": m45, + "providerSourceSubscription": MessageLookupByLibrary.simpleMessage( + "Subscription", + ), + "providerUrlTip": MessageLookupByLibrary.simpleMessage( + "Only remote providers are supported", + ), "providers": MessageLookupByLibrary.simpleMessage("External resources"), "proxies": MessageLookupByLibrary.simpleMessage("Proxies"), - "proxiesCount": m25, + "proxiesCount": m46, "proxiesEmpty": MessageLookupByLibrary.simpleMessage("Proxies are empty"), "proxyChains": MessageLookupByLibrary.simpleMessage("Proxy chain"), - "proxyDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "The selected proxies are abnormal", + "proxyDefinition": MessageLookupByLibrary.simpleMessage( + "Full configuration", + ), + "proxyDefinitionNotMap": MessageLookupByLibrary.simpleMessage( + "The configuration must be a YAML mapping with a name and a type", ), "proxyFilter": MessageLookupByLibrary.simpleMessage("Proxy filter"), "proxyGroup": MessageLookupByLibrary.simpleMessage("Proxy group"), - "proxyGroupDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "The current proxy group is abnormal", - ), "proxyGroupEmpty": MessageLookupByLibrary.simpleMessage( "Proxy group is empty", ), "proxyGroupNameDuplicate": MessageLookupByLibrary.simpleMessage( "Duplicate proxy group name", ), - "proxyGroupNameEmpty": MessageLookupByLibrary.simpleMessage( - "Proxy group name cannot be empty", - ), - "proxyNameserver": MessageLookupByLibrary.simpleMessage("Proxy nameserver"), - "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage( - "Used to resolve proxy node domains", - ), - "proxyProviderDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "The selected proxy providers are abnormal", - ), + "proxyNode": MessageLookupByLibrary.simpleMessage("Proxy node"), "proxyProviders": MessageLookupByLibrary.simpleMessage("Proxy providers"), "proxyProvidersEmpty": MessageLookupByLibrary.simpleMessage( "Proxy providers are empty", @@ -833,27 +1102,35 @@ class MessageLookup extends MessageLookupByLibrary { ), "proxyType": MessageLookupByLibrary.simpleMessage("Proxy type"), "pruneCache": MessageLookupByLibrary.simpleMessage("Prune cache"), + "pureBlack": MessageLookupByLibrary.simpleMessage("Pure black"), "pureBlackMode": MessageLookupByLibrary.simpleMessage("Pure black mode"), "qrcode": MessageLookupByLibrary.simpleMessage("QR code"), "qrcodeDesc": MessageLookupByLibrary.simpleMessage( "Scan a QR code to obtain a profile", ), + "quickAdd": MessageLookupByLibrary.simpleMessage("Quick add"), + "quickEdit": MessageLookupByLibrary.simpleMessage("Quick edit"), "quickFill": MessageLookupByLibrary.simpleMessage("Quick fill"), "rainbowScheme": MessageLookupByLibrary.simpleMessage("Rainbow"), + "recentRequests": MessageLookupByLibrary.simpleMessage("Recent requests"), + "recordType": MessageLookupByLibrary.simpleMessage("Record type"), "redirPort": MessageLookupByLibrary.simpleMessage("Redir port"), "redo": MessageLookupByLibrary.simpleMessage("Redo"), - "remote": MessageLookupByLibrary.simpleMessage("Remote"), - "remoteBackupDesc": MessageLookupByLibrary.simpleMessage( - "Back up data to WebDAV", + "releaseMemory": MessageLookupByLibrary.simpleMessage("Release memory"), + "releaseMemoryFailed": MessageLookupByLibrary.simpleMessage( + "Failed to release memory", ), + "remote": MessageLookupByLibrary.simpleMessage("Remote"), "remoteDestination": MessageLookupByLibrary.simpleMessage( "Remote destination", ), "remove": MessageLookupByLibrary.simpleMessage("Remove"), + "replace": MessageLookupByLibrary.simpleMessage("Replace"), + "replaceAll": MessageLookupByLibrary.simpleMessage("Replace all"), "request": MessageLookupByLibrary.simpleMessage("Request"), "requests": MessageLookupByLibrary.simpleMessage("Requests"), - "requestsDesc": MessageLookupByLibrary.simpleMessage( - "View recent request records", + "requestsAndUpdates": MessageLookupByLibrary.simpleMessage( + "Requests and updates", ), "reset": MessageLookupByLibrary.simpleMessage("Reset"), "resetPageChangesTip": MessageLookupByLibrary.simpleMessage( @@ -863,26 +1140,17 @@ class MessageLookup extends MessageLookupByLibrary { "Are you sure you want to reset?", ), "resources": MessageLookupByLibrary.simpleMessage("Resources"), - "resourcesDesc": MessageLookupByLibrary.simpleMessage( - "Information about external resources", - ), "respectRules": MessageLookupByLibrary.simpleMessage("Respect rules"), "respectRulesDesc": MessageLookupByLibrary.simpleMessage( - "DNS connections follow rules; requires proxy-server-nameserver", + "DNS connections follow rules; requires Proxy Server Nameserver", ), + "responseCode": MessageLookupByLibrary.simpleMessage("Response code"), "restart": MessageLookupByLibrary.simpleMessage("Restart"), "restartCoreTip": MessageLookupByLibrary.simpleMessage( "Are you sure you want to restart the core?", ), "restore": MessageLookupByLibrary.simpleMessage("Restore"), "restoreAllData": MessageLookupByLibrary.simpleMessage("Restore all data"), - "restoreException": MessageLookupByLibrary.simpleMessage("Restore error"), - "restoreFromFileDesc": MessageLookupByLibrary.simpleMessage( - "Restore data from a file", - ), - "restoreFromWebDAVDesc": MessageLookupByLibrary.simpleMessage( - "Restore data from WebDAV", - ), "restoreOnlyConfig": MessageLookupByLibrary.simpleMessage( "Restore profiles only", ), @@ -894,10 +1162,8 @@ class MessageLookup extends MessageLookupByLibrary { "restoreSuccess": MessageLookupByLibrary.simpleMessage( "Restore successful", ), + "retry": MessageLookupByLibrary.simpleMessage("Retry"), "routeAddress": MessageLookupByLibrary.simpleMessage("Route addresses"), - "routeAddressDesc": MessageLookupByLibrary.simpleMessage( - "Configure the listened route addresses", - ), "routeMode": MessageLookupByLibrary.simpleMessage("Route mode"), "routeModeBypassPrivate": MessageLookupByLibrary.simpleMessage( "Bypass private addresses", @@ -1016,10 +1282,25 @@ class MessageLookup extends MessageLookupByLibrary { ), "ruleEmpty": MessageLookupByLibrary.simpleMessage("Rule is empty"), "ruleName": MessageLookupByLibrary.simpleMessage("Rule name"), + "rulePresetBittorrentDirect": MessageLookupByLibrary.simpleMessage( + "BitTorrent direct", + ), + "rulePresetBlockDot": MessageLookupByLibrary.simpleMessage( + "Block DNS over TLS", + ), + "rulePresetBlockQuic": MessageLookupByLibrary.simpleMessage("Block QUIC"), + "rulePresetBlockStun": MessageLookupByLibrary.simpleMessage("Block STUN"), + "rulePresetLanDirect": MessageLookupByLibrary.simpleMessage("LAN direct"), + "rulePresetSystemServicesDirect": MessageLookupByLibrary.simpleMessage( + "Apple and Microsoft direct", + ), + "ruleProviders": MessageLookupByLibrary.simpleMessage("Rule providers"), "ruleSet": MessageLookupByLibrary.simpleMessage("Rule set"), "ruleTarget": MessageLookupByLibrary.simpleMessage("Rule target"), "rules": MessageLookupByLibrary.simpleMessage("Rules"), - "rulesCount": m26, + "rulesCount": m47, + "safeMode": MessageLookupByLibrary.simpleMessage("Safe mode"), + "safeModeAppTitle": m48, "save": MessageLookupByLibrary.simpleMessage("Save"), "saveChanges": MessageLookupByLibrary.simpleMessage("Save the changes?"), "script": MessageLookupByLibrary.simpleMessage("Script"), @@ -1031,11 +1312,8 @@ class MessageLookup extends MessageLookupByLibrary { ), "search": MessageLookupByLibrary.simpleMessage("Search"), "seconds": MessageLookupByLibrary.simpleMessage("seconds"), - "secondsCount": m27, + "secondsCount": m49, "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), - "selectMatchTarget": MessageLookupByLibrary.simpleMessage( - "Select MATCH-TARGET", - ), "selectProxies": MessageLookupByLibrary.simpleMessage("Select proxies"), "selectProxyProviders": MessageLookupByLibrary.simpleMessage( "Select proxy providers", @@ -1050,7 +1328,31 @@ class MessageLookup extends MessageLookupByLibrary { "Please select a sub-rule", ), "selected": MessageLookupByLibrary.simpleMessage("Selected"), - "selectedCountTitle": m28, + "selectedCountTitle": m50, + "server": MessageLookupByLibrary.simpleMessage("Server"), + "serviceAvailable": MessageLookupByLibrary.simpleMessage("Available"), + "serviceBlocked": MessageLookupByLibrary.simpleMessage("Blocked"), + "serviceCheck": MessageLookupByLibrary.simpleMessage("Check"), + "serviceCheckAll": MessageLookupByLibrary.simpleMessage("Check all"), + "serviceCheckedAt": m51, + "serviceComingSoon": MessageLookupByLibrary.simpleMessage("Coming soon"), + "serviceDisallowedIsp": MessageLookupByLibrary.simpleMessage( + "Disallowed ISP", + ), + "serviceFailed": MessageLookupByLibrary.simpleMessage("Check failed"), + "serviceManage": MessageLookupByLibrary.simpleMessage("Manage services"), + "serviceOriginalsOnly": MessageLookupByLibrary.simpleMessage( + "Originals only", + ), + "servicePending": MessageLookupByLibrary.simpleMessage("Not checked"), + "serviceRestricted": MessageLookupByLibrary.simpleMessage( + "Access restricted", + ), + "serviceStatus": MessageLookupByLibrary.simpleMessage("Service status"), + "serviceUnavailable": MessageLookupByLibrary.simpleMessage("Unavailable"), + "serviceUnsupportedRegion": MessageLookupByLibrary.simpleMessage( + "Region not supported", + ), "settings": MessageLookupByLibrary.simpleMessage("Settings"), "show": MessageLookupByLibrary.simpleMessage("Show"), "showLess": MessageLookupByLibrary.simpleMessage("Collapse"), @@ -1058,16 +1360,20 @@ class MessageLookup extends MessageLookupByLibrary { "showNotificationStopAction": MessageLookupByLibrary.simpleMessage( "Stop button in notification", ), - "showNotificationStopActionDesc": MessageLookupByLibrary.simpleMessage( - "Show a stop button on the persistent notification. Turn it off if your system keeps the notification expanded because of it", - ), "showPassword": MessageLookupByLibrary.simpleMessage("Show password"), "shrink": MessageLookupByLibrary.simpleMessage("Compact"), + "sidebarBlur": MessageLookupByLibrary.simpleMessage("Sidebar blur"), + "sidebarBlurDesc": MessageLookupByLibrary.simpleMessage( + "Show the blurred desktop behind the window through the sidebar", + ), "silentLaunch": MessageLookupByLibrary.simpleMessage("Silent launch"), "silentLaunchDesc": MessageLookupByLibrary.simpleMessage( - "Start in the background", + "Start without showing the window", ), + "singleAdd": MessageLookupByLibrary.simpleMessage("Single add"), + "singleValueTip": m52, "size": MessageLookupByLibrary.simpleMessage("Size"), + "slide": MessageLookupByLibrary.simpleMessage("Slide"), "socksPort": MessageLookupByLibrary.simpleMessage("SOCKS port"), "sort": MessageLookupByLibrary.simpleMessage("Sort"), "source": MessageLookupByLibrary.simpleMessage("Source"), @@ -1086,13 +1392,20 @@ class MessageLookup extends MessageLookupByLibrary { "Standard mode: overrides the basic configuration and offers simple rule additions", ), "start": MessageLookupByLibrary.simpleMessage("Start"), - "startVpn": MessageLookupByLibrary.simpleMessage("Starting VPN..."), + "startFromScratch": MessageLookupByLibrary.simpleMessage( + "Start from scratch", + ), + "startVpn": MessageLookupByLibrary.simpleMessage("Starting VPN…"), + "startupAndBackground": MessageLookupByLibrary.simpleMessage( + "Startup and background", + ), "status": MessageLookupByLibrary.simpleMessage("Status"), "statusDesc": MessageLookupByLibrary.simpleMessage( "When disabled, the system DNS is used", ), "stop": MessageLookupByLibrary.simpleMessage("Stop"), - "stopVpn": MessageLookupByLibrary.simpleMessage("Stopping VPN..."), + "stopVpn": MessageLookupByLibrary.simpleMessage("Stopping VPN…"), + "strategy": MessageLookupByLibrary.simpleMessage("Strategy"), "style": MessageLookupByLibrary.simpleMessage("Style"), "subRule": MessageLookupByLibrary.simpleMessage("Sub-rule"), "subRuleEmpty": MessageLookupByLibrary.simpleMessage("Sub-rule is empty"), @@ -1103,28 +1416,22 @@ class MessageLookup extends MessageLookupByLibrary { "subscriptionInfo": MessageLookupByLibrary.simpleMessage( "Subscription info", ), - "suspended": MessageLookupByLibrary.simpleMessage("Suspended..."), + "suspended": MessageLookupByLibrary.simpleMessage("Suspended…"), "sync": MessageLookupByLibrary.simpleMessage("Sync"), "system": MessageLookupByLibrary.simpleMessage("System"), "systemApp": MessageLookupByLibrary.simpleMessage("System apps"), "systemProxy": MessageLookupByLibrary.simpleMessage("System proxy"), - "systemProxyDesc": MessageLookupByLibrary.simpleMessage( - "Set the system proxy", - ), "tab": MessageLookupByLibrary.simpleMessage("Tab"), "tabAnimation": MessageLookupByLibrary.simpleMessage("Tab animation"), - "tabAnimationDesc": MessageLookupByLibrary.simpleMessage( - "Only effective in mobile view", - ), "tapToAuthorize": MessageLookupByLibrary.simpleMessage("Tap to authorize"), "tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP concurrent"), - "tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage( - "Allow concurrent TCP connections", - ), "testInterval": MessageLookupByLibrary.simpleMessage("Test interval"), "testUrl": MessageLookupByLibrary.simpleMessage("Test URL"), "testWhenUsed": MessageLookupByLibrary.simpleMessage("Test when used"), "textScale": MessageLookupByLibrary.simpleMessage("Text scaling"), + "textScalePreview": MessageLookupByLibrary.simpleMessage( + "Text in the app will look like this", + ), "theme": MessageLookupByLibrary.simpleMessage("Theme"), "themeColor": MessageLookupByLibrary.simpleMessage("Theme color"), "themeDesc": MessageLookupByLibrary.simpleMessage( @@ -1136,10 +1443,11 @@ class MessageLookup extends MessageLookupByLibrary { "timeout": MessageLookupByLibrary.simpleMessage("Timeout"), "tip": MessageLookupByLibrary.simpleMessage("Tip"), "toggle": MessageLookupByLibrary.simpleMessage("Toggle"), - "toggleLabel": MessageLookupByLibrary.simpleMessage("Toggle labels"), + "tolerance": MessageLookupByLibrary.simpleMessage("Tolerance"), "tonalSpotScheme": MessageLookupByLibrary.simpleMessage("Tonal spot"), "tools": MessageLookupByLibrary.simpleMessage("Tools"), "torch": MessageLookupByLibrary.simpleMessage("Flashlight"), + "total": MessageLookupByLibrary.simpleMessage("Total"), "totalTraffic": MessageLookupByLibrary.simpleMessage("Total traffic"), "tproxyPort": MessageLookupByLibrary.simpleMessage("TProxy port"), "trafficUsage": MessageLookupByLibrary.simpleMessage("Traffic usage"), @@ -1151,9 +1459,6 @@ class MessageLookup extends MessageLookupByLibrary { "turnOn": MessageLookupByLibrary.simpleMessage("Turn on"), "undo": MessageLookupByLibrary.simpleMessage("Undo"), "unifiedDelay": MessageLookupByLibrary.simpleMessage("Unified delay"), - "unifiedDelayDesc": MessageLookupByLibrary.simpleMessage( - "Remove extra delays such as handshakes", - ), "unknown": MessageLookupByLibrary.simpleMessage("Unknown"), "unknownNetworkError": MessageLookupByLibrary.simpleMessage( "Unknown network error", @@ -1167,7 +1472,7 @@ class MessageLookup extends MessageLookupByLibrary { "urlDesc": MessageLookupByLibrary.simpleMessage( "Obtain a profile from a URL", ), - "urlTip": m29, + "urlTip": m53, "useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"), "usedTraffic": MessageLookupByLibrary.simpleMessage("Used traffic"), @@ -1188,7 +1493,12 @@ class MessageLookup extends MessageLookupByLibrary { "WebDAV configuration", ), "whitelistMode": MessageLookupByLibrary.simpleMessage("Whitelist mode"), - "yearsAgo": m30, + "writeToSystem": MessageLookupByLibrary.simpleMessage("Write to system"), + "writeToSystemDesc": MessageLookupByLibrary.simpleMessage( + "Also set the system clock; Android ignores it", + ), + "yearsAgo": m54, + "yes": MessageLookupByLibrary.simpleMessage("Yes"), "zhCN": MessageLookupByLibrary.simpleMessage("Simplified Chinese"), }; } diff --git a/lib/l10n/intl/messages_ja.dart b/lib/l10n/intl/messages_ja.dart index 189a8abf..85b4d694 100644 --- a/lib/l10n/intl/messages_ja.dart +++ b/lib/l10n/intl/messages_ja.dart @@ -20,25 +20,25 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ja'; - static String m0(code) => + static String m0(count, skipped) => "${count}件を追加、${skipped}件は既存のためスキップ"; + + static String m1(code) => "Windows が FlClashCore.exe の実行を拒否しました(エラー ${code})。スマート アプリ コントロールや AppLocker などのアプリ制御ポリシーは未署名のプログラムをブロックします。ポリシーで FlClash を許可するか、ポリシーを無効にしてから再試行してください。"; - static String m1(name) => + static String m2(name) => "アプリの起動が2回連続で完了しませんでした。クラッシュループを断ち切るため、プロファイル ${name} の選択を解除し、今回の自動セットアップをスキップしました。いつでも選択し直せます。"; - static String m2(url) => "${url} からプロファイルを作成しますか?"; + static String m3(url) => "${url} からプロファイルを作成しますか?"; - static String m3(count) => "${count} 日前"; + static String m4(count) => "${count} 日前"; - static String m4(label) => "選択した${label}を削除してもよろしいですか?"; + static String m5(label) => "選択した${label}を削除してもよろしいですか?"; - static String m5(label) => "この${label}を削除してもよろしいですか?"; + static String m6(label) => "この${label}を削除してもよろしいですか?"; - static String m6(label) => "${label}の詳細"; + static String m7(label) => "${label}の詳細"; - static String m7(label) => "${label}は空にできません"; - - static String m8(count) => "${count} 件"; + static String m8(label) => "${label}は空にできません"; static String m9(label) => "${label}はすでに存在します"; @@ -46,44 +46,98 @@ class MessageLookup extends MessageLookupByLibrary { static String m11(name) => "${name} を更新しました"; - static String m12(count) => "${count} 時間前"; + static String m12(action) => "「${action}」で使用中です。保存するとこちらに移動します。"; - static String m13(count) => "${count} 時間"; + static String m13(modifiers) => "${modifiers} のいずれかを含めてください"; - static String m14(target) => "${target} は無効なポリシーです"; + static String m14(count) => "${count} 時間前"; - static String m15(proxyName) => "${proxyName} は無効なプロキシです"; + static String m15(count) => "${count} 時間"; - static String m16(providerName) => "${providerName} は無効なプロキシプロバイダーです"; + static String m16(target) => "${target} は無効なポリシーです"; - static String m17(subRule) => "${subRule} は無効な SUB_RULE です"; + static String m17(proxyName) => "${proxyName} は無効なプロキシです"; - static String m18(appName) => + static String m18(providerName) => "${providerName} は無効なプロキシプロバイダーです"; + + static String m19(ruleSet) => "${ruleSet} は無効なルールセットです"; + + static String m20(subRule) => "${subRule} は無効な SUB_RULE です"; + + static String m21(line, message) => "${line}行目:${message}"; + + static String m22(appName) => "1. システム設定 > プライバシーとセキュリティ を開く\n2. 位置情報サービス を選択\n3. リストで ${appName} を見つけてチェックを入れる\n\n設定が完了したらアプリに戻ると、通常どおり使用できます。ご協力ありがとうございます。"; - static String m19(label, max) => "${label}は最大${max}文字です"; + static String m23(label, max) => "${label}は最大${max}文字です"; - static String m20(count) => "${count} 分前"; + static String m24(size) => "${size} を解放しました"; - static String m21(count) => "${count} か月前"; + static String m25(count) => "${count} 分前"; - static String m22(label) => "${label}はまだありません"; + static String m26(count) => "${count} か月前"; - static String m23(label) => "${label}は数値である必要があります"; + static String m27(code) => + "サーバーがアクセスを拒否しました(HTTP ${code})。リンクの期限切れか、認証情報が誤っている可能性があります"; - static String m24(label) => "${label} は 1024〜49151 の範囲で指定してください"; + static String m28(code) => "サーバーがリクエストを拒否しました(HTTP ${code})"; - static String m25(count) => "プロキシ ${count} 件"; + static String m29(code) => + "このアドレスには何も見つかりませんでした(HTTP ${code})。URL が正しいか確認してください"; - static String m26(count) => "ルール ${count} 件"; + static String m30(detail) => "ネットワークリクエストに失敗しました:${detail}"; - static String m27(count) => "${count} 秒"; + static String m31(code) => "サーバーで問題が発生しました(HTTP ${code})。しばらくしてから再試行してください"; - static String m28(count) => "${count} 件選択中"; + static String m32(label) => "${label}はまだありません"; - static String m29(label) => "${label}はURLである必要があります"; + static String m33(label) => "${label}は数値である必要があります"; - static String m30(count) => "${count} 年前"; + static String m34(message) => "コアがこのプロキシを解析できません:${message}"; + + static String m35(name) => "名前 ${name} は他のプロキシまたはプロキシグループで使用されています"; + + static String m36(path) => "プロキシグループが循環参照しています:${path}"; + + static String m37(names) => "次のプロキシプロバイダーは存在しません:${names}"; + + static String m38(names) => "次のプロキシまたはポリシーは存在しません:${names}"; + + static String m39(name) => + "プロファイルに ${name} という名前のプロバイダーが既にあるため、同名のアプリレベルのプロバイダーは使用されません。名前を変更してください"; + + static String m40(name) => "${name} は組み込みポリシー名のため使用できません"; + + static String m41(names) => + "プロファイル自身のプロキシグループが、カスタムプロキシに含まれないプロキシを参照しています:${names}"; + + static String m42(count) => "${count} 件に問題があり、上書きの適用に失敗する可能性があります"; + + static String m43(label) => "${label} は 1024〜49151 の範囲で指定してください"; + + static String m44(label, profiles) => + "${label} は ${profiles} のカスタムプロキシグループまたはルールでまだ使用されています。先にそこから外してください"; + + static String m45(profiles, label) => + "${profiles} のサブスクリプションには既に ${label} があるため、名前を変えるとそちらが使われます。別の名前にしてください"; + + static String m46(count) => "プロキシ ${count} 件"; + + static String m47(count) => "ルール ${count} 件"; + + static String m48(appName) => "${appName}(セーフモード)"; + + static String m49(count) => "${count} 秒"; + + static String m50(count) => "${count} 件選択中"; + + static String m51(time) => "${time} に検査"; + + static String m52(label) => "${label}は1項目のみ指定できます"; + + static String m53(label) => "${label}はURLである必要があります"; + + static String m54(count) => "${count} 年前"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -104,12 +158,19 @@ class MessageLookup extends MessageLookupByLibrary { "accessControlSettings": MessageLookupByLibrary.simpleMessage("アクセス制御の設定"), "account": MessageLookupByLibrary.simpleMessage("アカウント"), "action": MessageLookupByLibrary.simpleMessage("アクション"), + "actionDelayTest": MessageLookupByLibrary.simpleMessage("すべての遅延をテスト"), + "actionDirectMode": MessageLookupByLibrary.simpleMessage("ダイレクトモード"), + "actionGlobalMode": MessageLookupByLibrary.simpleMessage("グローバルモード"), "actionMode": MessageLookupByLibrary.simpleMessage("モード切替"), "actionProxy": MessageLookupByLibrary.simpleMessage("システムプロキシ"), + "actionRuleMode": MessageLookupByLibrary.simpleMessage("ルールモード"), "actionStart": MessageLookupByLibrary.simpleMessage("開始/停止"), "actionTun": MessageLookupByLibrary.simpleMessage("TUN"), + "actionUpdateProfiles": MessageLookupByLibrary.simpleMessage("プロファイルを更新"), "actionView": MessageLookupByLibrary.simpleMessage("表示/非表示"), "add": MessageLookupByLibrary.simpleMessage("追加"), + "addCustomProxy": MessageLookupByLibrary.simpleMessage("プロキシを追加"), + "addOverrideEntry": MessageLookupByLibrary.simpleMessage("上書き項目を追加"), "addProfile": MessageLookupByLibrary.simpleMessage("プロファイルを追加"), "addProxies": MessageLookupByLibrary.simpleMessage("プロキシを追加"), "addProxyGroup": MessageLookupByLibrary.simpleMessage("プロキシグループを追加"), @@ -125,24 +186,22 @@ class MessageLookup extends MessageLookupByLibrary { "有効なWebDAVアドレスを入力してください", ), "advancedConfig": MessageLookupByLibrary.simpleMessage("詳細設定"), - "advancedConfigDesc": MessageLookupByLibrary.simpleMessage("多彩な設定項目を提供します"), + "advancedConfigDesc": MessageLookupByLibrary.simpleMessage( + "ネットワーク、DNS、追加ルール、スクリプト", + ), "agree": MessageLookupByLibrary.simpleMessage("同意する"), "allowBypass": MessageLookupByLibrary.simpleMessage("アプリによるVPNバイパスを許可"), - "allowBypassDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、一部のアプリがVPNをバイパスできます", - ), "allowLan": MessageLookupByLibrary.simpleMessage("LANプロキシ"), - "allowLanDesc": MessageLookupByLibrary.simpleMessage("LAN経由でのプロキシ利用を許可します"), + "answers": MessageLookupByLibrary.simpleMessage("応答"), "app": MessageLookupByLibrary.simpleMessage("アプリ"), "appAccessControl": MessageLookupByLibrary.simpleMessage("アプリアクセス制御"), + "appIconDesign": MessageLookupByLibrary.simpleMessage("アプリアイコンのデザイン"), + "appProviderShadowed": MessageLookupByLibrary.simpleMessage( + "同名のアプリ側の項目はここでは使われません", + ), + "appProxyProviders": MessageLookupByLibrary.simpleMessage("アプリのプロキシプロバイダー"), + "appRuleProviders": MessageLookupByLibrary.simpleMessage("アプリのルールプロバイダー"), "appendSystemDns": MessageLookupByLibrary.simpleMessage("システムDNSを追加"), - "appendSystemDnsTip": MessageLookupByLibrary.simpleMessage( - "設定にシステムDNSを強制的に追加します", - ), - "application": MessageLookupByLibrary.simpleMessage("アプリケーション"), - "applicationDesc": MessageLookupByLibrary.simpleMessage( - "アプリケーション関連の設定を変更します", - ), "authentication": MessageLookupByLibrary.simpleMessage("認証"), "authenticationDesc": MessageLookupByLibrary.simpleMessage( "ローカルプロキシポートに認証を要求し、他のアプリによる無断利用を防ぎます", @@ -154,9 +213,6 @@ class MessageLookup extends MessageLookupByLibrary { "authorized": MessageLookupByLibrary.simpleMessage("許可済み"), "auto": MessageLookupByLibrary.simpleMessage("自動"), "autoCheckUpdate": MessageLookupByLibrary.simpleMessage("更新の自動チェック"), - "autoCheckUpdateDesc": MessageLookupByLibrary.simpleMessage( - "アプリ起動時に更新を自動的にチェックします", - ), "autoCloseConnections": MessageLookupByLibrary.simpleMessage("接続を自動的に閉じる"), "autoCloseConnectionsDesc": MessageLookupByLibrary.simpleMessage( "ノードの切り替え後、接続を自動的に閉じます", @@ -174,17 +230,24 @@ class MessageLookup extends MessageLookupByLibrary { "backupAndRestoreDesc": MessageLookupByLibrary.simpleMessage( "WebDAVまたはファイルでデータを同期します", ), + "backupFromNewerVersion": MessageLookupByLibrary.simpleMessage( + "このバックアップは新しいバージョンのアプリで作成されています。アプリを更新してから復元してください", + ), "backupSuccess": MessageLookupByLibrary.simpleMessage("バックアップが完了しました"), - "basicConfig": MessageLookupByLibrary.simpleMessage("基本設定"), - "basicConfigDesc": MessageLookupByLibrary.simpleMessage("基本設定をグローバルに変更します"), "basicInfo": MessageLookupByLibrary.simpleMessage("基本情報"), "basicStrategy": MessageLookupByLibrary.simpleMessage("基本ポリシー"), + "batchAdd": MessageLookupByLibrary.simpleMessage("一括追加"), + "batchListInputTip": MessageLookupByLibrary.simpleMessage( + "1行に1項目、またはカンマ区切りで入力してください", + ), + "batchMapInputTip": MessageLookupByLibrary.simpleMessage( + "1行に1件、キーと値はスペースで区切ってください", + ), + "batchPreviewTip": m0, "batteryOptimizationDesc": MessageLookupByLibrary.simpleMessage( "バックグラウンドでの動作を維持するため、このアプリの電池の最適化を無効にしてください。タップすると設定を開きます。", ), - "batteryOptimizationStatusTip": MessageLookupByLibrary.simpleMessage( - "システムの制限により、実行中は電池の最適化の状態を正しく取得できません", - ), + "behavior": MessageLookupByLibrary.simpleMessage("動作"), "bind": MessageLookupByLibrary.simpleMessage("連携"), "blacklistMode": MessageLookupByLibrary.simpleMessage("ブラックリストモード"), "blockConnection": MessageLookupByLibrary.simpleMessage("接続をブロック"), @@ -192,9 +255,19 @@ class MessageLookup extends MessageLookupByLibrary { "bypassDomainDesc": MessageLookupByLibrary.simpleMessage( "システムプロキシが有効な場合のみ適用されます", ), + "cache": MessageLookupByLibrary.simpleMessage("キャッシュ"), + "cacheAlgorithm": MessageLookupByLibrary.simpleMessage("キャッシュアルゴリズム"), "cacheCorrupt": MessageLookupByLibrary.simpleMessage( "キャッシュが破損しています。クリアしますか?", ), + "cacheMaxSize": MessageLookupByLibrary.simpleMessage("キャッシュサイズ"), + "cameraPermissionDesc": MessageLookupByLibrary.simpleMessage( + "QRコードをスキャンするには、システム設定でカメラへのアクセスを許可するか、アルバムからQRコード画像を選択してください。", + ), + "cameraPermissionRequired": MessageLookupByLibrary.simpleMessage( + "カメラの権限が必要です", + ), + "cameraUnavailable": MessageLookupByLibrary.simpleMessage("カメラを使用できません"), "cancel": MessageLookupByLibrary.simpleMessage("キャンセル"), "cancelSelectAll": MessageLookupByLibrary.simpleMessage("すべて選択解除"), "changeProxyFailedTip": MessageLookupByLibrary.simpleMessage( @@ -241,10 +314,9 @@ class MessageLookup extends MessageLookupByLibrary { "確定すると既存のデータを上書きします", ), "connected": MessageLookupByLibrary.simpleMessage("接続済み"), - "connecting": MessageLookupByLibrary.simpleMessage("接続中..."), + "connecting": MessageLookupByLibrary.simpleMessage("接続中…"), "connection": MessageLookupByLibrary.simpleMessage("接続"), "connections": MessageLookupByLibrary.simpleMessage("接続"), - "connectionsDesc": MessageLookupByLibrary.simpleMessage("現在の接続データを表示します"), "connectivity": MessageLookupByLibrary.simpleMessage("接続状態:"), "content": MessageLookupByLibrary.simpleMessage("内容"), "contentNotEmpty": MessageLookupByLibrary.simpleMessage("内容は空にできません"), @@ -257,24 +329,26 @@ class MessageLookup extends MessageLookupByLibrary { "copyLink": MessageLookupByLibrary.simpleMessage("リンクをコピー"), "copySuccess": MessageLookupByLibrary.simpleMessage("コピーしました"), "core": MessageLookupByLibrary.simpleMessage("コア"), - "coreBlockedByPolicyTip": m0, + "coreBlockedByPolicyTip": m1, "coreBlockedBySmartAppControlTip": MessageLookupByLibrary.simpleMessage( "Windows のスマート アプリ コントロールが、署名されていない FlClashCore.exe をブロックしました。Windows セキュリティ → アプリとブラウザーの制御 → スマート アプリ コントロールの設定で「オフ」を選び、FlClash を再起動してください。一度オフにすると、Windows を再インストールしない限り再度オンにはできません。", ), "coreStatus": MessageLookupByLibrary.simpleMessage("コアの状態"), "country": MessageLookupByLibrary.simpleMessage("地域"), "crashDetected": MessageLookupByLibrary.simpleMessage("クラッシュを検出しました"), - "crashDetectedTip": m1, + "crashDetectedTip": m2, "crashTest": MessageLookupByLibrary.simpleMessage("クラッシュテスト"), "crashlytics": MessageLookupByLibrary.simpleMessage("クラッシュ分析"), "crashlyticsTip": MessageLookupByLibrary.simpleMessage( "有効にすると、アプリのクラッシュ時に機密情報を含まないクラッシュログを自動的にアップロードします", ), "create": MessageLookupByLibrary.simpleMessage("作成"), - "createProfile": MessageLookupByLibrary.simpleMessage("プロファイルを作成"), - "createProfileFromUrlTip": m2, + "createProfileFromUrlTip": m3, "creationTime": MessageLookupByLibrary.simpleMessage("作成日時"), "custom": MessageLookupByLibrary.simpleMessage("カスタム"), + "customProxiesEmpty": MessageLookupByLibrary.simpleMessage( + "カスタムプロキシがないため、プロファイル自身のプロキシを使用します", + ), "cut": MessageLookupByLibrary.simpleMessage("切り取り"), "dark": MessageLookupByLibrary.simpleMessage("ダーク"), "dashboard": MessageLookupByLibrary.simpleMessage("ダッシュボード"), @@ -288,24 +362,20 @@ class MessageLookup extends MessageLookupByLibrary { "databaseWriteFailedTip": MessageLookupByLibrary.simpleMessage( "変更の保存に失敗したため、元に戻しました", ), - "daysAgo": m3, - "defaultNameserver": MessageLookupByLibrary.simpleMessage("デフォルトネームサーバー"), - "defaultNameserverDesc": MessageLookupByLibrary.simpleMessage( - "DNSサーバーの名前解決に使用します", - ), + "daysAgo": m4, "defaultText": MessageLookupByLibrary.simpleMessage("デフォルト"), "delay": MessageLookupByLibrary.simpleMessage("遅延"), "delayTest": MessageLookupByLibrary.simpleMessage("遅延テスト"), "delete": MessageLookupByLibrary.simpleMessage("削除"), - "deleteMultipTip": m4, - "deleteTip": m5, + "deleteMultipTip": m5, + "deleteTip": m6, "desc": MessageLookupByLibrary.simpleMessage( "ClashMetaベースのマルチプラットフォーム対応プロキシクライアント。シンプルで使いやすく、オープンソースで広告もありません。", ), "destination": MessageLookupByLibrary.simpleMessage("宛先"), "destinationGeoIP": MessageLookupByLibrary.simpleMessage("宛先GeoIP"), "destinationIPASN": MessageLookupByLibrary.simpleMessage("宛先IP ASN"), - "details": m6, + "details": m7, "detectionTip": MessageLookupByLibrary.simpleMessage( "サードパーティAPIに依存しているため、参考値です", ), @@ -313,19 +383,98 @@ class MessageLookup extends MessageLookupByLibrary { "developerModeEnableTip": MessageLookupByLibrary.simpleMessage( "開発者モードが有効になりました。", ), + "dialerProxy": MessageLookupByLibrary.simpleMessage("ダイヤラープロキシ"), + "dialerProxyDesc": MessageLookupByLibrary.simpleMessage( + "NTPサーバーへの接続に使用するアウトバウンド", + ), "direct": MessageLookupByLibrary.simpleMessage("ダイレクト"), "disableUDP": MessageLookupByLibrary.simpleMessage("UDPを無効化"), + "disabled": MessageLookupByLibrary.simpleMessage("無効"), + "discardChanges": MessageLookupByLibrary.simpleMessage("変更を破棄しますか?"), "disclaimer": MessageLookupByLibrary.simpleMessage("免責事項"), - "disclaimerDesc": MessageLookupByLibrary.simpleMessage( - "本ソフトウェアは、学習・交流や研究などの非商用目的でのみ使用できます。商用目的での使用は固く禁じられています。いかなる商業行為も本ソフトウェアとは一切関係ありません。", + "disclaimerAcceptContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアをインストール、複製または使用した時点で、本声明のすべての内容を読み、同意したものとみなされます。いずれかの条項に同意いただけない場合は、直ちに使用を中止し、本ソフトウェアをアンインストールしてください。", ), + "disclaimerAcceptTitle": MessageLookupByLibrary.simpleMessage("声明への同意"), + "disclaimerAnalyticsContent": MessageLookupByLibrary.simpleMessage( + "Firebase により基本的なアプリ利用統計が自動的に収集されます。\n\n収集内容:初回起動、アプリの起動とセッション時間、アプリの更新などの基本イベント、アプリインスタンス ID、端末のモデル、OS のバージョン、システム言語、および IP アドレスから推定される国または地域レベルのおおよその位置情報。\n\n目的:アクティブな端末数、バージョン分布、OS の互換性を把握するためにのみ使用します。開発者はこれらのデータを広告に使用したり、販売したり、サブスクリプションや設定と関連付けたりすることはありません。", + ), + "disclaimerAnalyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Analytics(利用統計)", + ), + "disclaimerAndroidOnly": MessageLookupByLibrary.simpleMessage("Android のみ"), + "disclaimerChangesContent": MessageLookupByLibrary.simpleMessage( + "開発者はバージョンの更新に伴い本声明を変更することがあり、変更内容は新しいバージョンの公開とともに効力を生じます。更新後も本ソフトウェアを引き続き使用した場合、変更後の声明に同意したものとみなされます。", + ), + "disclaimerChangesTitle": MessageLookupByLibrary.simpleMessage("本声明の変更"), + "disclaimerCrashlyticsContent": MessageLookupByLibrary.simpleMessage( + "アプリがクラッシュした際に、クラッシュレポートを自動的に送信します。\n\n収集内容:クラッシュのスタックトレースとエラー情報、発生日時、アプリのバージョンとビルド番号、端末のメーカーとモデル、Android のバージョン、画面の向き、空きメモリと空きストレージ、root 化の有無、およびインストール時に生成され再インストールでリセットされるランダムなインストール ID。\n\n目的:クラッシュの特定と修正のためにのみ使用します。\n\n「ツール > 一般 > クラッシュ分析」からいつでもオフにできます。", + ), + "disclaimerCrashlyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Crashlytics(クラッシュ分析)", + ), + "disclaimerDataProcessingContent": MessageLookupByLibrary.simpleMessage( + "これらのデータは Google が代わりに処理・保存し、お住まいの国または地域外(米国など)のサーバーに転送される場合があり、Google のプライバシーポリシーおよび Firebase のプライバシーとセキュリティに関する説明に従って取り扱われます。クラッシュレポートは最大 90 日間保存され、統計データは Firebase の既定の保存ポリシーに従って保存されます。", + ), + "disclaimerDesc": MessageLookupByLibrary.simpleMessage( + "FlClash(以下「本ソフトウェア」)をご利用になる前に、本声明の内容をよくお読みになり、十分にご理解ください。「同意する」をタップすると、以下のすべての条項を読み、理解し、承諾したものとみなされます。同意いただけない場合は「終了」をタップし、本ソフトウェアの使用を中止してください。", + ), + "disclaimerFirebasePrivacy": MessageLookupByLibrary.simpleMessage( + "Firebase のプライバシーとセキュリティ", + ), + "disclaimerGooglePrivacy": MessageLookupByLibrary.simpleMessage( + "Google プライバシーポリシー", + ), + "disclaimerLiabilityContent": MessageLookupByLibrary.simpleMessage( + "適用法で認められる最大限の範囲において、開発者およびすべての貢献者は、本ソフトウェアの使用または使用不能に起因する直接的、間接的、偶発的、特別、懲罰的または結果的な損害(データの消失、機器の損傷、ネットワーク障害、業務の中断、逸失利益、およびそれに起因する法的紛争を含むがこれらに限らない)について、その可能性を知らされていた場合であっても、一切責任を負いません。", + ), + "disclaimerLiabilityTitle": MessageLookupByLibrary.simpleMessage("責任の制限"), + "disclaimerLicenseContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアは GPL-3.0 ライセンスのもとでオープンソースとして公開されています。同ライセンスを遵守する限り、自由に使用、改変、再配布できますが、派生物も GPL-3.0 で公開し、原著作者の著作権表示を保持する必要があります。\n\n本ソフトウェアに含まれるサードパーティのコンポーネント(Clash.Meta コアを含む)は、それぞれのライセンスに従います。改変版や再配布版に起因する問題について、原著作者は責任を負いません。", + ), + "disclaimerLicenseTitle": MessageLookupByLibrary.simpleMessage( + "オープンソースライセンス", + ), + "disclaimerPrivacyContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアは、サブスクリプション URL、ノード情報、設定内容、閲覧したウェブサイト、接続記録、通信内容、ログを収集またはアップロードしません。これらのデータは端末内にのみ保存され、開発者がアクセスすることはできません。\n\n本ソフトウェアが外部ネットワークにアクセスするのは、プロファイル更新時に指定されたサブスクリプション URL へアクセスする場合や、アップデート確認時に GitHub へアクセスする場合など、該当する機能を使用したときのみです。\n\nデスクトップ版(Windows、macOS、Linux)には、統計やクラッシュレポートのサービスは一切組み込まれていません。Android 版には、安定性向上のため以下の 2 つの Google Firebase サービスが組み込まれています。", + ), + "disclaimerPrivacyTitle": MessageLookupByLibrary.simpleMessage( + "データ収集とプライバシー", + ), + "disclaimerResponsibilityContent": MessageLookupByLibrary.simpleMessage( + "お住まいの国または地域で本ソフトウェアの使用が合法であることはご自身で確認する必要があり、本ソフトウェアを使用したすべての行為とその結果について、ご自身が単独で法的責任を負います。\n\nインポートするサブスクリプション、ノード、設定はご自身の判断で選択したものです。その出所の適法性、内容の安全性、サービスの安定性については、利用者と各提供者の間で解決してください。", + ), + "disclaimerResponsibilityTitle": MessageLookupByLibrary.simpleMessage( + "利用者の責任", + ), + "disclaimerSoftwareContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアは Clash.Meta(mihomo)コアをベースとしたオープンソースのネットワークプロキシクライアントであり、設定管理、ルールによる振り分け、トラフィック転送などのローカルツール機能のみを提供します。\n\n本ソフトウェア自体は、プロキシサーバー、ノード、サブスクリプション、ネットワーク接続サービスを一切提供しておらず、それらのサービス提供者と提携、代理、保証の関係はありません。", + ), + "disclaimerSoftwareTitle": MessageLookupByLibrary.simpleMessage( + "ソフトウェアの性質", + ), + "disclaimerThirdPartyContent": MessageLookupByLibrary.simpleMessage( + "サブスクリプションリンク、設定ファイル、ルールセット、スクリプト、外部リソース、外部リンクはすべて第三者が提供するものであり、開発者はその適法性、正確性、安全性、可用性を審査または保証することはできず、また行いません。\n\nサードパーティのコンテンツの使用に起因する情報漏えい、財産上の損失、アカウント停止その他の損失は、利用者と第三者の間で解決するものとし、開発者は一切責任を負いません。", + ), + "disclaimerThirdPartyTitle": MessageLookupByLibrary.simpleMessage( + "サードパーティのコンテンツ", + ), + "disclaimerUsageContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアは学習、交流、技術研究などの非商用目的でのみ使用できます。有償配布、抱き合わせ販売、商用サービスの一部としての利用、本ソフトウェアの名義での事業活動など、あらゆる商用目的での使用を固く禁じます。いかなる商業行為も本ソフトウェアおよび開発者とは一切関係ありません。\n\nお住まいの国または地域の法令に違反する目的での使用を固く禁じます。これには、法に基づくネットワークアクセス制限の回避、違法情報の拡散、サイバー攻撃、他者の権利の侵害などが含まれますが、これらに限りません。", + ), + "disclaimerUsageTitle": MessageLookupByLibrary.simpleMessage("使用の制限"), + "disclaimerWarrantyContent": MessageLookupByLibrary.simpleMessage( + "本ソフトウェアは「現状のまま」かつ「提供可能な範囲で」提供され、商品性、特定目的への適合性、非侵害、継続的な可用性、エラーやセキュリティ上の脆弱性がないことの保証を含め、明示または黙示を問わずいかなる保証も伴いません。\n\n開発者は、本ソフトウェアが利用者の要件を満たすこと、また中断やエラーなく動作することを保証しません。", + ), + "disclaimerWarrantyTitle": MessageLookupByLibrary.simpleMessage("無保証"), "disconnected": MessageLookupByLibrary.simpleMessage("切断済み"), "discoverNewVersion": MessageLookupByLibrary.simpleMessage( "新しいバージョンが見つかりました", ), - "dnsDesc": MessageLookupByLibrary.simpleMessage("DNS関連の設定を更新します"), "dnsHijacking": MessageLookupByLibrary.simpleMessage("DNSハイジャック"), "dnsMode": MessageLookupByLibrary.simpleMessage("DNSモード"), + "dnsQueries": MessageLookupByLibrary.simpleMessage("DNSクエリ"), + "docked": MessageLookupByLibrary.simpleMessage("固定"), "domain": MessageLookupByLibrary.simpleMessage("ドメイン"), "download": MessageLookupByLibrary.simpleMessage("ダウンロード"), "edit": MessageLookupByLibrary.simpleMessage("編集"), @@ -334,10 +483,12 @@ class MessageLookup extends MessageLookupByLibrary { "editProxyGroup": MessageLookupByLibrary.simpleMessage("プロキシグループを編集"), "editRule": MessageLookupByLibrary.simpleMessage("ルールを編集"), "editSsid": MessageLookupByLibrary.simpleMessage("SSIDを編集"), - "emptyTip": m7, + "editorUnavailable": MessageLookupByLibrary.simpleMessage("エディターを利用できません"), + "emptyTip": m8, "en": MessageLookupByLibrary.simpleMessage("英語"), + "enabled": MessageLookupByLibrary.simpleMessage("有効"), "entries": MessageLookupByLibrary.simpleMessage(" 件"), - "entriesCount": m8, + "error": MessageLookupByLibrary.simpleMessage("エラー"), "exclude": MessageLookupByLibrary.simpleMessage("最近のタスクから隠す"), "excludeDesc": MessageLookupByLibrary.simpleMessage( "バックグラウンド時に、最近のタスクからアプリを隠します", @@ -362,12 +513,16 @@ class MessageLookup extends MessageLookupByLibrary { "externalControllerDesc": MessageLookupByLibrary.simpleMessage( "有効にすると、ポート9090でClashコアを制御できます", ), - "externalFetch": MessageLookupByLibrary.simpleMessage("外部取得"), "externalLink": MessageLookupByLibrary.simpleMessage("外部リンク"), + "fade": MessageLookupByLibrary.simpleMessage("フェード"), "fakeipFilter": MessageLookupByLibrary.simpleMessage("Fake-IPフィルター"), + "fakeipFilterMode": MessageLookupByLibrary.simpleMessage("Fake-IPフィルターモード"), + "fakeipFilterModeDesc": MessageLookupByLibrary.simpleMessage( + "blacklistは一致を除外、whitelistは一致のみ、ruleはルールで判定", + ), "fakeipRange": MessageLookupByLibrary.simpleMessage("Fake-IP範囲"), - "fallback": MessageLookupByLibrary.simpleMessage("フォールバック"), - "fallbackDesc": MessageLookupByLibrary.simpleMessage("通常は国外のDNSを使用します"), + "fakeipRange6": MessageLookupByLibrary.simpleMessage("Fake-IP範囲(IPv6)"), + "fakeipTtl": MessageLookupByLibrary.simpleMessage("Fake-IP TTL"), "fallbackFilter": MessageLookupByLibrary.simpleMessage("フォールバックフィルター"), "fidelityScheme": MessageLookupByLibrary.simpleMessage("フィデリティ"), "file": MessageLookupByLibrary.simpleMessage("ファイル"), @@ -375,15 +530,16 @@ class MessageLookup extends MessageLookupByLibrary { "fileIsUpdate": MessageLookupByLibrary.simpleMessage( "ファイルが変更されています。変更を保存しますか?", ), + "filter": MessageLookupByLibrary.simpleMessage("フィルター"), "findProcessMode": MessageLookupByLibrary.simpleMessage("プロセス検出"), - "findProcessModeDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、パフォーマンスが多少低下します", - ), + "floating": MessageLookupByLibrary.simpleMessage("フローティング"), "followProfile": MessageLookupByLibrary.simpleMessage("プロファイルに従う"), + "followSystem": MessageLookupByLibrary.simpleMessage("システムに従う"), "fontFamily": MessageLookupByLibrary.simpleMessage("フォント"), "forceRestartCoreTip": MessageLookupByLibrary.simpleMessage( "コアを強制再起動してもよろしいですか?", ), + "format": MessageLookupByLibrary.simpleMessage("形式"), "fruitSaladScheme": MessageLookupByLibrary.simpleMessage("フルーツサラダ"), "general": MessageLookupByLibrary.simpleMessage("一般"), "geoAutoUpdate": MessageLookupByLibrary.simpleMessage("自動更新"), @@ -396,10 +552,6 @@ class MessageLookup extends MessageLookupByLibrary { "geoSkipped": m10, "geoUpdated": m11, "geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低メモリモード"), - "geodataLoaderDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、低メモリのGeoローダーを使用します", - ), - "geoipCode": MessageLookupByLibrary.simpleMessage("GeoIPコード"), "global": MessageLookupByLibrary.simpleMessage("グローバル"), "go": MessageLookupByLibrary.simpleMessage("開く"), "goDownload": MessageLookupByLibrary.simpleMessage("ダウンロードへ"), @@ -409,20 +561,34 @@ class MessageLookup extends MessageLookupByLibrary { "Helper サービスが利用できないため、TUN モードを有効にできません。FlClash を再インストールしてください。", ), "hideFromList": MessageLookupByLibrary.simpleMessage("リストから隠す"), + "hideIp": MessageLookupByLibrary.simpleMessage("IP を隠す"), "hidePassword": MessageLookupByLibrary.simpleMessage("パスワードを隠す"), + "hideTimeoutProxies": MessageLookupByLibrary.simpleMessage( + "タイムアウトしたノードを隠す", + ), + "hideTimeoutProxiesDesc": MessageLookupByLibrary.simpleMessage( + "前回の遅延テストがタイムアウトしたノードを表示しない", + ), "host": MessageLookupByLibrary.simpleMessage("ホスト"), - "hostsDesc": MessageLookupByLibrary.simpleMessage("Hostsを追加します"), - "hotkeyConflict": MessageLookupByLibrary.simpleMessage("ホットキーが競合しています"), + "hotkeyConflictWith": m12, + "hotkeyDesc": MessageLookupByLibrary.simpleMessage( + "グローバルホットキーはウィンドウが非表示でも有効です。アクションをタップしてキーの組み合わせを記録します。", + ), "hotkeyManagement": MessageLookupByLibrary.simpleMessage("ホットキー管理"), - "hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage( - "キーボードでアプリを操作します", + "hotkeyNeedsModifier": m13, + "hotkeyNotSet": MessageLookupByLibrary.simpleMessage("未設定"), + "hotkeyUnavailable": MessageLookupByLibrary.simpleMessage( + "登録できませんでした。他のアプリが使用している可能性があります", ), "hours": MessageLookupByLibrary.simpleMessage("時間"), - "hoursAgo": m12, - "hoursCount": m13, + "hoursAgo": m14, + "hoursCount": m15, "icon": MessageLookupByLibrary.simpleMessage("アイコン"), "iconRecords": MessageLookupByLibrary.simpleMessage("アイコン履歴"), "iconStyle": MessageLookupByLibrary.simpleMessage("アイコンスタイル"), + "iconStyleFilled": MessageLookupByLibrary.simpleMessage("背景あり"), + "iconStyleHidden": MessageLookupByLibrary.simpleMessage("非表示"), + "iconStylePlain": MessageLookupByLibrary.simpleMessage("背景なし"), "iconUrl": MessageLookupByLibrary.simpleMessage("アイコンURL"), "ignoreBatteryOptimization": MessageLookupByLibrary.simpleMessage( "電池の最適化を無視", @@ -440,13 +606,11 @@ class MessageLookup extends MessageLookupByLibrary { "すべてのプロキシプロバイダーを含める", ), "includeAllProxyProvidersTip": MessageLookupByLibrary.simpleMessage( - "有効にすると、取り込んだプロキシプロバイダーを上書きします", + "有効にすると、このプロファイルのすべてのプロキシプロバイダーを含めます。サブスクリプション自身のものに加え、いずれかのプロキシグループが使うプロファイルとアプリのプロキシプロバイダーも含みます", ), "infiniteTime": MessageLookupByLibrary.simpleMessage("無期限"), "init": MessageLookupByLibrary.simpleMessage("初期化"), - "inputCorrectHotkey": MessageLookupByLibrary.simpleMessage( - "正しいホットキーを入力してください", - ), + "initiator": MessageLookupByLibrary.simpleMessage("発信元"), "inputProxyGroupName": MessageLookupByLibrary.simpleMessage( "プロキシグループ名を入力してください", ), @@ -476,15 +640,56 @@ class MessageLookup extends MessageLookupByLibrary { "interval": MessageLookupByLibrary.simpleMessage("間隔"), "intranetIP": MessageLookupByLibrary.simpleMessage("イントラネットIP"), "invalidBackupFile": MessageLookupByLibrary.simpleMessage("無効なバックアップファイル"), - "invalidPolicy": m14, - "invalidProxy": m15, - "invalidProxyProvider": m16, - "invalidSubRule": m17, - "ipcidr": MessageLookupByLibrary.simpleMessage("IP/CIDR"), + "invalidDscpContent": MessageLookupByLibrary.simpleMessage( + "DSCP マークは 63 を超えられません", + ), + "invalidNetworkContent": MessageLookupByLibrary.simpleMessage( + "tcp または udp のみ対応しています", + ), + "invalidPolicy": m16, + "invalidProfileQrcode": MessageLookupByLibrary.simpleMessage( + "このQRコードにはプロファイルのリンクが含まれていません", + ), + "invalidProxy": m17, + "invalidProxyProvider": m18, + "invalidRangeContent": MessageLookupByLibrary.simpleMessage( + "80 や 8000-9000 のような数値または範囲を / 区切りで入力してください", + ), + "invalidRuleSet": m19, + "invalidSubRule": m20, + "ipAddress": MessageLookupByLibrary.simpleMessage("IP アドレス"), + "ipAsn": MessageLookupByLibrary.simpleMessage("ASN"), + "ipFlagAbuser": MessageLookupByLibrary.simpleMessage("不正利用の履歴"), + "ipFlagProxy": MessageLookupByLibrary.simpleMessage("プロキシ"), + "ipFlagTor": MessageLookupByLibrary.simpleMessage("Tor"), + "ipFlagVpn": MessageLookupByLibrary.simpleMessage("VPN"), + "ipFlags": MessageLookupByLibrary.simpleMessage("検出"), + "ipOrganization": MessageLookupByLibrary.simpleMessage("組織"), + "ipQualityFailed": MessageLookupByLibrary.simpleMessage( + "IP タイプを判定できませんでした", + ), + "ipQualityGood": MessageLookupByLibrary.simpleMessage("良好"), + "ipQualityLevel": MessageLookupByLibrary.simpleMessage("レベル"), + "ipQualityNormal": MessageLookupByLibrary.simpleMessage("普通"), + "ipQualityRetry": MessageLookupByLibrary.simpleMessage("再確認"), + "ipQualityRisky": MessageLookupByLibrary.simpleMessage("リスクあり"), + "ipQualitySource": MessageLookupByLibrary.simpleMessage("採用したソース"), + "ipQualitySources": MessageLookupByLibrary.simpleMessage("各ソース"), + "ipSourceIpMismatch": MessageLookupByLibrary.simpleMessage( + "アウトバウンド IP が不一致", + ), + "ipSourceNoType": MessageLookupByLibrary.simpleMessage("判定不可"), + "ipSourceRateLimited": MessageLookupByLibrary.simpleMessage("レート制限"), + "ipType": MessageLookupByLibrary.simpleMessage("タイプ"), + "ipTypeBusiness": MessageLookupByLibrary.simpleMessage("ビジネス"), + "ipTypeHosting": MessageLookupByLibrary.simpleMessage("データセンター"), + "ipTypeMobile": MessageLookupByLibrary.simpleMessage("モバイル回線"), + "ipTypeResidential": MessageLookupByLibrary.simpleMessage("住宅"), "ipv6Desc": MessageLookupByLibrary.simpleMessage( "有効にすると、IPv6トラフィックを受信できます", ), "ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("IPv6インバウンドを許可します"), + "ipv6Timeout": MessageLookupByLibrary.simpleMessage("IPv6タイムアウト(ms)"), "ja": MessageLookupByLibrary.simpleMessage("日本語"), "justNow": MessageLookupByLibrary.simpleMessage("たった今"), "keepAliveIntervalDesc": MessageLookupByLibrary.simpleMessage( @@ -498,13 +703,15 @@ class MessageLookup extends MessageLookupByLibrary { ), "layout": MessageLookupByLibrary.simpleMessage("レイアウト"), "light": MessageLookupByLibrary.simpleMessage("ライト"), + "lineIssueTip": m21, + "lineWrap": MessageLookupByLibrary.simpleMessage("折り返し"), "list": MessageLookupByLibrary.simpleMessage("リスト"), "listen": MessageLookupByLibrary.simpleMessage("リッスン"), - "loading": MessageLookupByLibrary.simpleMessage("読み込み中..."), + "listenRoutingMark": MessageLookupByLibrary.simpleMessage("リッスンのルーティングマーク"), + "listenRoutingMarkDesc": MessageLookupByLibrary.simpleMessage("Linuxのみ"), + "liveConnections": MessageLookupByLibrary.simpleMessage("リアルタイム接続"), + "loading": MessageLookupByLibrary.simpleMessage("読み込み中…"), "local": MessageLookupByLibrary.simpleMessage("ローカル"), - "localBackupDesc": MessageLookupByLibrary.simpleMessage( - "ローカルにデータをバックアップします", - ), "locationPermission": MessageLookupByLibrary.simpleMessage("位置情報の権限"), "locationPermissionDeniedMessage": MessageLookupByLibrary.simpleMessage( "位置情報の権限が拒否されたため、現在の Wi-Fi 名を取得できません。システム設定で位置情報の権限を手動で有効にしてください。", @@ -512,7 +719,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationPermissionDesc": MessageLookupByLibrary.simpleMessage( "システムの要件により、Wi-Fi 名の取得には位置情報の権限が必要です。Android では「常に許可」を選択してください。そうしないと、アプリがバックグラウンドにあるときに Wi-Fi 名を取得できません。", ), - "locationPermissionGuide": m18, + "locationPermissionGuide": m22, "locationPermissionRequired": MessageLookupByLibrary.simpleMessage( "位置情報の権限が必要です", ), @@ -521,57 +728,77 @@ class MessageLookup extends MessageLookupByLibrary { "logcat": MessageLookupByLibrary.simpleMessage("ログキャプチャ"), "logcatDesc": MessageLookupByLibrary.simpleMessage("無効にするとログの入り口が非表示になります"), "logs": MessageLookupByLibrary.simpleMessage("ログ"), - "logsDesc": MessageLookupByLibrary.simpleMessage("キャプチャしたログの記録"), + "logsAndDiagnostics": MessageLookupByLibrary.simpleMessage("ログと診断"), "logsTest": MessageLookupByLibrary.simpleMessage("ログテスト"), - "loopback": MessageLookupByLibrary.simpleMessage("ループバック解除ツール"), - "loopbackDesc": MessageLookupByLibrary.simpleMessage("UWPのループバック解除に使用します"), + "loopback": MessageLookupByLibrary.simpleMessage("UWP ループバック解除"), "loose": MessageLookupByLibrary.simpleMessage("ゆったり"), "matchSourceIp": MessageLookupByLibrary.simpleMessage("送信元IPにマッチ"), "matchTarget": MessageLookupByLibrary.simpleMessage("MATCH-TARGET"), - "matchTargetDesc": MessageLookupByLibrary.simpleMessage( - "MATCH-TARGET を対象にしたルールの行き先。既定ではこのプロファイル末尾の MATCH ルールのターゲットを使います。", - ), - "matchTargetTitle": MessageLookupByLibrary.simpleMessage("マッチ先"), "maxFailedTimes": MessageLookupByLibrary.simpleMessage("最大失敗回数"), - "maxLengthTip": m19, + "maxLengthTip": m23, "maximize": MessageLookupByLibrary.simpleMessage("最大化"), + "memoryAppResident": MessageLookupByLibrary.simpleMessage("常駐メモリ"), + "memoryAppShared": MessageLookupByLibrary.simpleMessage("アプリと共有"), + "memoryCoreHeapIdle": MessageLookupByLibrary.simpleMessage("未使用のヒープ"), + "memoryCoreHeapInuse": MessageLookupByLibrary.simpleMessage("使用中のヒープ"), + "memoryCoreNotRunning": MessageLookupByLibrary.simpleMessage( + "コアは実行されていません", + ), + "memoryCoreRuntime": MessageLookupByLibrary.simpleMessage("ランタイムのオーバーヘッド"), + "memoryCoreStack": MessageLookupByLibrary.simpleMessage("ゴルーチンスタック"), + "memoryEstimateDesc": MessageLookupByLibrary.simpleMessage( + "プロセスの常駐メモリからの推定値で、システムの表示とは異なる場合があります。", + ), + "memoryEstimateSharedDesc": MessageLookupByLibrary.simpleMessage( + "コアはアプリと同じプロセスで動作します。コア分はランタイム統計から推定し、残りはアプリと共有メモリとして計上します。", + ), "memoryInfo": MessageLookupByLibrary.simpleMessage("メモリ情報"), + "memoryReleased": MessageLookupByLibrary.simpleMessage("メモリを解放しました"), + "memoryReleasedSize": m24, "messageTest": MessageLookupByLibrary.simpleMessage("メッセージテスト"), "messageTestTip": MessageLookupByLibrary.simpleMessage("これはメッセージです。"), "min": MessageLookupByLibrary.simpleMessage("最小"), "minimize": MessageLookupByLibrary.simpleMessage("最小化"), "minimizeOnExit": MessageLookupByLibrary.simpleMessage("終了時に最小化"), - "minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage( - "システム標準の終了動作を変更します", - ), - "minutesAgo": m20, + "minutesAgo": m25, "mixedPort": MessageLookupByLibrary.simpleMessage("Mixedポート"), "mode": MessageLookupByLibrary.simpleMessage("モード"), "monochromeScheme": MessageLookupByLibrary.simpleMessage("モノクローム"), - "monthsAgo": m21, + "monthsAgo": m26, "more": MessageLookupByLibrary.simpleMessage("その他"), - "multipleValuesTip": MessageLookupByLibrary.simpleMessage( - "複数の値はカンマで区切ってください", - ), "name": MessageLookupByLibrary.simpleMessage("名前"), - "nameserver": MessageLookupByLibrary.simpleMessage("ネームサーバー"), - "nameserverDesc": MessageLookupByLibrary.simpleMessage("ドメインの名前解決に使用します"), - "nameserverPolicy": MessageLookupByLibrary.simpleMessage("ネームサーバーポリシー"), - "nameserverPolicyDesc": MessageLookupByLibrary.simpleMessage( - "ドメインごとのネームサーバーポリシーを指定します", - ), + "navigationBarStyle": MessageLookupByLibrary.simpleMessage("ボトムバー"), "network": MessageLookupByLibrary.simpleMessage("ネットワーク"), - "networkDesc": MessageLookupByLibrary.simpleMessage("ネットワーク関連の設定を変更します"), - "networkDetection": MessageLookupByLibrary.simpleMessage("ネットワーク検出"), - "networkException": MessageLookupByLibrary.simpleMessage( - "ネットワークエラーです。接続を確認してから再試行してください", + "networkAccessDeniedError": m27, + "networkBadResponseError": m28, + "networkCancelledError": MessageLookupByLibrary.simpleMessage( + "リクエストはキャンセルされました", ), + "networkConnectionError": MessageLookupByLibrary.simpleMessage( + "サーバーに接続できませんでした。ネットワーク接続またはプロキシ設定を確認してください", + ), + "networkDetection": MessageLookupByLibrary.simpleMessage("ネットワーク検出"), + "networkHostLookupError": MessageLookupByLibrary.simpleMessage( + "サーバーのアドレスを解決できませんでした。URL が正しいこと、DNS が使えることを確認してください", + ), + "networkNotFoundError": m29, + "networkRateLimitedError": MessageLookupByLibrary.simpleMessage( + "リクエストが多すぎます(HTTP 429)。しばらく待ってから再試行してください", + ), + "networkRequestFailed": m30, + "networkServerError": m31, "networkSpeed": MessageLookupByLibrary.simpleMessage("ネットワーク速度"), + "networkTimeoutError": MessageLookupByLibrary.simpleMessage( + "リクエストがタイムアウトしました。ネットワークまたはプロキシを確認してから再試行してください", + ), + "networkTlsError": MessageLookupByLibrary.simpleMessage( + "安全な接続に失敗しました。サーバー証明書が無効か、接続が傍受されている可能性があります", + ), "networkType": MessageLookupByLibrary.simpleMessage("ネットワーク種別"), "neutralScheme": MessageLookupByLibrary.simpleMessage("ニュートラル"), "nextMatch": MessageLookupByLibrary.simpleMessage("次の一致"), + "no": MessageLookupByLibrary.simpleMessage("いいえ"), "noData": MessageLookupByLibrary.simpleMessage("データがありません"), - "noHotKey": MessageLookupByLibrary.simpleMessage("ホットキーはまだありません"), "noInfo": MessageLookupByLibrary.simpleMessage("情報がありません"), "noLongerRemind": MessageLookupByLibrary.simpleMessage("今後表示しない"), "noNetwork": MessageLookupByLibrary.simpleMessage("ネットワークがありません"), @@ -579,39 +806,58 @@ class MessageLookup extends MessageLookupByLibrary { "noRecords": MessageLookupByLibrary.simpleMessage("記録がありません"), "noResolve": MessageLookupByLibrary.simpleMessage("IPを解決しない"), "noResolveHostname": MessageLookupByLibrary.simpleMessage("ホスト名を解決しない"), + "noSearchResults": MessageLookupByLibrary.simpleMessage("一致する結果はありません"), + "nonTextProviderFile": MessageLookupByLibrary.simpleMessage( + "この外部リソースはテキストファイルではありません", + ), "none": MessageLookupByLibrary.simpleMessage("なし"), "notSelectedTip": MessageLookupByLibrary.simpleMessage( "現在のプロキシグループは選択できません", ), - "nullProfileDesc": MessageLookupByLibrary.simpleMessage( - "プロファイルがありません。先にプロファイルを追加してください", + "ntpInterval": MessageLookupByLibrary.simpleMessage("同期間隔(分)"), + "ntpStatusDesc": MessageLookupByLibrary.simpleMessage( + "システムクロックではなくNTPサーバーから時刻を取得します", ), - "nullTip": m22, - "numberTip": m23, + "nullProfileDesc": MessageLookupByLibrary.simpleMessage( + "プロファイルを追加して始めましょう", + ), + "nullTip": m32, + "numberTip": m33, "onDemand": MessageLookupByLibrary.simpleMessage("オンデマンド"), "onDemandDesc": MessageLookupByLibrary.simpleMessage( "特定のシナリオでのアプリの実行状態を設定します", ), - "onlyIcon": MessageLookupByLibrary.simpleMessage("アイコンのみ"), - "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage("プロキシのみ集計"), - "onlyStatisticsProxyDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、プロキシのトラフィックのみを集計します", + "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage( + "プロキシトラフィックのみ集計", ), "optional": MessageLookupByLibrary.simpleMessage("任意"), "options": MessageLookupByLibrary.simpleMessage("オプション"), "other": MessageLookupByLibrary.simpleMessage("その他"), "otherContributors": MessageLookupByLibrary.simpleMessage("その他の貢献者"), + "outboundIp": MessageLookupByLibrary.simpleMessage("アウトバウンド IP"), "outboundMode": MessageLookupByLibrary.simpleMessage("アウトバウンドモード"), "override": MessageLookupByLibrary.simpleMessage("上書き"), "overrideDns": MessageLookupByLibrary.simpleMessage("DNSを上書き"), - "overrideDnsDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、プロファイル内のDNS設定を上書きします", - ), + "overrideEntries": MessageLookupByLibrary.simpleMessage("上書き項目"), "overrideMode": MessageLookupByLibrary.simpleMessage("上書きモード"), + "overrideNtp": MessageLookupByLibrary.simpleMessage("NTPを上書き"), "overrideScript": MessageLookupByLibrary.simpleMessage("上書きスクリプト"), + "overwriteIssueCoreRejected": m34, + "overwriteIssueDuplicateName": m35, + "overwriteIssueEmptyName": MessageLookupByLibrary.simpleMessage("名前が空です"), + "overwriteIssueGroupLoop": m36, + "overwriteIssueMissingProviders": m37, + "overwriteIssueMissingProxies": m38, + "overwriteIssueNoProxySource": MessageLookupByLibrary.simpleMessage( + "プロキシもプロキシプロバイダーも選択されていないため、コアはこのグループを拒否します", + ), + "overwriteIssueProviderShadowed": m39, + "overwriteIssueReservedName": m40, + "overwriteIssueSubscriptionGroupMissingProxies": m41, + "overwriteIssuesSummary": m42, "overwriteTypeCustom": MessageLookupByLibrary.simpleMessage("カスタム"), "overwriteTypeCustomDesc": MessageLookupByLibrary.simpleMessage( - "カスタムモード:プロキシグループとルールを完全にカスタマイズできます", + "カスタムモード:プロキシ、プロキシグループ、ルールを完全にカスタマイズできます", ), "palette": MessageLookupByLibrary.simpleMessage("パレット"), "password": MessageLookupByLibrary.simpleMessage("パスワード"), @@ -627,10 +873,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "port": MessageLookupByLibrary.simpleMessage("ポート"), "portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"), - "portTip": m24, - "preferH3Desc": MessageLookupByLibrary.simpleMessage("DoHでHTTP/3を優先します"), + "portTip": m43, "prerequisites": MessageLookupByLibrary.simpleMessage("前提条件"), - "pressKeyboard": MessageLookupByLibrary.simpleMessage("キーを押してください"), + "pressKeyboard": MessageLookupByLibrary.simpleMessage("キーの組み合わせを押してください"), "preview": MessageLookupByLibrary.simpleMessage("プレビュー"), "previousMatch": MessageLookupByLibrary.simpleMessage("前の一致"), "process": MessageLookupByLibrary.simpleMessage("プロセス"), @@ -654,33 +899,28 @@ class MessageLookup extends MessageLookupByLibrary { "profiles": MessageLookupByLibrary.simpleMessage("プロファイル"), "profilesSort": MessageLookupByLibrary.simpleMessage("プロファイルの並べ替え"), "project": MessageLookupByLibrary.simpleMessage("プロジェクト"), + "providerInUse": m44, + "providerRenameShadowed": m45, + "providerSourceSubscription": MessageLookupByLibrary.simpleMessage( + "サブスクリプション", + ), + "providerUrlTip": MessageLookupByLibrary.simpleMessage("リモートリソースのみ対応しています"), "providers": MessageLookupByLibrary.simpleMessage("外部リソース"), "proxies": MessageLookupByLibrary.simpleMessage("プロキシ"), - "proxiesCount": m25, + "proxiesCount": m46, "proxiesEmpty": MessageLookupByLibrary.simpleMessage("プロキシが空です"), "proxyChains": MessageLookupByLibrary.simpleMessage("プロキシチェーン"), - "proxyDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "選択したプロキシに異常が見つかりました", + "proxyDefinition": MessageLookupByLibrary.simpleMessage("完全な設定"), + "proxyDefinitionNotMap": MessageLookupByLibrary.simpleMessage( + "設定は name と type を含む YAML マッピングである必要があります", ), "proxyFilter": MessageLookupByLibrary.simpleMessage("ノードフィルター"), "proxyGroup": MessageLookupByLibrary.simpleMessage("プロキシグループ"), - "proxyGroupDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "現在のプロキシグループに異常が見つかりました", - ), "proxyGroupEmpty": MessageLookupByLibrary.simpleMessage("プロキシグループが空です"), "proxyGroupNameDuplicate": MessageLookupByLibrary.simpleMessage( "プロキシグループ名が重複しています", ), - "proxyGroupNameEmpty": MessageLookupByLibrary.simpleMessage( - "プロキシグループ名は空にできません", - ), - "proxyNameserver": MessageLookupByLibrary.simpleMessage("プロキシネームサーバー"), - "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage( - "プロキシノードのドメイン解決に使用します", - ), - "proxyProviderDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "選択したプロキシプロバイダーに異常が見つかりました", - ), + "proxyNode": MessageLookupByLibrary.simpleMessage("プロキシノード"), "proxyProviders": MessageLookupByLibrary.simpleMessage("プロキシプロバイダー"), "proxyProvidersEmpty": MessageLookupByLibrary.simpleMessage( "プロキシプロバイダーが空です", @@ -690,55 +930,54 @@ class MessageLookup extends MessageLookupByLibrary { ), "proxyType": MessageLookupByLibrary.simpleMessage("プロキシタイプ"), "pruneCache": MessageLookupByLibrary.simpleMessage("キャッシュを整理"), + "pureBlack": MessageLookupByLibrary.simpleMessage("ピュアブラック"), "pureBlackMode": MessageLookupByLibrary.simpleMessage("ピュアブラックモード"), "qrcode": MessageLookupByLibrary.simpleMessage("QRコード"), "qrcodeDesc": MessageLookupByLibrary.simpleMessage( "QRコードをスキャンしてプロファイルを取得します", ), + "quickAdd": MessageLookupByLibrary.simpleMessage("クイック追加"), + "quickEdit": MessageLookupByLibrary.simpleMessage("クイック編集"), "quickFill": MessageLookupByLibrary.simpleMessage("クイック入力"), "rainbowScheme": MessageLookupByLibrary.simpleMessage("レインボー"), + "recentRequests": MessageLookupByLibrary.simpleMessage("最近のリクエスト"), + "recordType": MessageLookupByLibrary.simpleMessage("レコードタイプ"), "redirPort": MessageLookupByLibrary.simpleMessage("Redirポート"), "redo": MessageLookupByLibrary.simpleMessage("やり直す"), - "remote": MessageLookupByLibrary.simpleMessage("リモート"), - "remoteBackupDesc": MessageLookupByLibrary.simpleMessage( - "WebDAVにデータをバックアップします", + "releaseMemory": MessageLookupByLibrary.simpleMessage("メモリを解放"), + "releaseMemoryFailed": MessageLookupByLibrary.simpleMessage( + "メモリの解放に失敗しました", ), + "remote": MessageLookupByLibrary.simpleMessage("リモート"), "remoteDestination": MessageLookupByLibrary.simpleMessage("リモート宛先"), "remove": MessageLookupByLibrary.simpleMessage("削除"), + "replace": MessageLookupByLibrary.simpleMessage("置換"), + "replaceAll": MessageLookupByLibrary.simpleMessage("すべて置換"), "request": MessageLookupByLibrary.simpleMessage("リクエスト"), "requests": MessageLookupByLibrary.simpleMessage("リクエスト"), - "requestsDesc": MessageLookupByLibrary.simpleMessage("最近のリクエスト記録を表示します"), + "requestsAndUpdates": MessageLookupByLibrary.simpleMessage("リクエストと更新"), "reset": MessageLookupByLibrary.simpleMessage("リセット"), "resetPageChangesTip": MessageLookupByLibrary.simpleMessage( "このページには変更があります。リセットしてもよろしいですか?", ), "resetTip": MessageLookupByLibrary.simpleMessage("リセットしてもよろしいですか?"), "resources": MessageLookupByLibrary.simpleMessage("リソース"), - "resourcesDesc": MessageLookupByLibrary.simpleMessage("外部リソースの関連情報"), "respectRules": MessageLookupByLibrary.simpleMessage("ルールに従う"), "respectRulesDesc": MessageLookupByLibrary.simpleMessage( - "DNS接続がルールに従います。proxy-server-nameserverの設定が必要です", + "DNS接続がルールに従います。Proxy Server Nameserverの設定が必要です", ), + "responseCode": MessageLookupByLibrary.simpleMessage("応答コード"), "restart": MessageLookupByLibrary.simpleMessage("再起動"), "restartCoreTip": MessageLookupByLibrary.simpleMessage("コアを再起動してもよろしいですか?"), "restore": MessageLookupByLibrary.simpleMessage("復元"), "restoreAllData": MessageLookupByLibrary.simpleMessage("すべてのデータを復元"), - "restoreException": MessageLookupByLibrary.simpleMessage("復元エラー"), - "restoreFromFileDesc": MessageLookupByLibrary.simpleMessage( - "ファイルからデータを復元します", - ), - "restoreFromWebDAVDesc": MessageLookupByLibrary.simpleMessage( - "WebDAVからデータを復元します", - ), "restoreOnlyConfig": MessageLookupByLibrary.simpleMessage("プロファイルのみ復元"), "restoreStrategy": MessageLookupByLibrary.simpleMessage("復元方式"), "restoreStrategyCompatible": MessageLookupByLibrary.simpleMessage("互換"), "restoreStrategyOverride": MessageLookupByLibrary.simpleMessage("上書き"), "restoreSuccess": MessageLookupByLibrary.simpleMessage("復元が完了しました"), + "retry": MessageLookupByLibrary.simpleMessage("再試行"), "routeAddress": MessageLookupByLibrary.simpleMessage("ルートアドレス"), - "routeAddressDesc": MessageLookupByLibrary.simpleMessage( - "リッスンするルートアドレスを設定します", - ), "routeMode": MessageLookupByLibrary.simpleMessage("ルートモード"), "routeModeBypassPrivate": MessageLookupByLibrary.simpleMessage( "プライベートアドレスをバイパス", @@ -847,10 +1086,25 @@ class MessageLookup extends MessageLookupByLibrary { ), "ruleEmpty": MessageLookupByLibrary.simpleMessage("ルールが空です"), "ruleName": MessageLookupByLibrary.simpleMessage("ルール名"), + "rulePresetBittorrentDirect": MessageLookupByLibrary.simpleMessage( + "BitTorrent を直接接続", + ), + "rulePresetBlockDot": MessageLookupByLibrary.simpleMessage( + "DNS over TLS をブロック", + ), + "rulePresetBlockQuic": MessageLookupByLibrary.simpleMessage("QUIC をブロック"), + "rulePresetBlockStun": MessageLookupByLibrary.simpleMessage("STUN をブロック"), + "rulePresetLanDirect": MessageLookupByLibrary.simpleMessage("LAN 直接接続"), + "rulePresetSystemServicesDirect": MessageLookupByLibrary.simpleMessage( + "Apple と Microsoft に直接接続", + ), + "ruleProviders": MessageLookupByLibrary.simpleMessage("ルールプロバイダー"), "ruleSet": MessageLookupByLibrary.simpleMessage("ルールセット"), "ruleTarget": MessageLookupByLibrary.simpleMessage("ルールターゲット"), "rules": MessageLookupByLibrary.simpleMessage("ルール"), - "rulesCount": m26, + "rulesCount": m47, + "safeMode": MessageLookupByLibrary.simpleMessage("セーフモード"), + "safeModeAppTitle": m48, "save": MessageLookupByLibrary.simpleMessage("保存"), "saveChanges": MessageLookupByLibrary.simpleMessage("変更を保存しますか?"), "script": MessageLookupByLibrary.simpleMessage("スクリプト"), @@ -860,11 +1114,8 @@ class MessageLookup extends MessageLookupByLibrary { "scrollToSelected": MessageLookupByLibrary.simpleMessage("選択項目へスクロール"), "search": MessageLookupByLibrary.simpleMessage("検索"), "seconds": MessageLookupByLibrary.simpleMessage("秒"), - "secondsCount": m27, + "secondsCount": m49, "selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"), - "selectMatchTarget": MessageLookupByLibrary.simpleMessage( - "MATCH-TARGET を選択", - ), "selectProxies": MessageLookupByLibrary.simpleMessage("プロキシを選択"), "selectProxyProviders": MessageLookupByLibrary.simpleMessage( "プロキシプロバイダーを選択", @@ -875,7 +1126,25 @@ class MessageLookup extends MessageLookupByLibrary { ), "selectSubRule": MessageLookupByLibrary.simpleMessage("サブルールを選択してください"), "selected": MessageLookupByLibrary.simpleMessage("選択済み"), - "selectedCountTitle": m28, + "selectedCountTitle": m50, + "server": MessageLookupByLibrary.simpleMessage("サーバー"), + "serviceAvailable": MessageLookupByLibrary.simpleMessage("利用可能"), + "serviceBlocked": MessageLookupByLibrary.simpleMessage("ブロック済み"), + "serviceCheck": MessageLookupByLibrary.simpleMessage("検査"), + "serviceCheckAll": MessageLookupByLibrary.simpleMessage("すべて検査"), + "serviceCheckedAt": m51, + "serviceComingSoon": MessageLookupByLibrary.simpleMessage("近日提供予定"), + "serviceDisallowedIsp": MessageLookupByLibrary.simpleMessage( + "許可されていない ISP", + ), + "serviceFailed": MessageLookupByLibrary.simpleMessage("検出に失敗しました"), + "serviceManage": MessageLookupByLibrary.simpleMessage("サービスを管理"), + "serviceOriginalsOnly": MessageLookupByLibrary.simpleMessage("オリジナル作品のみ"), + "servicePending": MessageLookupByLibrary.simpleMessage("未検査"), + "serviceRestricted": MessageLookupByLibrary.simpleMessage("アクセス制限"), + "serviceStatus": MessageLookupByLibrary.simpleMessage("サービスの状態"), + "serviceUnavailable": MessageLookupByLibrary.simpleMessage("利用不可"), + "serviceUnsupportedRegion": MessageLookupByLibrary.simpleMessage("対象外の地域"), "settings": MessageLookupByLibrary.simpleMessage("設定"), "show": MessageLookupByLibrary.simpleMessage("表示"), "showLess": MessageLookupByLibrary.simpleMessage("折りたたむ"), @@ -883,14 +1152,20 @@ class MessageLookup extends MessageLookupByLibrary { "showNotificationStopAction": MessageLookupByLibrary.simpleMessage( "通知に停止ボタンを表示", ), - "showNotificationStopActionDesc": MessageLookupByLibrary.simpleMessage( - "常駐通知に停止ボタンを表示します。これが原因で通知が常に展開される場合はオフにしてください", - ), "showPassword": MessageLookupByLibrary.simpleMessage("パスワードを表示"), "shrink": MessageLookupByLibrary.simpleMessage("コンパクト"), + "sidebarBlur": MessageLookupByLibrary.simpleMessage("サイドバーのぼかし"), + "sidebarBlurDesc": MessageLookupByLibrary.simpleMessage( + "ウィンドウ背後のデスクトップをぼかしてサイドバーに透過します", + ), "silentLaunch": MessageLookupByLibrary.simpleMessage("サイレント起動"), - "silentLaunchDesc": MessageLookupByLibrary.simpleMessage("バックグラウンドで起動します"), + "silentLaunchDesc": MessageLookupByLibrary.simpleMessage( + "起動時にウィンドウを表示しません", + ), + "singleAdd": MessageLookupByLibrary.simpleMessage("個別追加"), + "singleValueTip": m52, "size": MessageLookupByLibrary.simpleMessage("サイズ"), + "slide": MessageLookupByLibrary.simpleMessage("スライド"), "socksPort": MessageLookupByLibrary.simpleMessage("SOCKSポート"), "sort": MessageLookupByLibrary.simpleMessage("並べ替え"), "source": MessageLookupByLibrary.simpleMessage("ソース"), @@ -909,35 +1184,36 @@ class MessageLookup extends MessageLookupByLibrary { "標準モード:基本設定を上書きし、シンプルなルール追加機能を提供します", ), "start": MessageLookupByLibrary.simpleMessage("開始"), - "startVpn": MessageLookupByLibrary.simpleMessage("VPNを起動しています..."), + "startFromScratch": MessageLookupByLibrary.simpleMessage("最初から作成"), + "startVpn": MessageLookupByLibrary.simpleMessage("VPNを起動しています…"), + "startupAndBackground": MessageLookupByLibrary.simpleMessage("起動とバックグラウンド"), "status": MessageLookupByLibrary.simpleMessage("状態"), "statusDesc": MessageLookupByLibrary.simpleMessage("無効にすると、システムDNSを使用します"), "stop": MessageLookupByLibrary.simpleMessage("停止"), - "stopVpn": MessageLookupByLibrary.simpleMessage("VPNを停止しています..."), + "stopVpn": MessageLookupByLibrary.simpleMessage("VPNを停止しています…"), + "strategy": MessageLookupByLibrary.simpleMessage("戦略"), "style": MessageLookupByLibrary.simpleMessage("スタイル"), "subRule": MessageLookupByLibrary.simpleMessage("サブルール"), "subRuleEmpty": MessageLookupByLibrary.simpleMessage("サブルールが空です"), "subRuleNotEmpty": MessageLookupByLibrary.simpleMessage("サブルールは空にできません"), "submit": MessageLookupByLibrary.simpleMessage("送信"), "subscriptionInfo": MessageLookupByLibrary.simpleMessage("サブスクリプション情報"), - "suspended": MessageLookupByLibrary.simpleMessage("一時停止中..."), + "suspended": MessageLookupByLibrary.simpleMessage("一時停止中…"), "sync": MessageLookupByLibrary.simpleMessage("同期"), "system": MessageLookupByLibrary.simpleMessage("システム"), "systemApp": MessageLookupByLibrary.simpleMessage("システムアプリ"), "systemProxy": MessageLookupByLibrary.simpleMessage("システムプロキシ"), - "systemProxyDesc": MessageLookupByLibrary.simpleMessage("システムプロキシを設定します"), "tab": MessageLookupByLibrary.simpleMessage("タブ"), "tabAnimation": MessageLookupByLibrary.simpleMessage("タブアニメーション"), - "tabAnimationDesc": MessageLookupByLibrary.simpleMessage("モバイル表示でのみ有効です"), "tapToAuthorize": MessageLookupByLibrary.simpleMessage("タップして許可"), "tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP同時接続"), - "tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage( - "有効にすると、TCPの同時接続を許可します", - ), "testInterval": MessageLookupByLibrary.simpleMessage("テスト間隔"), "testUrl": MessageLookupByLibrary.simpleMessage("テストURL"), "testWhenUsed": MessageLookupByLibrary.simpleMessage("使用時にテスト"), "textScale": MessageLookupByLibrary.simpleMessage("テキストの拡大縮小"), + "textScalePreview": MessageLookupByLibrary.simpleMessage( + "アプリ内の文字はこの大きさで表示されます", + ), "theme": MessageLookupByLibrary.simpleMessage("テーマ"), "themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"), "themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定と色の調整"), @@ -947,10 +1223,11 @@ class MessageLookup extends MessageLookupByLibrary { "timeout": MessageLookupByLibrary.simpleMessage("タイムアウト"), "tip": MessageLookupByLibrary.simpleMessage("ヒント"), "toggle": MessageLookupByLibrary.simpleMessage("切り替え"), - "toggleLabel": MessageLookupByLibrary.simpleMessage("ラベルを切り替え"), + "tolerance": MessageLookupByLibrary.simpleMessage("許容値"), "tonalSpotScheme": MessageLookupByLibrary.simpleMessage("トーナルスポット"), "tools": MessageLookupByLibrary.simpleMessage("ツール"), "torch": MessageLookupByLibrary.simpleMessage("ライト"), + "total": MessageLookupByLibrary.simpleMessage("合計"), "totalTraffic": MessageLookupByLibrary.simpleMessage("合計トラフィック"), "tproxyPort": MessageLookupByLibrary.simpleMessage("TProxyポート"), "trafficUsage": MessageLookupByLibrary.simpleMessage("トラフィック統計"), @@ -960,9 +1237,6 @@ class MessageLookup extends MessageLookupByLibrary { "turnOn": MessageLookupByLibrary.simpleMessage("オンにする"), "undo": MessageLookupByLibrary.simpleMessage("元に戻す"), "unifiedDelay": MessageLookupByLibrary.simpleMessage("統一遅延"), - "unifiedDelayDesc": MessageLookupByLibrary.simpleMessage( - "ハンドシェイクなどの余分な遅延を除きます", - ), "unknown": MessageLookupByLibrary.simpleMessage("不明"), "unknownNetworkError": MessageLookupByLibrary.simpleMessage("不明なネットワークエラー"), "unmaximize": MessageLookupByLibrary.simpleMessage("元に戻す"), @@ -972,7 +1246,7 @@ class MessageLookup extends MessageLookupByLibrary { "upload": MessageLookupByLibrary.simpleMessage("アップロード"), "url": MessageLookupByLibrary.simpleMessage("URL"), "urlDesc": MessageLookupByLibrary.simpleMessage("URLからプロファイルを取得します"), - "urlTip": m29, + "urlTip": m53, "useHosts": MessageLookupByLibrary.simpleMessage("Hostsを使用"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("システムのHostsを使用"), "usedTraffic": MessageLookupByLibrary.simpleMessage("使用済みトラフィック"), @@ -989,7 +1263,12 @@ class MessageLookup extends MessageLookupByLibrary { "vpnTip": MessageLookupByLibrary.simpleMessage("変更はVPNの再起動後に有効になります"), "webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV設定"), "whitelistMode": MessageLookupByLibrary.simpleMessage("ホワイトリストモード"), - "yearsAgo": m30, + "writeToSystem": MessageLookupByLibrary.simpleMessage("システムに書き込む"), + "writeToSystemDesc": MessageLookupByLibrary.simpleMessage( + "システムクロックも設定します。Androidでは無視されます", + ), + "yearsAgo": m54, + "yes": MessageLookupByLibrary.simpleMessage("はい"), "zhCN": MessageLookupByLibrary.simpleMessage("簡体字中国語"), }; } diff --git a/lib/l10n/intl/messages_ru.dart b/lib/l10n/intl/messages_ru.dart index dd11eafa..51359d9b 100644 --- a/lib/l10n/intl/messages_ru.dart +++ b/lib/l10n/intl/messages_ru.dart @@ -20,28 +20,28 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ru'; - static String m0(code) => + static String m0(count, skipped) => + "Будет добавлено: ${count}, пропущено (уже есть): ${skipped}"; + + static String m1(code) => "Windows отказалась запускать FlClashCore.exe (ошибка ${code}). Политики контроля приложений, такие как Smart App Control или AppLocker, блокируют неподписанные программы; разрешите FlClash в этой политике или отключите её и повторите попытку."; - static String m1(name) => + static String m2(name) => "Приложение два раза подряд не смогло завершить запуск. Чтобы разорвать цикл, профиль ${name} снят с выбора, а автоматическая настройка пропущена. Вы можете выбрать его снова в любой момент."; - static String m2(url) => "Создать профиль по ссылке ${url}?"; + static String m3(url) => "Создать профиль по ссылке ${url}?"; - static String m3(count) => + static String m4(count) => "${Intl.plural(count, one: '${count} день назад', few: '${count} дня назад', many: '${count} дней назад', other: '${count} дня назад')}"; - static String m4(label) => + static String m5(label) => "Вы уверены, что хотите удалить выбранные элементы (${label})?"; - static String m5(label) => "Вы уверены, что хотите удалить «${label}»?"; + static String m6(label) => "Вы уверены, что хотите удалить «${label}»?"; - static String m6(label) => "Сведения: ${label}"; + static String m7(label) => "Сведения: ${label}"; - static String m7(label) => "Поле «${label}» не может быть пустым"; - - static String m8(count) => - "${Intl.plural(count, one: '${count} запись', few: '${count} записи', many: '${count} записей', other: '${count} записи')}"; + static String m8(label) => "Поле «${label}» не может быть пустым"; static String m9(label) => "«${label}» уже существует"; @@ -49,52 +49,114 @@ class MessageLookup extends MessageLookupByLibrary { static String m11(name) => "${name}: обновлено"; - static String m12(count) => + static String m12(action) => + "Уже используется для «${action}». При сохранении будет перенесено сюда."; + + static String m13(modifiers) => + "Добавьте хотя бы одну из клавиш: ${modifiers}"; + + static String m14(count) => "${Intl.plural(count, one: '${count} час назад', few: '${count} часа назад', many: '${count} часов назад', other: '${count} часа назад')}"; - static String m13(count) => + static String m15(count) => "${Intl.plural(count, one: '${count} час', few: '${count} часа', many: '${count} часов', other: '${count} часа')}"; - static String m14(target) => "${target} — недопустимая политика"; + static String m16(target) => "${target} — недопустимая политика"; - static String m15(proxyName) => "${proxyName} — недопустимый прокси"; + static String m17(proxyName) => "${proxyName} — недопустимый прокси"; - static String m16(providerName) => + static String m18(providerName) => "${providerName} — недопустимый провайдер прокси"; - static String m17(subRule) => "${subRule} — недопустимый SUB_RULE"; + static String m19(ruleSet) => "${ruleSet} — недопустимый набор правил"; - static String m18(appName) => + static String m20(subRule) => "${subRule} — недопустимый SUB_RULE"; + + static String m21(line, message) => "Строка ${line}: ${message}"; + + static String m22(appName) => "1. Откройте Системные настройки > Конфиденциальность и безопасность\n2. Выберите Службы геолокации\n3. Найдите и отметьте ${appName} в списке\n\nПосле настройки вернитесь в приложение и продолжайте работу. Спасибо за сотрудничество."; - static String m19(label, max) => "«${label}» — не более ${max} символов"; + static String m23(label, max) => "«${label}» — не более ${max} символов"; - static String m20(count) => + static String m24(size) => "Освобождено ${size}"; + + static String m25(count) => "${Intl.plural(count, one: '${count} минуту назад', few: '${count} минуты назад', many: '${count} минут назад', other: '${count} минуты назад')}"; - static String m21(count) => + static String m26(count) => "${Intl.plural(count, one: '${count} месяц назад', few: '${count} месяца назад', many: '${count} месяцев назад', other: '${count} месяца назад')}"; - static String m22(label) => "Пока нет: ${label}"; + static String m27(code) => + "Сервер запретил доступ (HTTP ${code}). Возможно, ссылка устарела или учётные данные неверны"; - static String m23(label) => "Значение «${label}» должно быть числом"; + static String m28(code) => "Сервер отклонил запрос (HTTP ${code})"; - static String m24(label) => + static String m29(code) => + "По этому адресу ничего не найдено (HTTP ${code}). Проверьте правильность URL"; + + static String m30(detail) => "Сетевой запрос не выполнен: ${detail}"; + + static String m31(code) => + "На сервере произошла ошибка (HTTP ${code}). Повторите попытку позже"; + + static String m32(label) => "Пока нет: ${label}"; + + static String m33(label) => "Значение «${label}» должно быть числом"; + + static String m34(message) => + "Ядро не может разобрать этот прокси: ${message}"; + + static String m35(name) => + "Имя ${name} уже занято другим прокси или группой прокси"; + + static String m36(path) => + "Группы прокси ссылаются друг на друга по кругу: ${path}"; + + static String m37(names) => "Эти провайдеры прокси не существуют: ${names}"; + + static String m38(names) => "Эти прокси или политики не существуют: ${names}"; + + static String m39(name) => + "В профиле уже есть провайдер с именем ${name}, поэтому провайдер приложения с тем же именем не используется. Переименуйте его"; + + static String m40(name) => + "${name} — встроенное имя политики, его нельзя использовать"; + + static String m41(names) => + "Собственные группы прокси профиля ссылаются на прокси, которых больше нет среди пользовательских: ${names}"; + + static String m42(count) => + "Проблем: ${count}, применение переопределения может завершиться ошибкой"; + + static String m43(label) => "Значение «${label}» должно быть от 1024 до 49151"; - static String m25(count) => "${count} прокси"; + static String m44(label, profiles) => + "«${label}» всё ещё используется в пользовательских группах прокси или правилах профилей: ${profiles}. Сначала уберите его оттуда"; - static String m26(count) => + static String m45(profiles, label) => + "В подписках профилей ${profiles} уже есть «${label}», и после переименования они будут использовать его. Выберите другое имя"; + + static String m46(count) => "${count} прокси"; + + static String m47(count) => "${Intl.plural(count, one: '${count} правило', few: '${count} правила', many: '${count} правил', other: '${count} правила')}"; - static String m27(count) => + static String m48(appName) => "${appName} (Безопасный режим)"; + + static String m49(count) => "${Intl.plural(count, one: '${count} секунда', few: '${count} секунды', many: '${count} секунд', other: '${count} секунды')}"; - static String m28(count) => "Выбрано: ${count}"; + static String m50(count) => "Выбрано: ${count}"; - static String m29(label) => "Значение «${label}» должно быть URL"; + static String m51(time) => "Проверено в ${time}"; - static String m30(count) => + static String m52(label) => "«${label}» — только одно значение"; + + static String m53(label) => "Значение «${label}» должно быть URL"; + + static String m54(count) => "${Intl.plural(count, one: '${count} год назад', few: '${count} года назад', many: '${count} лет назад', other: '${count} года назад')}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -118,12 +180,27 @@ class MessageLookup extends MessageLookupByLibrary { ), "account": MessageLookupByLibrary.simpleMessage("Аккаунт"), "action": MessageLookupByLibrary.simpleMessage("Действие"), + "actionDelayTest": MessageLookupByLibrary.simpleMessage( + "Проверить все задержки", + ), + "actionDirectMode": MessageLookupByLibrary.simpleMessage("Прямой режим"), + "actionGlobalMode": MessageLookupByLibrary.simpleMessage( + "Глобальный режим", + ), "actionMode": MessageLookupByLibrary.simpleMessage("Переключить режим"), "actionProxy": MessageLookupByLibrary.simpleMessage("Системный прокси"), + "actionRuleMode": MessageLookupByLibrary.simpleMessage("Режим правил"), "actionStart": MessageLookupByLibrary.simpleMessage("Старт/Стоп"), "actionTun": MessageLookupByLibrary.simpleMessage("TUN"), + "actionUpdateProfiles": MessageLookupByLibrary.simpleMessage( + "Обновить профили", + ), "actionView": MessageLookupByLibrary.simpleMessage("Показать/Скрыть"), "add": MessageLookupByLibrary.simpleMessage("Добавить"), + "addCustomProxy": MessageLookupByLibrary.simpleMessage("Добавить прокси"), + "addOverrideEntry": MessageLookupByLibrary.simpleMessage( + "Добавить параметр", + ), "addProfile": MessageLookupByLibrary.simpleMessage("Добавить профиль"), "addProxies": MessageLookupByLibrary.simpleMessage("Добавить прокси"), "addProxyGroup": MessageLookupByLibrary.simpleMessage( @@ -148,33 +225,33 @@ class MessageLookup extends MessageLookupByLibrary { "Расширенная конфигурация", ), "advancedConfigDesc": MessageLookupByLibrary.simpleMessage( - "Разнообразные параметры конфигурации", + "Сеть, DNS, добавленные правила и скрипты", ), "agree": MessageLookupByLibrary.simpleMessage("Согласен"), "allowBypass": MessageLookupByLibrary.simpleMessage( "Разрешить приложениям обходить VPN", ), - "allowBypassDesc": MessageLookupByLibrary.simpleMessage( - "При включении некоторые приложения смогут обходить VPN", - ), "allowLan": MessageLookupByLibrary.simpleMessage("Разрешить LAN"), - "allowLanDesc": MessageLookupByLibrary.simpleMessage( - "Разрешить доступ к прокси из локальной сети", - ), + "answers": MessageLookupByLibrary.simpleMessage("Ответы"), "app": MessageLookupByLibrary.simpleMessage("Приложение"), "appAccessControl": MessageLookupByLibrary.simpleMessage( "Контроль доступа приложений", ), + "appIconDesign": MessageLookupByLibrary.simpleMessage( + "Дизайн значка приложения", + ), + "appProviderShadowed": MessageLookupByLibrary.simpleMessage( + "Одноимённый элемент приложения здесь не используется", + ), + "appProxyProviders": MessageLookupByLibrary.simpleMessage( + "Прокси-провайдеры приложения", + ), + "appRuleProviders": MessageLookupByLibrary.simpleMessage( + "Провайдеры правил приложения", + ), "appendSystemDns": MessageLookupByLibrary.simpleMessage( "Добавлять системный DNS", ), - "appendSystemDnsTip": MessageLookupByLibrary.simpleMessage( - "Принудительно добавлять системный DNS в конфигурацию", - ), - "application": MessageLookupByLibrary.simpleMessage("Приложение"), - "applicationDesc": MessageLookupByLibrary.simpleMessage( - "Настройки, связанные с приложением", - ), "authentication": MessageLookupByLibrary.simpleMessage("Аутентификация"), "authenticationDesc": MessageLookupByLibrary.simpleMessage( "Требовать учётные данные для локального порта прокси, чтобы другие приложения не могли использовать его", @@ -188,9 +265,6 @@ class MessageLookup extends MessageLookupByLibrary { "autoCheckUpdate": MessageLookupByLibrary.simpleMessage( "Автопроверка обновлений", ), - "autoCheckUpdateDesc": MessageLookupByLibrary.simpleMessage( - "Автоматически проверять обновления при запуске приложения", - ), "autoCloseConnections": MessageLookupByLibrary.simpleMessage( "Автозакрытие соединений", ), @@ -220,21 +294,26 @@ class MessageLookup extends MessageLookupByLibrary { "backupAndRestoreDesc": MessageLookupByLibrary.simpleMessage( "Синхронизация данных через WebDAV или файлы", ), + "backupFromNewerVersion": MessageLookupByLibrary.simpleMessage( + "Резервная копия создана более новой версией приложения. Обновите приложение перед восстановлением", + ), "backupSuccess": MessageLookupByLibrary.simpleMessage( "Резервная копия создана", ), - "basicConfig": MessageLookupByLibrary.simpleMessage("Базовая конфигурация"), - "basicConfigDesc": MessageLookupByLibrary.simpleMessage( - "Глобальное изменение базовой конфигурации", - ), "basicInfo": MessageLookupByLibrary.simpleMessage("Основная информация"), "basicStrategy": MessageLookupByLibrary.simpleMessage("Базовые политики"), + "batchAdd": MessageLookupByLibrary.simpleMessage("Массовое добавление"), + "batchListInputTip": MessageLookupByLibrary.simpleMessage( + "По одному значению на строку или через запятую", + ), + "batchMapInputTip": MessageLookupByLibrary.simpleMessage( + "По одной записи на строку: ключ, пробел, значение", + ), + "batchPreviewTip": m0, "batteryOptimizationDesc": MessageLookupByLibrary.simpleMessage( "Чтобы приложение работало в фоне, отключите для него оптимизацию батареи. Нажмите, чтобы перейти к настройкам.", ), - "batteryOptimizationStatusTip": MessageLookupByLibrary.simpleMessage( - "Из-за системных ограничений во время работы невозможно корректно получить статус оптимизации батареи", - ), + "behavior": MessageLookupByLibrary.simpleMessage("Поведение"), "bind": MessageLookupByLibrary.simpleMessage("Привязать"), "blacklistMode": MessageLookupByLibrary.simpleMessage( "Режим чёрного списка", @@ -246,9 +325,21 @@ class MessageLookup extends MessageLookupByLibrary { "bypassDomainDesc": MessageLookupByLibrary.simpleMessage( "Действует только при включённом системном прокси", ), + "cache": MessageLookupByLibrary.simpleMessage("Кэш"), + "cacheAlgorithm": MessageLookupByLibrary.simpleMessage("Алгоритм кэша"), "cacheCorrupt": MessageLookupByLibrary.simpleMessage( "Кэш повреждён. Очистить его?", ), + "cacheMaxSize": MessageLookupByLibrary.simpleMessage("Размер кэша"), + "cameraPermissionDesc": MessageLookupByLibrary.simpleMessage( + "Разрешите доступ к камере в системных настройках, чтобы сканировать QR-коды, или выберите изображение QR-кода из галереи.", + ), + "cameraPermissionRequired": MessageLookupByLibrary.simpleMessage( + "Требуется доступ к камере", + ), + "cameraUnavailable": MessageLookupByLibrary.simpleMessage( + "Камера недоступна", + ), "cancel": MessageLookupByLibrary.simpleMessage("Отмена"), "cancelSelectAll": MessageLookupByLibrary.simpleMessage("Снять выделение"), "changeProxyFailedTip": MessageLookupByLibrary.simpleMessage( @@ -309,12 +400,9 @@ class MessageLookup extends MessageLookupByLibrary { "После подтверждения существующие данные будут перезаписаны", ), "connected": MessageLookupByLibrary.simpleMessage("Подключено"), - "connecting": MessageLookupByLibrary.simpleMessage("Подключение..."), + "connecting": MessageLookupByLibrary.simpleMessage("Подключение…"), "connection": MessageLookupByLibrary.simpleMessage("Соединение"), "connections": MessageLookupByLibrary.simpleMessage("Соединения"), - "connectionsDesc": MessageLookupByLibrary.simpleMessage( - "Просмотр данных о текущих соединениях", - ), "connectivity": MessageLookupByLibrary.simpleMessage("Подключение: "), "content": MessageLookupByLibrary.simpleMessage("Содержимое"), "contentNotEmpty": MessageLookupByLibrary.simpleMessage( @@ -331,24 +419,26 @@ class MessageLookup extends MessageLookupByLibrary { "copyLink": MessageLookupByLibrary.simpleMessage("Копировать ссылку"), "copySuccess": MessageLookupByLibrary.simpleMessage("Скопировано"), "core": MessageLookupByLibrary.simpleMessage("Ядро"), - "coreBlockedByPolicyTip": m0, + "coreBlockedByPolicyTip": m1, "coreBlockedBySmartAppControlTip": MessageLookupByLibrary.simpleMessage( "Smart App Control в Windows заблокировал неподписанный FlClashCore.exe. Откройте Безопасность Windows → Управление приложениями и браузером → Параметры Smart App Control, выберите «Выкл.» и снова запустите FlClash. Повторно включить Smart App Control без переустановки Windows нельзя.", ), "coreStatus": MessageLookupByLibrary.simpleMessage("Статус ядра"), "country": MessageLookupByLibrary.simpleMessage("Регион"), "crashDetected": MessageLookupByLibrary.simpleMessage("Обнаружен сбой"), - "crashDetectedTip": m1, + "crashDetectedTip": m2, "crashTest": MessageLookupByLibrary.simpleMessage("Тест сбоя"), "crashlytics": MessageLookupByLibrary.simpleMessage("Аналитика сбоев"), "crashlyticsTip": MessageLookupByLibrary.simpleMessage( "При включении в случае сбоя приложения автоматически загружаются логи сбоя без конфиденциальной информации", ), "create": MessageLookupByLibrary.simpleMessage("Создать"), - "createProfile": MessageLookupByLibrary.simpleMessage("Создать профиль"), - "createProfileFromUrlTip": m2, + "createProfileFromUrlTip": m3, "creationTime": MessageLookupByLibrary.simpleMessage("Время создания"), "custom": MessageLookupByLibrary.simpleMessage("Вручную"), + "customProxiesEmpty": MessageLookupByLibrary.simpleMessage( + "Пользовательских прокси нет, поэтому используются прокси самого профиля", + ), "cut": MessageLookupByLibrary.simpleMessage("Вырезать"), "dark": MessageLookupByLibrary.simpleMessage("Тёмная"), "dashboard": MessageLookupByLibrary.simpleMessage("Панель"), @@ -364,19 +454,13 @@ class MessageLookup extends MessageLookupByLibrary { "databaseWriteFailedTip": MessageLookupByLibrary.simpleMessage( "Не удалось сохранить изменение; оно отменено", ), - "daysAgo": m3, - "defaultNameserver": MessageLookupByLibrary.simpleMessage( - "DNS-сервер по умолчанию", - ), - "defaultNameserverDesc": MessageLookupByLibrary.simpleMessage( - "Используется для разрешения адресов DNS-серверов", - ), + "daysAgo": m4, "defaultText": MessageLookupByLibrary.simpleMessage("По умолчанию"), "delay": MessageLookupByLibrary.simpleMessage("Задержка"), "delayTest": MessageLookupByLibrary.simpleMessage("Тест задержки"), "delete": MessageLookupByLibrary.simpleMessage("Удалить"), - "deleteMultipTip": m4, - "deleteTip": m5, + "deleteMultipTip": m5, + "deleteTip": m6, "desc": MessageLookupByLibrary.simpleMessage( "Многоплатформенный прокси-клиент на основе ClashMeta: простой и удобный, с открытым исходным кодом и без рекламы.", ), @@ -387,7 +471,7 @@ class MessageLookup extends MessageLookupByLibrary { "destinationIPASN": MessageLookupByLibrary.simpleMessage( "ASN IP назначения", ), - "details": m6, + "details": m7, "detectionTip": MessageLookupByLibrary.simpleMessage( "Использует сторонний API; только для справки", ), @@ -395,23 +479,116 @@ class MessageLookup extends MessageLookupByLibrary { "developerModeEnableTip": MessageLookupByLibrary.simpleMessage( "Режим разработчика включён.", ), + "dialerProxy": MessageLookupByLibrary.simpleMessage( + "Прокси для подключения", + ), + "dialerProxyDesc": MessageLookupByLibrary.simpleMessage( + "Исход, через который идёт обращение к NTP-серверу", + ), "direct": MessageLookupByLibrary.simpleMessage("Прямой"), "disableUDP": MessageLookupByLibrary.simpleMessage("Отключить UDP"), + "disabled": MessageLookupByLibrary.simpleMessage("Выключено"), + "discardChanges": MessageLookupByLibrary.simpleMessage( + "Отменить изменения?", + ), "disclaimer": MessageLookupByLibrary.simpleMessage( "Отказ от ответственности", ), + "disclaimerAcceptContent": MessageLookupByLibrary.simpleMessage( + "Устанавливая, копируя или используя Программу, вы подтверждаете, что прочитали и приняли это заявление полностью. Если вы не согласны с каким-либо его условием, немедленно прекратите использование и удалите Программу.", + ), + "disclaimerAcceptTitle": MessageLookupByLibrary.simpleMessage( + "Принятие условий", + ), + "disclaimerAnalyticsContent": MessageLookupByLibrary.simpleMessage( + "Вместе с Firebase автоматически собирается базовая статистика использования приложения.\n\nЧто собирается: базовые события, такие как первый запуск, открытие приложения и длительность сеанса, обновление приложения; идентификатор экземпляра приложения; модель устройства, версия ОС и язык системы; приблизительное местоположение на уровне страны или региона, определённое по IP-адресу.\n\nЦель: только оценка числа активных устройств, распределения версий и совместимости с ОС. Разработчики не используют эти данные для рекламы, не продают их и не связывают с вашими подписками или конфигурациями.", + ), + "disclaimerAnalyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Analytics (статистика использования)", + ), + "disclaimerAndroidOnly": MessageLookupByLibrary.simpleMessage( + "Только Android", + ), + "disclaimerChangesContent": MessageLookupByLibrary.simpleMessage( + "Разработчики могут изменять это заявление в любом выпуске; изменения вступают в силу с момента публикации выпуска. Продолжая пользоваться Программой после обновления, вы принимаете изменённое заявление.", + ), + "disclaimerChangesTitle": MessageLookupByLibrary.simpleMessage( + "Изменения заявления", + ), + "disclaimerCrashlyticsContent": MessageLookupByLibrary.simpleMessage( + "При сбое приложения отчёт о сбое отправляется автоматически.\n\nЧто собирается: трассировка стека и сообщение об ошибке, время сбоя, версия и номер сборки приложения, производитель и модель устройства, версия Android, ориентация экрана, свободная память и место в хранилище, наличие root-доступа, а также случайный идентификатор установки, который создаётся при установке и сбрасывается при переустановке.\n\nЦель: только поиск и исправление сбоев.\n\nВы можете отключить это в любой момент: «Инструменты > Общие > Аналитика сбоев».", + ), + "disclaimerCrashlyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Crashlytics (аналитика сбоев)", + ), + "disclaimerDataProcessingContent": MessageLookupByLibrary.simpleMessage( + "Эти данные обрабатываются и хранятся компанией Google от нашего имени, могут передаваться на серверы за пределами вашей страны или региона (например, в США) и регулируются Политикой конфиденциальности Google и документацией Firebase о конфиденциальности и безопасности. Отчёты о сбоях хранятся до 90 дней; статистика хранится в соответствии с политикой хранения Firebase по умолчанию.", + ), "disclaimerDesc": MessageLookupByLibrary.simpleMessage( - "Это программное обеспечение предназначено только для некоммерческого использования: обучения, обмена опытом и научных исследований. Коммерческое использование строго запрещено; любая коммерческая деятельность не имеет отношения к этому программному обеспечению.", + "Перед использованием FlClash (далее — «Программа») внимательно прочитайте это заявление и убедитесь, что понимаете его полностью. Нажимая «Согласен», вы подтверждаете, что прочитали, поняли и принимаете все приведённые ниже условия. Если вы не согласны, нажмите «Выход» и прекратите использование Программы.", + ), + "disclaimerFirebasePrivacy": MessageLookupByLibrary.simpleMessage( + "Конфиденциальность и безопасность Firebase", + ), + "disclaimerGooglePrivacy": MessageLookupByLibrary.simpleMessage( + "Политика конфиденциальности Google", + ), + "disclaimerLiabilityContent": MessageLookupByLibrary.simpleMessage( + "В максимальной степени, допустимой применимым законодательством, ни разработчики, ни участники проекта не несут ответственности за любой прямой, косвенный, случайный, особый, штрафной или последующий ущерб, возникший в результате использования или невозможности использования Программы, включая, помимо прочего, потерю данных, повреждение устройства, сбои сети, прерывание деятельности, упущенную выгоду или связанные с этим правовые споры, даже если они были предупреждены о возможности такого ущерба.", + ), + "disclaimerLiabilityTitle": MessageLookupByLibrary.simpleMessage( + "Ограничение ответственности", + ), + "disclaimerLicenseContent": MessageLookupByLibrary.simpleMessage( + "Программа распространяется с открытым исходным кодом по лицензии GPL-3.0. Вы можете свободно использовать, изменять и распространять её при соблюдении этой лицензии: производные работы также должны распространяться по GPL-3.0 с сохранением уведомлений об авторских правах.\n\nСторонние компоненты Программы, включая ядро Clash.Meta, распространяются по своим собственным лицензиям. Авторы оригинала не несут ответственности за проблемы, возникшие в изменённых или распространяемых третьими лицами версиях.", + ), + "disclaimerLicenseTitle": MessageLookupByLibrary.simpleMessage( + "Лицензия с открытым исходным кодом", + ), + "disclaimerPrivacyContent": MessageLookupByLibrary.simpleMessage( + "Программа не собирает и не отправляет адреса ваших подписок, сведения об узлах, содержимое конфигураций, посещённые сайты, записи о подключениях, содержимое трафика и журналы. Эти данные хранятся только на вашем устройстве, и у разработчиков нет к ним доступа.\n\nПрограмма обращается к сети только при использовании соответствующих функций, например загружает указанный вами адрес подписки при обновлении профиля или обращается к GitHub при проверке обновлений.\n\nНастольные версии (Windows, macOS, Linux) не содержат никаких сервисов статистики или отчётов о сбоях. Версия для Android использует два сервиса Google Firebase для повышения стабильности:", + ), + "disclaimerPrivacyTitle": MessageLookupByLibrary.simpleMessage( + "Сбор данных и конфиденциальность", + ), + "disclaimerResponsibilityContent": MessageLookupByLibrary.simpleMessage( + "Вы самостоятельно убеждаетесь, что использование Программы законно в вашей стране или регионе, и единолично несёте юридическую ответственность за все действия с ней и их последствия.\n\nПодписки, узлы и конфигурации, которые вы импортируете, выбираете вы сами. Законность их источника, безопасность содержимого и надёжность сервиса — вопрос между вами и их поставщиками.", + ), + "disclaimerResponsibilityTitle": MessageLookupByLibrary.simpleMessage( + "Ваша ответственность", + ), + "disclaimerSoftwareContent": MessageLookupByLibrary.simpleMessage( + "Программа — это клиент сетевого прокси с открытым исходным кодом на основе ядра Clash.Meta (mihomo). Она предоставляет только локальные инструменты: управление конфигурациями, маршрутизацию по правилам и пересылку трафика.\n\nСама Программа не предоставляет прокси-серверы, узлы, подписки или услуги доступа к сети и не состоит в партнёрских, агентских или гарантийных отношениях с поставщиками таких услуг.", + ), + "disclaimerSoftwareTitle": MessageLookupByLibrary.simpleMessage( + "Характер программы", + ), + "disclaimerThirdPartyContent": MessageLookupByLibrary.simpleMessage( + "Ссылки на подписки, файлы конфигурации, наборы правил, скрипты, внешние ресурсы и внешние ссылки предоставляются третьими лицами. Разработчики не могут проверять и не проверяют их законность, точность, безопасность и доступность и не дают на них никаких гарантий.\n\nУтечка данных, финансовые потери, блокировка аккаунта или иной ущерб, вызванные сторонним контентом, урегулируются между вами и третьим лицом; разработчики не несут за это никакой ответственности.", + ), + "disclaimerThirdPartyTitle": MessageLookupByLibrary.simpleMessage( + "Сторонний контент", + ), + "disclaimerUsageContent": MessageLookupByLibrary.simpleMessage( + "Программа предназначена только для некоммерческого использования: обучения, обмена опытом и технических исследований. Любое коммерческое использование строго запрещено, включая, помимо прочего, платное распространение, продажу в комплекте, использование в составе коммерческого сервиса или ведение деятельности от имени Программы. Любая коммерческая деятельность не имеет отношения к Программе и её разработчикам.\n\nСтрого запрещено использовать Программу для действий, нарушающих законы вашей страны или региона, включая, помимо прочего, обход законно установленных ограничений доступа к сети, распространение незаконной информации, сетевые атаки и нарушение законных прав других лиц.", + ), + "disclaimerUsageTitle": MessageLookupByLibrary.simpleMessage( + "Ограничения использования", + ), + "disclaimerWarrantyContent": MessageLookupByLibrary.simpleMessage( + "Программа предоставляется «как есть» и «по мере доступности», без каких-либо явных или подразумеваемых гарантий, включая, помимо прочего, гарантии товарной пригодности, пригодности для определённой цели, ненарушения прав, бесперебойной работы, отсутствия ошибок и уязвимостей.\n\nРазработчики не гарантируют, что Программа будет соответствовать вашим потребностям или работать без сбоев и ошибок.", + ), + "disclaimerWarrantyTitle": MessageLookupByLibrary.simpleMessage( + "Отсутствие гарантий", ), "disconnected": MessageLookupByLibrary.simpleMessage("Отключено"), "discoverNewVersion": MessageLookupByLibrary.simpleMessage( "Доступна новая версия", ), - "dnsDesc": MessageLookupByLibrary.simpleMessage( - "Настройки, связанные с DNS", - ), "dnsHijacking": MessageLookupByLibrary.simpleMessage("Перехват DNS"), "dnsMode": MessageLookupByLibrary.simpleMessage("Режим DNS"), + "dnsQueries": MessageLookupByLibrary.simpleMessage("DNS-запросы"), + "docked": MessageLookupByLibrary.simpleMessage("Закреплённая"), "domain": MessageLookupByLibrary.simpleMessage("Домен"), "download": MessageLookupByLibrary.simpleMessage("Загрузка"), "edit": MessageLookupByLibrary.simpleMessage("Редактировать"), @@ -424,10 +601,14 @@ class MessageLookup extends MessageLookupByLibrary { ), "editRule": MessageLookupByLibrary.simpleMessage("Редактировать правило"), "editSsid": MessageLookupByLibrary.simpleMessage("Изменить SSID"), - "emptyTip": m7, + "editorUnavailable": MessageLookupByLibrary.simpleMessage( + "Редактор недоступен", + ), + "emptyTip": m8, "en": MessageLookupByLibrary.simpleMessage("Английский"), + "enabled": MessageLookupByLibrary.simpleMessage("Включено"), "entries": MessageLookupByLibrary.simpleMessage(" записей"), - "entriesCount": m8, + "error": MessageLookupByLibrary.simpleMessage("Ошибка"), "exclude": MessageLookupByLibrary.simpleMessage("Скрыть из недавних задач"), "excludeDesc": MessageLookupByLibrary.simpleMessage( "Скрывать приложение из недавних задач, когда оно в фоне", @@ -458,14 +639,20 @@ class MessageLookup extends MessageLookupByLibrary { "externalControllerDesc": MessageLookupByLibrary.simpleMessage( "При включении ядром Clash можно управлять через порт 9090", ), - "externalFetch": MessageLookupByLibrary.simpleMessage("Внешнее получение"), "externalLink": MessageLookupByLibrary.simpleMessage("Внешняя ссылка"), + "fade": MessageLookupByLibrary.simpleMessage("Растворение"), "fakeipFilter": MessageLookupByLibrary.simpleMessage("Фильтр Fake-IP"), - "fakeipRange": MessageLookupByLibrary.simpleMessage("Диапазон Fake-IP"), - "fallback": MessageLookupByLibrary.simpleMessage("Fallback"), - "fallbackDesc": MessageLookupByLibrary.simpleMessage( - "Обычно зарубежный DNS", + "fakeipFilterMode": MessageLookupByLibrary.simpleMessage( + "Режим фильтра Fake-IP", ), + "fakeipFilterModeDesc": MessageLookupByLibrary.simpleMessage( + "blacklist исключает совпадения, whitelist — только их, rule — по правилам", + ), + "fakeipRange": MessageLookupByLibrary.simpleMessage("Диапазон Fake-IP"), + "fakeipRange6": MessageLookupByLibrary.simpleMessage( + "Диапазон Fake-IP (IPv6)", + ), + "fakeipTtl": MessageLookupByLibrary.simpleMessage("TTL Fake-IP"), "fallbackFilter": MessageLookupByLibrary.simpleMessage("Фильтр fallback"), "fidelityScheme": MessageLookupByLibrary.simpleMessage("Точная передача"), "file": MessageLookupByLibrary.simpleMessage("Файл"), @@ -475,15 +662,16 @@ class MessageLookup extends MessageLookupByLibrary { "fileIsUpdate": MessageLookupByLibrary.simpleMessage( "Файл изменён. Сохранить изменения?", ), + "filter": MessageLookupByLibrary.simpleMessage("Фильтр"), "findProcessMode": MessageLookupByLibrary.simpleMessage("Поиск процесса"), - "findProcessModeDesc": MessageLookupByLibrary.simpleMessage( - "При включении возможна небольшая потеря производительности", - ), + "floating": MessageLookupByLibrary.simpleMessage("Плавающая"), "followProfile": MessageLookupByLibrary.simpleMessage("Как в профиле"), + "followSystem": MessageLookupByLibrary.simpleMessage("Как в системе"), "fontFamily": MessageLookupByLibrary.simpleMessage("Шрифт"), "forceRestartCoreTip": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите принудительно перезапустить ядро?", ), + "format": MessageLookupByLibrary.simpleMessage("Формат"), "fruitSaladScheme": MessageLookupByLibrary.simpleMessage("Фруктовый микс"), "general": MessageLookupByLibrary.simpleMessage("Общие"), "geoAutoUpdate": MessageLookupByLibrary.simpleMessage("Автообновление"), @@ -500,10 +688,6 @@ class MessageLookup extends MessageLookupByLibrary { "geodataLoader": MessageLookupByLibrary.simpleMessage( "Geo: экономия памяти", ), - "geodataLoaderDesc": MessageLookupByLibrary.simpleMessage( - "При включении используется Geo-загрузчик с низким потреблением памяти", - ), - "geoipCode": MessageLookupByLibrary.simpleMessage("Код GeoIP"), "global": MessageLookupByLibrary.simpleMessage("Глобальный"), "go": MessageLookupByLibrary.simpleMessage("Перейти"), "goDownload": MessageLookupByLibrary.simpleMessage("Скачать"), @@ -517,22 +701,34 @@ class MessageLookup extends MessageLookupByLibrary { "Служба Helper недоступна, поэтому TUN-режим включить нельзя. Переустановите FlClash.", ), "hideFromList": MessageLookupByLibrary.simpleMessage("Скрыть из списка"), + "hideIp": MessageLookupByLibrary.simpleMessage("Скрыть IP"), "hidePassword": MessageLookupByLibrary.simpleMessage("Скрыть пароль"), + "hideTimeoutProxies": MessageLookupByLibrary.simpleMessage( + "Скрывать узлы с таймаутом", + ), + "hideTimeoutProxiesDesc": MessageLookupByLibrary.simpleMessage( + "Не показывать узлы, у которых последний тест задержки завершился таймаутом", + ), "host": MessageLookupByLibrary.simpleMessage("Хост"), - "hostsDesc": MessageLookupByLibrary.simpleMessage("Добавить записи hosts"), - "hotkeyConflict": MessageLookupByLibrary.simpleMessage( - "Конфликт горячих клавиш", + "hotkeyConflictWith": m12, + "hotkeyDesc": MessageLookupByLibrary.simpleMessage( + "Глобальные горячие клавиши работают, даже когда окно скрыто. Нажмите на действие, чтобы записать сочетание клавиш.", ), "hotkeyManagement": MessageLookupByLibrary.simpleMessage("Горячие клавиши"), - "hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage( - "Управление приложением с клавиатуры", + "hotkeyNeedsModifier": m13, + "hotkeyNotSet": MessageLookupByLibrary.simpleMessage("Не задано"), + "hotkeyUnavailable": MessageLookupByLibrary.simpleMessage( + "Не зарегистрировано: сочетание может быть занято другим приложением", ), "hours": MessageLookupByLibrary.simpleMessage("часов"), - "hoursAgo": m12, - "hoursCount": m13, + "hoursAgo": m14, + "hoursCount": m15, "icon": MessageLookupByLibrary.simpleMessage("Значок"), "iconRecords": MessageLookupByLibrary.simpleMessage("История значков"), "iconStyle": MessageLookupByLibrary.simpleMessage("Стиль значков"), + "iconStyleFilled": MessageLookupByLibrary.simpleMessage("С подложкой"), + "iconStyleHidden": MessageLookupByLibrary.simpleMessage("Скрыто"), + "iconStylePlain": MessageLookupByLibrary.simpleMessage("Без подложки"), "iconUrl": MessageLookupByLibrary.simpleMessage("URL значка"), "ignoreBatteryOptimization": MessageLookupByLibrary.simpleMessage( "Игнорировать оптимизацию батареи", @@ -552,13 +748,11 @@ class MessageLookup extends MessageLookupByLibrary { "Включить всех провайдеров прокси", ), "includeAllProxyProvidersTip": MessageLookupByLibrary.simpleMessage( - "При включении переопределяет подключённых провайдеров прокси", + "При включении группа берёт всех провайдеров прокси этого профиля: собственных провайдеров подписки, а также профили и прокси-провайдеры приложения, которые использует любая группа прокси", ), "infiniteTime": MessageLookupByLibrary.simpleMessage("Бессрочно"), "init": MessageLookupByLibrary.simpleMessage("Инициализация"), - "inputCorrectHotkey": MessageLookupByLibrary.simpleMessage( - "Введите корректную горячую клавишу", - ), + "initiator": MessageLookupByLibrary.simpleMessage("Инициатор"), "inputProxyGroupName": MessageLookupByLibrary.simpleMessage( "Введите название группы прокси", ), @@ -593,17 +787,60 @@ class MessageLookup extends MessageLookupByLibrary { "invalidBackupFile": MessageLookupByLibrary.simpleMessage( "Недопустимый файл резервной копии", ), - "invalidPolicy": m14, - "invalidProxy": m15, - "invalidProxyProvider": m16, - "invalidSubRule": m17, - "ipcidr": MessageLookupByLibrary.simpleMessage("IP/CIDR"), + "invalidDscpContent": MessageLookupByLibrary.simpleMessage( + "Метка DSCP не может превышать 63", + ), + "invalidNetworkContent": MessageLookupByLibrary.simpleMessage( + "Поддерживаются только tcp и udp", + ), + "invalidPolicy": m16, + "invalidProfileQrcode": MessageLookupByLibrary.simpleMessage( + "Этот QR-код не содержит ссылку на профиль", + ), + "invalidProxy": m17, + "invalidProxyProvider": m18, + "invalidRangeContent": MessageLookupByLibrary.simpleMessage( + "Введите числа или диапазоны, например 80 или 8000-9000, через /", + ), + "invalidRuleSet": m19, + "invalidSubRule": m20, + "ipAddress": MessageLookupByLibrary.simpleMessage("IP-адрес"), + "ipAsn": MessageLookupByLibrary.simpleMessage("ASN"), + "ipFlagAbuser": MessageLookupByLibrary.simpleMessage("Злоупотребления"), + "ipFlagProxy": MessageLookupByLibrary.simpleMessage("Прокси"), + "ipFlagTor": MessageLookupByLibrary.simpleMessage("Tor"), + "ipFlagVpn": MessageLookupByLibrary.simpleMessage("VPN"), + "ipFlags": MessageLookupByLibrary.simpleMessage("Метки"), + "ipOrganization": MessageLookupByLibrary.simpleMessage("Организация"), + "ipQualityFailed": MessageLookupByLibrary.simpleMessage( + "Не удалось определить тип IP", + ), + "ipQualityGood": MessageLookupByLibrary.simpleMessage("Хороший"), + "ipQualityLevel": MessageLookupByLibrary.simpleMessage("Уровень"), + "ipQualityNormal": MessageLookupByLibrary.simpleMessage("Обычный"), + "ipQualityRetry": MessageLookupByLibrary.simpleMessage("Проверить снова"), + "ipQualityRisky": MessageLookupByLibrary.simpleMessage("Рискованный"), + "ipQualitySource": MessageLookupByLibrary.simpleMessage("Источник ответа"), + "ipQualitySources": MessageLookupByLibrary.simpleMessage("Источники"), + "ipSourceIpMismatch": MessageLookupByLibrary.simpleMessage( + "Другой исходящий IP", + ), + "ipSourceNoType": MessageLookupByLibrary.simpleMessage("Тип не определён"), + "ipSourceRateLimited": MessageLookupByLibrary.simpleMessage( + "Лимит запросов", + ), + "ipType": MessageLookupByLibrary.simpleMessage("Тип"), + "ipTypeBusiness": MessageLookupByLibrary.simpleMessage("Бизнес"), + "ipTypeHosting": MessageLookupByLibrary.simpleMessage("Дата-центр"), + "ipTypeMobile": MessageLookupByLibrary.simpleMessage("Мобильная сеть"), + "ipTypeResidential": MessageLookupByLibrary.simpleMessage("Домашний"), "ipv6Desc": MessageLookupByLibrary.simpleMessage( "При включении можно принимать трафик IPv6", ), "ipv6InboundDesc": MessageLookupByLibrary.simpleMessage( "Разрешить входящий IPv6", ), + "ipv6Timeout": MessageLookupByLibrary.simpleMessage("Тайм-аут IPv6 (мс)"), "ja": MessageLookupByLibrary.simpleMessage("Японский"), "justNow": MessageLookupByLibrary.simpleMessage("Только что"), "keepAliveIntervalDesc": MessageLookupByLibrary.simpleMessage( @@ -619,13 +856,21 @@ class MessageLookup extends MessageLookupByLibrary { ), "layout": MessageLookupByLibrary.simpleMessage("Макет"), "light": MessageLookupByLibrary.simpleMessage("Светлая"), + "lineIssueTip": m21, + "lineWrap": MessageLookupByLibrary.simpleMessage("Перенос строк"), "list": MessageLookupByLibrary.simpleMessage("Список"), "listen": MessageLookupByLibrary.simpleMessage("Прослушивание"), - "loading": MessageLookupByLibrary.simpleMessage("Загрузка..."), - "local": MessageLookupByLibrary.simpleMessage("Локально"), - "localBackupDesc": MessageLookupByLibrary.simpleMessage( - "Резервное копирование данных локально", + "listenRoutingMark": MessageLookupByLibrary.simpleMessage( + "Метка маршрутизации", ), + "listenRoutingMarkDesc": MessageLookupByLibrary.simpleMessage( + "Только Linux", + ), + "liveConnections": MessageLookupByLibrary.simpleMessage( + "Активные соединения", + ), + "loading": MessageLookupByLibrary.simpleMessage("Загрузка…"), + "local": MessageLookupByLibrary.simpleMessage("Локально"), "locationPermission": MessageLookupByLibrary.simpleMessage( "Разрешение на геолокацию", ), @@ -635,7 +880,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationPermissionDesc": MessageLookupByLibrary.simpleMessage( "По требованию системы для получения имени сети Wi-Fi необходимо разрешение на геолокацию. На Android выберите «Разрешить всегда», иначе имя сети Wi-Fi нельзя получить, пока приложение в фоне.", ), - "locationPermissionGuide": m18, + "locationPermissionGuide": m22, "locationPermissionRequired": MessageLookupByLibrary.simpleMessage( "Требуется разрешение на геолокацию", ), @@ -646,31 +891,53 @@ class MessageLookup extends MessageLookupByLibrary { "При отключении раздел логов будет скрыт", ), "logs": MessageLookupByLibrary.simpleMessage("Логи"), - "logsDesc": MessageLookupByLibrary.simpleMessage( - "Записи захваченных логов", + "logsAndDiagnostics": MessageLookupByLibrary.simpleMessage( + "Логи и диагностика", ), "logsTest": MessageLookupByLibrary.simpleMessage("Тест логов"), "loopback": MessageLookupByLibrary.simpleMessage( - "Инструмент разблокировки loopback", - ), - "loopbackDesc": MessageLookupByLibrary.simpleMessage( - "Для снятия ограничения loopback у UWP-приложений", + "Снятие ограничения loopback для UWP", ), "loose": MessageLookupByLibrary.simpleMessage("Свободный"), "matchSourceIp": MessageLookupByLibrary.simpleMessage( "Сопоставлять IP источника", ), "matchTarget": MessageLookupByLibrary.simpleMessage("MATCH-TARGET"), - "matchTargetDesc": MessageLookupByLibrary.simpleMessage( - "Куда направляются правила с целью MATCH-TARGET. По умолчанию — цель последнего правила MATCH этого профиля.", - ), - "matchTargetTitle": MessageLookupByLibrary.simpleMessage("Цель MATCH"), "maxFailedTimes": MessageLookupByLibrary.simpleMessage( "Макс. число неудач", ), - "maxLengthTip": m19, + "maxLengthTip": m23, "maximize": MessageLookupByLibrary.simpleMessage("Развернуть"), + "memoryAppResident": MessageLookupByLibrary.simpleMessage( + "Резидентная память", + ), + "memoryAppShared": MessageLookupByLibrary.simpleMessage( + "Приложение и общая", + ), + "memoryCoreHeapIdle": MessageLookupByLibrary.simpleMessage( + "Свободная куча", + ), + "memoryCoreHeapInuse": MessageLookupByLibrary.simpleMessage( + "Используемая куча", + ), + "memoryCoreNotRunning": MessageLookupByLibrary.simpleMessage( + "Ядро не запущено", + ), + "memoryCoreRuntime": MessageLookupByLibrary.simpleMessage( + "Накладные расходы среды", + ), + "memoryCoreStack": MessageLookupByLibrary.simpleMessage("Стеки горутин"), + "memoryEstimateDesc": MessageLookupByLibrary.simpleMessage( + "Оценка по резидентной памяти процессов; может отличаться от данных системы.", + ), + "memoryEstimateSharedDesc": MessageLookupByLibrary.simpleMessage( + "Ядро работает в процессе приложения. Его доля оценивается по статистике среды выполнения, остальное относится к приложению и общей памяти.", + ), "memoryInfo": MessageLookupByLibrary.simpleMessage("Память"), + "memoryReleased": MessageLookupByLibrary.simpleMessage( + "Память освобождена", + ), + "memoryReleasedSize": m24, "messageTest": MessageLookupByLibrary.simpleMessage("Тест сообщения"), "messageTestTip": MessageLookupByLibrary.simpleMessage("Это сообщение."), "min": MessageLookupByLibrary.simpleMessage("Минимальный"), @@ -678,43 +945,45 @@ class MessageLookup extends MessageLookupByLibrary { "minimizeOnExit": MessageLookupByLibrary.simpleMessage( "Сворачивать при выходе", ), - "minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage( - "Изменяет стандартное поведение при выходе", - ), - "minutesAgo": m20, + "minutesAgo": m25, "mixedPort": MessageLookupByLibrary.simpleMessage("Смешанный порт"), "mode": MessageLookupByLibrary.simpleMessage("Режим"), "monochromeScheme": MessageLookupByLibrary.simpleMessage("Монохром"), - "monthsAgo": m21, + "monthsAgo": m26, "more": MessageLookupByLibrary.simpleMessage("Ещё"), - "multipleValuesTip": MessageLookupByLibrary.simpleMessage( - "Разделяйте несколько значений запятыми", - ), "name": MessageLookupByLibrary.simpleMessage("Название"), - "nameserver": MessageLookupByLibrary.simpleMessage("DNS-сервер"), - "nameserverDesc": MessageLookupByLibrary.simpleMessage( - "Используется для разрешения доменов", - ), - "nameserverPolicy": MessageLookupByLibrary.simpleMessage( - "Политика DNS-серверов", - ), - "nameserverPolicyDesc": MessageLookupByLibrary.simpleMessage( - "Задать политику DNS-серверов для доменов", - ), + "navigationBarStyle": MessageLookupByLibrary.simpleMessage("Нижняя панель"), "network": MessageLookupByLibrary.simpleMessage("Сеть"), - "networkDesc": MessageLookupByLibrary.simpleMessage( - "Настройки, связанные с сетью", + "networkAccessDeniedError": m27, + "networkBadResponseError": m28, + "networkCancelledError": MessageLookupByLibrary.simpleMessage( + "Запрос отменён", + ), + "networkConnectionError": MessageLookupByLibrary.simpleMessage( + "Не удалось подключиться к серверу. Проверьте подключение к сети или настройки прокси", ), "networkDetection": MessageLookupByLibrary.simpleMessage("Проверка сети"), - "networkException": MessageLookupByLibrary.simpleMessage( - "Ошибка сети. Проверьте подключение и повторите попытку", + "networkHostLookupError": MessageLookupByLibrary.simpleMessage( + "Не удалось определить адрес сервера. Проверьте правильность URL и работу DNS", ), + "networkNotFoundError": m29, + "networkRateLimitedError": MessageLookupByLibrary.simpleMessage( + "Слишком много запросов (HTTP 429). Подождите немного и повторите попытку", + ), + "networkRequestFailed": m30, + "networkServerError": m31, "networkSpeed": MessageLookupByLibrary.simpleMessage("Скорость сети"), + "networkTimeoutError": MessageLookupByLibrary.simpleMessage( + "Время ожидания запроса истекло. Проверьте сеть или прокси и повторите попытку", + ), + "networkTlsError": MessageLookupByLibrary.simpleMessage( + "Не удалось установить защищённое соединение. Сертификат сервера может быть недействителен, или соединение перехватывается", + ), "networkType": MessageLookupByLibrary.simpleMessage("Тип сети"), "neutralScheme": MessageLookupByLibrary.simpleMessage("Нейтральная"), "nextMatch": MessageLookupByLibrary.simpleMessage("Следующее совпадение"), + "no": MessageLookupByLibrary.simpleMessage("Нет"), "noData": MessageLookupByLibrary.simpleMessage("Нет данных"), - "noHotKey": MessageLookupByLibrary.simpleMessage("Горячих клавиш пока нет"), "noInfo": MessageLookupByLibrary.simpleMessage("Нет информации"), "noLongerRemind": MessageLookupByLibrary.simpleMessage( "Больше не напоминать", @@ -726,25 +995,33 @@ class MessageLookup extends MessageLookupByLibrary { "noResolveHostname": MessageLookupByLibrary.simpleMessage( "Не разрешать имя хоста", ), + "noSearchResults": MessageLookupByLibrary.simpleMessage( + "Ничего не найдено", + ), + "nonTextProviderFile": MessageLookupByLibrary.simpleMessage( + "Этот внешний ресурс не является текстовым файлом", + ), "none": MessageLookupByLibrary.simpleMessage("Нет"), "notSelectedTip": MessageLookupByLibrary.simpleMessage( "Текущую группу прокси нельзя выбрать", ), - "nullProfileDesc": MessageLookupByLibrary.simpleMessage( - "Профилей пока нет. Сначала добавьте профиль", + "ntpInterval": MessageLookupByLibrary.simpleMessage( + "Интервал синхронизации (минуты)", ), - "nullTip": m22, - "numberTip": m23, + "ntpStatusDesc": MessageLookupByLibrary.simpleMessage( + "Брать время с NTP-сервера, а не из системных часов", + ), + "nullProfileDesc": MessageLookupByLibrary.simpleMessage( + "Добавьте профиль, чтобы начать", + ), + "nullTip": m32, + "numberTip": m33, "onDemand": MessageLookupByLibrary.simpleMessage("По условию"), "onDemandDesc": MessageLookupByLibrary.simpleMessage( "Настройте состояние работы приложения для определённых сценариев", ), - "onlyIcon": MessageLookupByLibrary.simpleMessage("Только значок"), "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage( - "Учитывать только прокси", - ), - "onlyStatisticsProxyDesc": MessageLookupByLibrary.simpleMessage( - "При включении учитывается только трафик через прокси", + "Учитывать только трафик прокси", ), "optional": MessageLookupByLibrary.simpleMessage("Необязательно"), "options": MessageLookupByLibrary.simpleMessage("Опции"), @@ -752,25 +1029,42 @@ class MessageLookup extends MessageLookupByLibrary { "otherContributors": MessageLookupByLibrary.simpleMessage( "Другие участники", ), + "outboundIp": MessageLookupByLibrary.simpleMessage("Исходящий IP"), "outboundMode": MessageLookupByLibrary.simpleMessage( "Режим исходящего трафика", ), "override": MessageLookupByLibrary.simpleMessage("Переопределение"), "overrideDns": MessageLookupByLibrary.simpleMessage("Переопределить DNS"), - "overrideDnsDesc": MessageLookupByLibrary.simpleMessage( - "При включении настройки DNS профиля переопределяются", + "overrideEntries": MessageLookupByLibrary.simpleMessage( + "Переопределяемые параметры", ), "overrideMode": MessageLookupByLibrary.simpleMessage( "Режим переопределения", ), + "overrideNtp": MessageLookupByLibrary.simpleMessage("Переопределить NTP"), "overrideScript": MessageLookupByLibrary.simpleMessage( "Скрипт переопределения", ), + "overwriteIssueCoreRejected": m34, + "overwriteIssueDuplicateName": m35, + "overwriteIssueEmptyName": MessageLookupByLibrary.simpleMessage( + "Имя не задано", + ), + "overwriteIssueGroupLoop": m36, + "overwriteIssueMissingProviders": m37, + "overwriteIssueMissingProxies": m38, + "overwriteIssueNoProxySource": MessageLookupByLibrary.simpleMessage( + "Не выбраны ни прокси, ни провайдеры прокси, поэтому ядро отклонит эту группу", + ), + "overwriteIssueProviderShadowed": m39, + "overwriteIssueReservedName": m40, + "overwriteIssueSubscriptionGroupMissingProxies": m41, + "overwriteIssuesSummary": m42, "overwriteTypeCustom": MessageLookupByLibrary.simpleMessage( "Пользовательский", ), "overwriteTypeCustomDesc": MessageLookupByLibrary.simpleMessage( - "Пользовательский режим: полная настройка групп прокси и правил", + "Пользовательский режим: полная настройка прокси, групп прокси и правил", ), "palette": MessageLookupByLibrary.simpleMessage("Палитра"), "password": MessageLookupByLibrary.simpleMessage("Пароль"), @@ -792,14 +1086,13 @@ class MessageLookup extends MessageLookupByLibrary { "portConflictTip": MessageLookupByLibrary.simpleMessage( "Введите другой порт", ), - "portTip": m24, - "preferH3Desc": MessageLookupByLibrary.simpleMessage( - "Предпочитать HTTP/3 для DoH", - ), + "portTip": m43, "prerequisites": MessageLookupByLibrary.simpleMessage( "Предварительные условия", ), - "pressKeyboard": MessageLookupByLibrary.simpleMessage("Нажмите клавишу"), + "pressKeyboard": MessageLookupByLibrary.simpleMessage( + "Нажмите сочетание клавиш", + ), "preview": MessageLookupByLibrary.simpleMessage("Предпросмотр"), "previousMatch": MessageLookupByLibrary.simpleMessage( "Предыдущее совпадение", @@ -825,37 +1118,34 @@ class MessageLookup extends MessageLookupByLibrary { "profiles": MessageLookupByLibrary.simpleMessage("Профили"), "profilesSort": MessageLookupByLibrary.simpleMessage("Сортировка профилей"), "project": MessageLookupByLibrary.simpleMessage("Проект"), + "providerInUse": m44, + "providerRenameShadowed": m45, + "providerSourceSubscription": MessageLookupByLibrary.simpleMessage( + "Подписка", + ), + "providerUrlTip": MessageLookupByLibrary.simpleMessage( + "Поддерживаются только удалённые ресурсы", + ), "providers": MessageLookupByLibrary.simpleMessage("Внешние ресурсы"), "proxies": MessageLookupByLibrary.simpleMessage("Прокси"), - "proxiesCount": m25, + "proxiesCount": m46, "proxiesEmpty": MessageLookupByLibrary.simpleMessage("Список прокси пуст"), "proxyChains": MessageLookupByLibrary.simpleMessage("Цепочка прокси"), - "proxyDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "Обнаружены отклонения в выбранных прокси", + "proxyDefinition": MessageLookupByLibrary.simpleMessage( + "Полная конфигурация", + ), + "proxyDefinitionNotMap": MessageLookupByLibrary.simpleMessage( + "Конфигурация должна быть YAML-словарём с полями name и type", ), "proxyFilter": MessageLookupByLibrary.simpleMessage("Фильтр узлов"), "proxyGroup": MessageLookupByLibrary.simpleMessage("Группа прокси"), - "proxyGroupDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "Обнаружены отклонения в текущей группе прокси", - ), "proxyGroupEmpty": MessageLookupByLibrary.simpleMessage( "Группа прокси пуста", ), "proxyGroupNameDuplicate": MessageLookupByLibrary.simpleMessage( "Название группы прокси уже используется", ), - "proxyGroupNameEmpty": MessageLookupByLibrary.simpleMessage( - "Название группы прокси не может быть пустым", - ), - "proxyNameserver": MessageLookupByLibrary.simpleMessage( - "DNS-сервер для прокси", - ), - "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage( - "Используется для разрешения доменов прокси-узлов", - ), - "proxyProviderDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "Обнаружены отклонения в выбранных провайдерах прокси", - ), + "proxyNode": MessageLookupByLibrary.simpleMessage("Прокси-узел"), "proxyProviders": MessageLookupByLibrary.simpleMessage("Провайдеры прокси"), "proxyProvidersEmpty": MessageLookupByLibrary.simpleMessage( "Список провайдеров прокси пуст", @@ -865,27 +1155,35 @@ class MessageLookup extends MessageLookupByLibrary { ), "proxyType": MessageLookupByLibrary.simpleMessage("Тип прокси"), "pruneCache": MessageLookupByLibrary.simpleMessage("Очистить кэш"), + "pureBlack": MessageLookupByLibrary.simpleMessage("Чисто чёрный"), "pureBlackMode": MessageLookupByLibrary.simpleMessage("Чисто чёрный режим"), "qrcode": MessageLookupByLibrary.simpleMessage("QR-код"), "qrcodeDesc": MessageLookupByLibrary.simpleMessage( "Сканируйте QR-код, чтобы получить профиль", ), + "quickAdd": MessageLookupByLibrary.simpleMessage("Быстрое добавление"), + "quickEdit": MessageLookupByLibrary.simpleMessage("Быстрое редактирование"), "quickFill": MessageLookupByLibrary.simpleMessage("Быстрое заполнение"), "rainbowScheme": MessageLookupByLibrary.simpleMessage("Радуга"), + "recentRequests": MessageLookupByLibrary.simpleMessage("Последние запросы"), + "recordType": MessageLookupByLibrary.simpleMessage("Тип записи"), "redirPort": MessageLookupByLibrary.simpleMessage("Порт Redir"), "redo": MessageLookupByLibrary.simpleMessage("Повторить"), - "remote": MessageLookupByLibrary.simpleMessage("Удалённо"), - "remoteBackupDesc": MessageLookupByLibrary.simpleMessage( - "Резервное копирование данных в WebDAV", + "releaseMemory": MessageLookupByLibrary.simpleMessage("Освободить память"), + "releaseMemoryFailed": MessageLookupByLibrary.simpleMessage( + "Не удалось освободить память", ), + "remote": MessageLookupByLibrary.simpleMessage("Удалённо"), "remoteDestination": MessageLookupByLibrary.simpleMessage( "Удалённое назначение", ), "remove": MessageLookupByLibrary.simpleMessage("Убрать"), + "replace": MessageLookupByLibrary.simpleMessage("Заменить"), + "replaceAll": MessageLookupByLibrary.simpleMessage("Заменить все"), "request": MessageLookupByLibrary.simpleMessage("Запрос"), "requests": MessageLookupByLibrary.simpleMessage("Запросы"), - "requestsDesc": MessageLookupByLibrary.simpleMessage( - "Просмотр последних запросов", + "requestsAndUpdates": MessageLookupByLibrary.simpleMessage( + "Запросы и обновления", ), "reset": MessageLookupByLibrary.simpleMessage("Сброс"), "resetPageChangesTip": MessageLookupByLibrary.simpleMessage( @@ -895,13 +1193,11 @@ class MessageLookup extends MessageLookupByLibrary { "Вы уверены, что хотите выполнить сброс?", ), "resources": MessageLookupByLibrary.simpleMessage("Ресурсы"), - "resourcesDesc": MessageLookupByLibrary.simpleMessage( - "Сведения о внешних ресурсах", - ), "respectRules": MessageLookupByLibrary.simpleMessage("Соблюдать правила"), "respectRulesDesc": MessageLookupByLibrary.simpleMessage( - "DNS-соединения следуют правилам; требуется настроить proxy-server-nameserver", + "DNS-соединения следуют правилам; требуется Proxy Server Nameserver", ), + "responseCode": MessageLookupByLibrary.simpleMessage("Код ответа"), "restart": MessageLookupByLibrary.simpleMessage("Перезапустить"), "restartCoreTip": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите перезапустить ядро?", @@ -910,15 +1206,6 @@ class MessageLookup extends MessageLookupByLibrary { "restoreAllData": MessageLookupByLibrary.simpleMessage( "Восстановить все данные", ), - "restoreException": MessageLookupByLibrary.simpleMessage( - "Ошибка восстановления", - ), - "restoreFromFileDesc": MessageLookupByLibrary.simpleMessage( - "Восстановить данные из файла", - ), - "restoreFromWebDAVDesc": MessageLookupByLibrary.simpleMessage( - "Восстановить данные из WebDAV", - ), "restoreOnlyConfig": MessageLookupByLibrary.simpleMessage( "Восстановить только профили", ), @@ -934,10 +1221,8 @@ class MessageLookup extends MessageLookupByLibrary { "restoreSuccess": MessageLookupByLibrary.simpleMessage( "Восстановление выполнено", ), + "retry": MessageLookupByLibrary.simpleMessage("Повторить"), "routeAddress": MessageLookupByLibrary.simpleMessage("Адреса маршрутов"), - "routeAddressDesc": MessageLookupByLibrary.simpleMessage( - "Настроить прослушиваемые адреса маршрутов", - ), "routeMode": MessageLookupByLibrary.simpleMessage("Режим маршрутизации"), "routeModeBypassPrivate": MessageLookupByLibrary.simpleMessage( "Обходить частные адреса", @@ -1060,10 +1345,31 @@ class MessageLookup extends MessageLookupByLibrary { ), "ruleEmpty": MessageLookupByLibrary.simpleMessage("Правило пусто"), "ruleName": MessageLookupByLibrary.simpleMessage("Название правила"), + "rulePresetBittorrentDirect": MessageLookupByLibrary.simpleMessage( + "BitTorrent напрямую", + ), + "rulePresetBlockDot": MessageLookupByLibrary.simpleMessage( + "Блокировать DNS over TLS", + ), + "rulePresetBlockQuic": MessageLookupByLibrary.simpleMessage( + "Блокировать QUIC", + ), + "rulePresetBlockStun": MessageLookupByLibrary.simpleMessage( + "Блокировать STUN", + ), + "rulePresetLanDirect": MessageLookupByLibrary.simpleMessage( + "Локальная сеть напрямую", + ), + "rulePresetSystemServicesDirect": MessageLookupByLibrary.simpleMessage( + "Apple и Microsoft напрямую", + ), + "ruleProviders": MessageLookupByLibrary.simpleMessage("Провайдеры правил"), "ruleSet": MessageLookupByLibrary.simpleMessage("Набор правил"), "ruleTarget": MessageLookupByLibrary.simpleMessage("Цель правила"), "rules": MessageLookupByLibrary.simpleMessage("Правила"), - "rulesCount": m26, + "rulesCount": m47, + "safeMode": MessageLookupByLibrary.simpleMessage("Безопасный режим"), + "safeModeAppTitle": m48, "save": MessageLookupByLibrary.simpleMessage("Сохранить"), "saveChanges": MessageLookupByLibrary.simpleMessage("Сохранить изменения?"), "script": MessageLookupByLibrary.simpleMessage("Скрипт"), @@ -1075,11 +1381,8 @@ class MessageLookup extends MessageLookupByLibrary { ), "search": MessageLookupByLibrary.simpleMessage("Поиск"), "seconds": MessageLookupByLibrary.simpleMessage("секунд"), - "secondsCount": m27, + "secondsCount": m49, "selectAll": MessageLookupByLibrary.simpleMessage("Выбрать всё"), - "selectMatchTarget": MessageLookupByLibrary.simpleMessage( - "Выбрать MATCH-TARGET", - ), "selectProxies": MessageLookupByLibrary.simpleMessage("Выбрать прокси"), "selectProxyProviders": MessageLookupByLibrary.simpleMessage( "Выбрать провайдеров прокси", @@ -1094,7 +1397,33 @@ class MessageLookup extends MessageLookupByLibrary { "Выберите подправило", ), "selected": MessageLookupByLibrary.simpleMessage("Выбрано"), - "selectedCountTitle": m28, + "selectedCountTitle": m50, + "server": MessageLookupByLibrary.simpleMessage("Сервер"), + "serviceAvailable": MessageLookupByLibrary.simpleMessage("Доступен"), + "serviceBlocked": MessageLookupByLibrary.simpleMessage("Заблокировано"), + "serviceCheck": MessageLookupByLibrary.simpleMessage("Проверить"), + "serviceCheckAll": MessageLookupByLibrary.simpleMessage("Проверить все"), + "serviceCheckedAt": m51, + "serviceComingSoon": MessageLookupByLibrary.simpleMessage("Скоро появится"), + "serviceDisallowedIsp": MessageLookupByLibrary.simpleMessage( + "Недопустимый провайдер", + ), + "serviceFailed": MessageLookupByLibrary.simpleMessage("Ошибка проверки"), + "serviceManage": MessageLookupByLibrary.simpleMessage( + "Управление сервисами", + ), + "serviceOriginalsOnly": MessageLookupByLibrary.simpleMessage( + "Только оригиналы", + ), + "servicePending": MessageLookupByLibrary.simpleMessage("Не проверено"), + "serviceRestricted": MessageLookupByLibrary.simpleMessage( + "Доступ ограничен", + ), + "serviceStatus": MessageLookupByLibrary.simpleMessage("Состояние сервисов"), + "serviceUnavailable": MessageLookupByLibrary.simpleMessage("Недоступен"), + "serviceUnsupportedRegion": MessageLookupByLibrary.simpleMessage( + "Регион не поддерживается", + ), "settings": MessageLookupByLibrary.simpleMessage("Настройки"), "show": MessageLookupByLibrary.simpleMessage("Показать"), "showLess": MessageLookupByLibrary.simpleMessage("Свернуть"), @@ -1102,16 +1431,22 @@ class MessageLookup extends MessageLookupByLibrary { "showNotificationStopAction": MessageLookupByLibrary.simpleMessage( "Кнопка остановки в уведомлении", ), - "showNotificationStopActionDesc": MessageLookupByLibrary.simpleMessage( - "Показывать кнопку остановки в постоянном уведомлении. Отключите, если из-за неё система всегда разворачивает уведомление", - ), "showPassword": MessageLookupByLibrary.simpleMessage("Показать пароль"), "shrink": MessageLookupByLibrary.simpleMessage("Компактный"), + "sidebarBlur": MessageLookupByLibrary.simpleMessage( + "Размытие боковой панели", + ), + "sidebarBlurDesc": MessageLookupByLibrary.simpleMessage( + "Показывать сквозь боковую панель размытый рабочий стол за окном", + ), "silentLaunch": MessageLookupByLibrary.simpleMessage("Тихий запуск"), "silentLaunchDesc": MessageLookupByLibrary.simpleMessage( - "Запускаться в фоновом режиме", + "Запускаться без показа окна", ), + "singleAdd": MessageLookupByLibrary.simpleMessage("По одному"), + "singleValueTip": m52, "size": MessageLookupByLibrary.simpleMessage("Размер"), + "slide": MessageLookupByLibrary.simpleMessage("Сдвиг"), "socksPort": MessageLookupByLibrary.simpleMessage("Порт SOCKS"), "sort": MessageLookupByLibrary.simpleMessage("Сортировка"), "source": MessageLookupByLibrary.simpleMessage("Источник"), @@ -1134,13 +1469,18 @@ class MessageLookup extends MessageLookupByLibrary { "Стандартный режим: переопределяет базовую конфигурацию и позволяет просто добавлять правила", ), "start": MessageLookupByLibrary.simpleMessage("Старт"), - "startVpn": MessageLookupByLibrary.simpleMessage("Запуск VPN..."), + "startFromScratch": MessageLookupByLibrary.simpleMessage("С нуля"), + "startVpn": MessageLookupByLibrary.simpleMessage("Запуск VPN…"), + "startupAndBackground": MessageLookupByLibrary.simpleMessage( + "Запуск и фоновая работа", + ), "status": MessageLookupByLibrary.simpleMessage("Статус"), "statusDesc": MessageLookupByLibrary.simpleMessage( "При отключении используется системный DNS", ), "stop": MessageLookupByLibrary.simpleMessage("Стоп"), - "stopVpn": MessageLookupByLibrary.simpleMessage("Остановка VPN..."), + "stopVpn": MessageLookupByLibrary.simpleMessage("Остановка VPN…"), + "strategy": MessageLookupByLibrary.simpleMessage("Стратегия"), "style": MessageLookupByLibrary.simpleMessage("Стиль"), "subRule": MessageLookupByLibrary.simpleMessage("Подправило"), "subRuleEmpty": MessageLookupByLibrary.simpleMessage("Подправило пусто"), @@ -1151,26 +1491,17 @@ class MessageLookup extends MessageLookupByLibrary { "subscriptionInfo": MessageLookupByLibrary.simpleMessage( "Информация о подписке", ), - "suspended": MessageLookupByLibrary.simpleMessage("Приостановлено..."), + "suspended": MessageLookupByLibrary.simpleMessage("Приостановлено…"), "sync": MessageLookupByLibrary.simpleMessage("Синхронизация"), "system": MessageLookupByLibrary.simpleMessage("Система"), "systemApp": MessageLookupByLibrary.simpleMessage("Системные приложения"), "systemProxy": MessageLookupByLibrary.simpleMessage("Системный прокси"), - "systemProxyDesc": MessageLookupByLibrary.simpleMessage( - "Настроить системный прокси", - ), "tab": MessageLookupByLibrary.simpleMessage("Вкладки"), "tabAnimation": MessageLookupByLibrary.simpleMessage("Анимация вкладок"), - "tabAnimationDesc": MessageLookupByLibrary.simpleMessage( - "Действует только в мобильном виде", - ), "tapToAuthorize": MessageLookupByLibrary.simpleMessage( "Нажмите, чтобы разрешить", ), "tcpConcurrent": MessageLookupByLibrary.simpleMessage("Параллельный TCP"), - "tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage( - "При включении разрешает параллельные TCP-подключения", - ), "testInterval": MessageLookupByLibrary.simpleMessage( "Интервал тестирования", ), @@ -1179,6 +1510,9 @@ class MessageLookup extends MessageLookupByLibrary { "Тестировать при использовании", ), "textScale": MessageLookupByLibrary.simpleMessage("Масштаб текста"), + "textScalePreview": MessageLookupByLibrary.simpleMessage( + "Так будет выглядеть текст в приложении", + ), "theme": MessageLookupByLibrary.simpleMessage("Тема"), "themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"), "themeDesc": MessageLookupByLibrary.simpleMessage( @@ -1190,10 +1524,11 @@ class MessageLookup extends MessageLookupByLibrary { "timeout": MessageLookupByLibrary.simpleMessage("Тайм-аут"), "tip": MessageLookupByLibrary.simpleMessage("Подсказка"), "toggle": MessageLookupByLibrary.simpleMessage("Переключить"), - "toggleLabel": MessageLookupByLibrary.simpleMessage("Переключить подписи"), + "tolerance": MessageLookupByLibrary.simpleMessage("Допуск"), "tonalSpotScheme": MessageLookupByLibrary.simpleMessage("Тональный акцент"), "tools": MessageLookupByLibrary.simpleMessage("Инструменты"), "torch": MessageLookupByLibrary.simpleMessage("Фонарик"), + "total": MessageLookupByLibrary.simpleMessage("Всего"), "totalTraffic": MessageLookupByLibrary.simpleMessage("Общий трафик"), "tproxyPort": MessageLookupByLibrary.simpleMessage("Порт TProxy"), "trafficUsage": MessageLookupByLibrary.simpleMessage("Статистика трафика"), @@ -1205,9 +1540,6 @@ class MessageLookup extends MessageLookupByLibrary { "turnOn": MessageLookupByLibrary.simpleMessage("Включить"), "undo": MessageLookupByLibrary.simpleMessage("Отменить"), "unifiedDelay": MessageLookupByLibrary.simpleMessage("Единая задержка"), - "unifiedDelayDesc": MessageLookupByLibrary.simpleMessage( - "Убирает лишние задержки, например рукопожатие", - ), "unknown": MessageLookupByLibrary.simpleMessage("Неизвестно"), "unknownNetworkError": MessageLookupByLibrary.simpleMessage( "Неизвестная сетевая ошибка", @@ -1219,7 +1551,7 @@ class MessageLookup extends MessageLookupByLibrary { "upload": MessageLookupByLibrary.simpleMessage("Отдача"), "url": MessageLookupByLibrary.simpleMessage("URL"), "urlDesc": MessageLookupByLibrary.simpleMessage("Получить профиль по URL"), - "urlTip": m29, + "urlTip": m53, "useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"), "useSystemHosts": MessageLookupByLibrary.simpleMessage( "Использовать системный hosts", @@ -1246,7 +1578,14 @@ class MessageLookup extends MessageLookupByLibrary { "whitelistMode": MessageLookupByLibrary.simpleMessage( "Режим белого списка", ), - "yearsAgo": m30, + "writeToSystem": MessageLookupByLibrary.simpleMessage( + "Записывать в систему", + ), + "writeToSystemDesc": MessageLookupByLibrary.simpleMessage( + "Также устанавливать системные часы; Android это игнорирует", + ), + "yearsAgo": m54, + "yes": MessageLookupByLibrary.simpleMessage("Да"), "zhCN": MessageLookupByLibrary.simpleMessage("Упрощённый китайский"), }; } diff --git a/lib/l10n/intl/messages_zh_CN.dart b/lib/l10n/intl/messages_zh_CN.dart index 2e41cbd4..c9849132 100644 --- a/lib/l10n/intl/messages_zh_CN.dart +++ b/lib/l10n/intl/messages_zh_CN.dart @@ -20,25 +20,25 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'zh_CN'; - static String m0(code) => + static String m0(count, skipped) => "将添加 ${count} 项,跳过 ${skipped} 项已存在"; + + static String m1(code) => "Windows 拒绝运行 FlClashCore.exe(错误 ${code})。智能应用控制、AppLocker 等应用控制策略会拦截未签名程序,请在该策略中放行 FlClash 或关闭策略后重试。"; - static String m1(name) => + static String m2(name) => "应用连续两次未能完成启动。为打断崩溃循环,已取消选中配置 ${name},并跳过本次自动配置,你可以随时重新选中它。"; - static String m2(url) => "是否要通过 ${url} 创建配置?"; + static String m3(url) => "是否要通过 ${url} 创建配置?"; - static String m3(count) => "${count} 天前"; + static String m4(count) => "${count} 天前"; - static String m4(label) => "确定删除选中的${label}吗?"; + static String m5(label) => "确定删除选中的${label}吗?"; - static String m5(label) => "确定删除当前${label}吗?"; + static String m6(label) => "确定删除当前${label}吗?"; - static String m6(label) => "${label}详情"; + static String m7(label) => "${label}详情"; - static String m7(label) => "${label}不能为空"; - - static String m8(count) => "${count} 个条目"; + static String m8(label) => "${label}不能为空"; static String m9(label) => "${label}当前已存在"; @@ -46,44 +46,94 @@ class MessageLookup extends MessageLookupByLibrary { static String m11(name) => "${name} 已更新"; - static String m12(count) => "${count} 小时前"; + static String m12(action) => "已被“${action}”使用,保存后将移到这里"; - static String m13(count) => "${count} 小时"; + static String m13(modifiers) => "至少包含 ${modifiers} 中的一个"; - static String m14(target) => "${target} 是一个无效的策略"; + static String m14(count) => "${count} 小时前"; - static String m15(proxyName) => "${proxyName} 是一个无效的代理"; + static String m15(count) => "${count} 小时"; - static String m16(providerName) => "${providerName} 是一个无效的代理集"; + static String m16(target) => "${target} 是一个无效的策略"; - static String m17(subRule) => "${subRule} 是一个无效的SUB_RULE"; + static String m17(proxyName) => "${proxyName} 是一个无效的代理"; - static String m18(appName) => + static String m18(providerName) => "${providerName} 是一个无效的代理集"; + + static String m19(ruleSet) => "${ruleSet} 不是有效的规则集"; + + static String m20(subRule) => "${subRule} 是一个无效的SUB_RULE"; + + static String m21(line, message) => "第 ${line} 行:${message}"; + + static String m22(appName) => "1. 打开 系统设置 > 隐私与安全性\n2. 选择 定位服务\n3. 在右侧列表中找到并勾选 ${appName}\n\n完成设置后,返回应用即可正常使用。感谢您的配合。"; - static String m19(label, max) => "${label}最多${max}个字符"; + static String m23(label, max) => "${label}最多${max}个字符"; - static String m20(count) => "${count} 分钟前"; + static String m24(size) => "已释放 ${size}"; - static String m21(count) => "${count} 个月前"; + static String m25(count) => "${count} 分钟前"; - static String m22(label) => "暂无${label}"; + static String m26(count) => "${count} 个月前"; - static String m23(label) => "${label}必须为数字"; + static String m27(code) => "服务器拒绝访问(HTTP ${code}),链接可能已过期或凭据有误"; - static String m24(label) => "${label} 必须在 1024 到 49151 之间"; + static String m28(code) => "服务器拒绝了请求(HTTP ${code})"; - static String m25(count) => "${count} 个代理"; + static String m29(code) => "该地址下没有内容(HTTP ${code}),请确认链接是否正确"; - static String m26(count) => "${count} 条规则"; + static String m30(detail) => "网络请求失败:${detail}"; - static String m27(count) => "${count} 秒"; + static String m31(code) => "服务器出现问题(HTTP ${code}),请稍后再试"; - static String m28(count) => "已选择 ${count} 项"; + static String m32(label) => "暂无${label}"; - static String m29(label) => "${label}必须为URL"; + static String m33(label) => "${label}必须为数字"; - static String m30(count) => "${count} 年前"; + static String m34(message) => "内核无法解析该代理:${message}"; + + static String m35(name) => "名称 ${name} 已被其他代理或策略组使用"; + + static String m36(path) => "策略组之间存在循环引用:${path}"; + + static String m37(names) => "以下代理集不存在:${names}"; + + static String m38(names) => "以下代理或策略不存在:${names}"; + + static String m39(name) => "配置文件中已有名为 ${name} 的外部资源,同名的应用级外部资源不会生效,请改名"; + + static String m40(name) => "${name} 是内置策略名,不能在此使用"; + + static String m41(names) => "配置文件自身的策略组引用了自定义代理中已没有的代理:${names}"; + + static String m42(count) => "${count} 项存在问题,应用覆写可能失败"; + + static String m43(label) => "${label} 必须在 1024 到 49151 之间"; + + static String m44(label, profiles) => + "${label} 仍被 ${profiles} 的自定义策略组或规则使用,请先在那里移除"; + + static String m45(profiles, label) => + "${profiles} 的订阅里已有 ${label},改名后这些配置会改用订阅里的那个,请换一个名称"; + + static String m46(count) => "${count} 个代理"; + + static String m47(count) => "${count} 条规则"; + + static String m48(appName) => "${appName}(安全模式)"; + + static String m49(count) => "${count} 秒"; + + static String m50(count) => "已选择 ${count} 项"; + + static String m51(time) => "检测于 ${time}"; + + static String m52(label) => "${label}只能是一项"; + + static String m53(label) => "${label}必须为URL"; + + static String m54(count) => "${count} 年前"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -102,12 +152,19 @@ class MessageLookup extends MessageLookupByLibrary { "accessControlSettings": MessageLookupByLibrary.simpleMessage("访问控制设置"), "account": MessageLookupByLibrary.simpleMessage("账号"), "action": MessageLookupByLibrary.simpleMessage("操作"), + "actionDelayTest": MessageLookupByLibrary.simpleMessage("测试全部延迟"), + "actionDirectMode": MessageLookupByLibrary.simpleMessage("直连模式"), + "actionGlobalMode": MessageLookupByLibrary.simpleMessage("全局模式"), "actionMode": MessageLookupByLibrary.simpleMessage("切换模式"), "actionProxy": MessageLookupByLibrary.simpleMessage("系统代理"), + "actionRuleMode": MessageLookupByLibrary.simpleMessage("规则模式"), "actionStart": MessageLookupByLibrary.simpleMessage("启动/停止"), "actionTun": MessageLookupByLibrary.simpleMessage("虚拟网卡"), + "actionUpdateProfiles": MessageLookupByLibrary.simpleMessage("更新全部配置"), "actionView": MessageLookupByLibrary.simpleMessage("显示/隐藏"), "add": MessageLookupByLibrary.simpleMessage("添加"), + "addCustomProxy": MessageLookupByLibrary.simpleMessage("添加代理"), + "addOverrideEntry": MessageLookupByLibrary.simpleMessage("添加覆写项"), "addProfile": MessageLookupByLibrary.simpleMessage("添加配置"), "addProxies": MessageLookupByLibrary.simpleMessage("添加代理"), "addProxyGroup": MessageLookupByLibrary.simpleMessage("添加策略组"), @@ -121,18 +178,20 @@ class MessageLookup extends MessageLookupByLibrary { "addressHelp": MessageLookupByLibrary.simpleMessage("WebDAV服务器地址"), "addressTip": MessageLookupByLibrary.simpleMessage("请输入有效的WebDAV地址"), "advancedConfig": MessageLookupByLibrary.simpleMessage("进阶配置"), - "advancedConfigDesc": MessageLookupByLibrary.simpleMessage("提供多样化配置"), + "advancedConfigDesc": MessageLookupByLibrary.simpleMessage( + "网络、DNS、附加规则与脚本", + ), "agree": MessageLookupByLibrary.simpleMessage("同意"), "allowBypass": MessageLookupByLibrary.simpleMessage("允许应用绕过VPN"), - "allowBypassDesc": MessageLookupByLibrary.simpleMessage("开启后部分应用可绕过VPN"), "allowLan": MessageLookupByLibrary.simpleMessage("局域网代理"), - "allowLanDesc": MessageLookupByLibrary.simpleMessage("允许通过局域网访问代理"), + "answers": MessageLookupByLibrary.simpleMessage("应答"), "app": MessageLookupByLibrary.simpleMessage("应用"), "appAccessControl": MessageLookupByLibrary.simpleMessage("应用访问控制"), + "appIconDesign": MessageLookupByLibrary.simpleMessage("应用图标设计"), + "appProviderShadowed": MessageLookupByLibrary.simpleMessage("同名的应用级项在此不生效"), + "appProxyProviders": MessageLookupByLibrary.simpleMessage("应用代理集"), + "appRuleProviders": MessageLookupByLibrary.simpleMessage("应用规则集"), "appendSystemDns": MessageLookupByLibrary.simpleMessage("追加系统DNS"), - "appendSystemDnsTip": MessageLookupByLibrary.simpleMessage("强制为配置附加系统DNS"), - "application": MessageLookupByLibrary.simpleMessage("应用程序"), - "applicationDesc": MessageLookupByLibrary.simpleMessage("修改应用程序相关设置"), "authentication": MessageLookupByLibrary.simpleMessage("认证"), "authenticationDesc": MessageLookupByLibrary.simpleMessage( "为本地代理端口启用认证,防止本机其他应用擅自使用", @@ -144,7 +203,6 @@ class MessageLookup extends MessageLookupByLibrary { "authorized": MessageLookupByLibrary.simpleMessage("已授权"), "auto": MessageLookupByLibrary.simpleMessage("自动"), "autoCheckUpdate": MessageLookupByLibrary.simpleMessage("自动检查更新"), - "autoCheckUpdateDesc": MessageLookupByLibrary.simpleMessage("应用启动时自动检查更新"), "autoCloseConnections": MessageLookupByLibrary.simpleMessage("自动关闭连接"), "autoCloseConnectionsDesc": MessageLookupByLibrary.simpleMessage( "切换节点后自动关闭连接", @@ -162,23 +220,34 @@ class MessageLookup extends MessageLookupByLibrary { "backupAndRestoreDesc": MessageLookupByLibrary.simpleMessage( "通过WebDAV或者文件同步数据", ), + "backupFromNewerVersion": MessageLookupByLibrary.simpleMessage( + "该备份来自更高版本的应用,请先更新应用再恢复", + ), "backupSuccess": MessageLookupByLibrary.simpleMessage("备份成功"), - "basicConfig": MessageLookupByLibrary.simpleMessage("基础配置"), - "basicConfigDesc": MessageLookupByLibrary.simpleMessage("全局修改基础配置"), "basicInfo": MessageLookupByLibrary.simpleMessage("基础信息"), "basicStrategy": MessageLookupByLibrary.simpleMessage("基础策略"), + "batchAdd": MessageLookupByLibrary.simpleMessage("批量添加"), + "batchListInputTip": MessageLookupByLibrary.simpleMessage("每行一项,也可用逗号分隔"), + "batchMapInputTip": MessageLookupByLibrary.simpleMessage("每行一条,键和值之间用空格分隔"), + "batchPreviewTip": m0, "batteryOptimizationDesc": MessageLookupByLibrary.simpleMessage( "为保证后台运行,请关闭本应用的电池优化。点击前往设置。", ), - "batteryOptimizationStatusTip": MessageLookupByLibrary.simpleMessage( - "由于系统限制,运行状态下无法正确获取电池优化状态", - ), + "behavior": MessageLookupByLibrary.simpleMessage("行为"), "bind": MessageLookupByLibrary.simpleMessage("绑定"), "blacklistMode": MessageLookupByLibrary.simpleMessage("黑名单模式"), "blockConnection": MessageLookupByLibrary.simpleMessage("阻止连接"), "bypassDomain": MessageLookupByLibrary.simpleMessage("排除域名"), "bypassDomainDesc": MessageLookupByLibrary.simpleMessage("仅在系统代理启用时生效"), + "cache": MessageLookupByLibrary.simpleMessage("缓存"), + "cacheAlgorithm": MessageLookupByLibrary.simpleMessage("缓存算法"), "cacheCorrupt": MessageLookupByLibrary.simpleMessage("缓存已损坏,是否清空?"), + "cacheMaxSize": MessageLookupByLibrary.simpleMessage("缓存大小"), + "cameraPermissionDesc": MessageLookupByLibrary.simpleMessage( + "请在系统设置中允许访问相机以扫描二维码,或从相册选择二维码图片。", + ), + "cameraPermissionRequired": MessageLookupByLibrary.simpleMessage("需要相机权限"), + "cameraUnavailable": MessageLookupByLibrary.simpleMessage("相机不可用"), "cancel": MessageLookupByLibrary.simpleMessage("取消"), "cancelSelectAll": MessageLookupByLibrary.simpleMessage("取消全选"), "changeProxyFailedTip": MessageLookupByLibrary.simpleMessage( @@ -211,14 +280,13 @@ class MessageLookup extends MessageLookupByLibrary { "confirmDeleteProxyGroup": MessageLookupByLibrary.simpleMessage( "确定要删除当前策略组吗?", ), - "confirmExitWindow": MessageLookupByLibrary.simpleMessage("确定要退出当前窗口吗?"), + "confirmExitWindow": MessageLookupByLibrary.simpleMessage("确定要退出当前窗口吗?"), "confirmForceCrashCore": MessageLookupByLibrary.simpleMessage("确定要强制崩溃核心?"), "confirmOverwriteTip": MessageLookupByLibrary.simpleMessage("确定后将会覆盖已有数据"), "connected": MessageLookupByLibrary.simpleMessage("已连接"), - "connecting": MessageLookupByLibrary.simpleMessage("连接中..."), + "connecting": MessageLookupByLibrary.simpleMessage("连接中…"), "connection": MessageLookupByLibrary.simpleMessage("连接"), "connections": MessageLookupByLibrary.simpleMessage("连接"), - "connectionsDesc": MessageLookupByLibrary.simpleMessage("查看当前连接数据"), "connectivity": MessageLookupByLibrary.simpleMessage("连通性:"), "content": MessageLookupByLibrary.simpleMessage("内容"), "contentNotEmpty": MessageLookupByLibrary.simpleMessage("内容不能为空"), @@ -229,24 +297,26 @@ class MessageLookup extends MessageLookupByLibrary { "copyLink": MessageLookupByLibrary.simpleMessage("复制链接"), "copySuccess": MessageLookupByLibrary.simpleMessage("复制成功"), "core": MessageLookupByLibrary.simpleMessage("内核"), - "coreBlockedByPolicyTip": m0, + "coreBlockedByPolicyTip": m1, "coreBlockedBySmartAppControlTip": MessageLookupByLibrary.simpleMessage( "Windows 智能应用控制拦截了未签名的 FlClashCore.exe。请打开 Windows 安全中心 → 应用和浏览器控制 → 智能应用控制设置,选择「关闭」后重新启动 FlClash。智能应用控制关闭后无法再开启,除非重装 Windows。", ), "coreStatus": MessageLookupByLibrary.simpleMessage("核心状态"), "country": MessageLookupByLibrary.simpleMessage("区域"), "crashDetected": MessageLookupByLibrary.simpleMessage("检测到崩溃"), - "crashDetectedTip": m1, + "crashDetectedTip": m2, "crashTest": MessageLookupByLibrary.simpleMessage("崩溃测试"), "crashlytics": MessageLookupByLibrary.simpleMessage("崩溃分析"), "crashlyticsTip": MessageLookupByLibrary.simpleMessage( "开启后,应用崩溃时自动上传不包含敏感信息的崩溃日志", ), "create": MessageLookupByLibrary.simpleMessage("创建"), - "createProfile": MessageLookupByLibrary.simpleMessage("创建配置"), - "createProfileFromUrlTip": m2, + "createProfileFromUrlTip": m3, "creationTime": MessageLookupByLibrary.simpleMessage("创建时间"), "custom": MessageLookupByLibrary.simpleMessage("自定义"), + "customProxiesEmpty": MessageLookupByLibrary.simpleMessage( + "未添加自定义代理,沿用配置文件自身的代理", + ), "cut": MessageLookupByLibrary.simpleMessage("剪切"), "dark": MessageLookupByLibrary.simpleMessage("深色"), "dashboard": MessageLookupByLibrary.simpleMessage("仪表盘"), @@ -258,36 +328,103 @@ class MessageLookup extends MessageLookupByLibrary { "databaseWriteFailedTip": MessageLookupByLibrary.simpleMessage( "保存更改失败,已回滚", ), - "daysAgo": m3, - "defaultNameserver": MessageLookupByLibrary.simpleMessage("默认域名服务器"), - "defaultNameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析DNS服务器"), + "daysAgo": m4, "defaultText": MessageLookupByLibrary.simpleMessage("默认"), "delay": MessageLookupByLibrary.simpleMessage("延迟"), "delayTest": MessageLookupByLibrary.simpleMessage("延迟测试"), "delete": MessageLookupByLibrary.simpleMessage("删除"), - "deleteMultipTip": m4, - "deleteTip": m5, + "deleteMultipTip": m5, + "deleteTip": m6, "desc": MessageLookupByLibrary.simpleMessage( "基于ClashMeta的多平台代理客户端,简单易用,开源无广告。", ), "destination": MessageLookupByLibrary.simpleMessage("目标地址"), "destinationGeoIP": MessageLookupByLibrary.simpleMessage("目标地理定位"), "destinationIPASN": MessageLookupByLibrary.simpleMessage("目标IP ASN"), - "details": m6, + "details": m7, "detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api,仅供参考"), "developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"), "developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"), + "dialerProxy": MessageLookupByLibrary.simpleMessage("拨号代理"), + "dialerProxyDesc": MessageLookupByLibrary.simpleMessage("用于连接NTP服务器的出站"), "direct": MessageLookupByLibrary.simpleMessage("直连"), "disableUDP": MessageLookupByLibrary.simpleMessage("禁用UDP"), + "disabled": MessageLookupByLibrary.simpleMessage("已关闭"), + "discardChanges": MessageLookupByLibrary.simpleMessage("是否放弃更改?"), "disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"), - "disclaimerDesc": MessageLookupByLibrary.simpleMessage( - "本软件仅供学习交流、科研等非商业性质的用途,严禁将本软件用于商业目的。如有任何商业行为,均与本软件无关。", + "disclaimerAcceptContent": MessageLookupByLibrary.simpleMessage( + "一旦你安装、复制或使用本软件,即视为你已阅读并同意本声明的全部内容。如你不同意本声明的任何条款,请立即停止使用并卸载本软件。", ), + "disclaimerAcceptTitle": MessageLookupByLibrary.simpleMessage("接受声明"), + "disclaimerAnalyticsContent": MessageLookupByLibrary.simpleMessage( + "随 Firebase 自动收集基础的应用使用统计。\n\n收集内容:首次启动、应用打开与会话时长、应用更新等基础事件,应用实例标识,设备型号、系统版本、系统语言,以及由 IP 地址推断的国家或地区级大致位置。\n\n用途:仅用于了解活跃设备数、版本分布与系统兼容情况。开发者不会将这些数据用于广告,不会出售,也不会与你的订阅或配置相关联。", + ), + "disclaimerAnalyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Analytics(使用统计)", + ), + "disclaimerAndroidOnly": MessageLookupByLibrary.simpleMessage("仅 Android"), + "disclaimerChangesContent": MessageLookupByLibrary.simpleMessage( + "开发者有权随版本更新修改本声明,修改后的内容随新版本发布即生效。你在更新后继续使用本软件,即视为接受修改后的声明。", + ), + "disclaimerChangesTitle": MessageLookupByLibrary.simpleMessage("声明变更"), + "disclaimerCrashlyticsContent": MessageLookupByLibrary.simpleMessage( + "应用发生崩溃时,自动上传崩溃报告。\n\n收集内容:崩溃堆栈与错误信息、崩溃发生时间、应用版本与构建号、设备品牌与型号、Android 系统版本、屏幕方向、剩余内存与存储空间、设备是否已 root,以及一个随安装生成、重装后即重置的随机安装标识。\n\n用途:仅用于定位和修复崩溃问题。\n\n你可以在“工具 > 常规 > 崩溃分析”中随时关闭。", + ), + "disclaimerCrashlyticsTitle": MessageLookupByLibrary.simpleMessage( + "Firebase Crashlytics(崩溃分析)", + ), + "disclaimerDataProcessingContent": MessageLookupByLibrary.simpleMessage( + "上述数据由 Google 代为处理和存储,可能被传输至你所在国家或地区以外(如美国)的服务器,并受 Google 隐私政策与 Firebase 隐私和安全说明约束。崩溃报告最多保留 90 天,统计数据按 Firebase 的默认策略保留。", + ), + "disclaimerDesc": MessageLookupByLibrary.simpleMessage( + "在使用 FlClash(以下简称“本软件”)前,请仔细阅读并充分理解本声明的全部内容。点击“同意”即表示你已阅读、理解并接受以下全部条款;如不同意,请点击“退出”并停止使用本软件。", + ), + "disclaimerFirebasePrivacy": MessageLookupByLibrary.simpleMessage( + "Firebase 隐私和安全说明", + ), + "disclaimerGooglePrivacy": MessageLookupByLibrary.simpleMessage( + "Google 隐私政策", + ), + "disclaimerLiabilityContent": MessageLookupByLibrary.simpleMessage( + "在适用法律允许的最大范围内,开发者及所有贡献者均不对因使用或无法使用本软件而产生的任何直接、间接、偶然、特殊、惩罚性或后果性损害承担责任,包括但不限于数据丢失、设备损坏、网络异常、业务中断、利润损失或因此引起的任何法律纠纷,即使已被告知发生此类损害的可能性。", + ), + "disclaimerLiabilityTitle": MessageLookupByLibrary.simpleMessage("责任限制"), + "disclaimerLicenseContent": MessageLookupByLibrary.simpleMessage( + "本软件以 GPL-3.0 协议开源。你可以在遵守该协议的前提下自由使用、修改和分发本软件,但须同样以 GPL-3.0 协议开源并保留原作者的版权声明。\n\n本软件包含的第三方组件(包括 Clash.Meta 内核)分别遵循其各自的开源协议。基于本软件修改或分发的版本所产生的任何问题,与原作者无关。", + ), + "disclaimerLicenseTitle": MessageLookupByLibrary.simpleMessage("开源协议"), + "disclaimerPrivacyContent": MessageLookupByLibrary.simpleMessage( + "本软件不会收集或上传你的订阅地址、节点信息、配置内容、访问的网站、连接记录、流量内容和日志,这些数据仅保存在你的设备本地,开发者无法获取。\n\n本软件只会在你使用相应功能时访问外部网络,例如更新订阅时访问你提供的订阅地址、检查更新时访问 GitHub。\n\n桌面版(Windows、macOS、Linux)未集成任何数据统计或崩溃上报服务。Android 版集成了 Google Firebase 的以下两项服务,用于改进应用稳定性:", + ), + "disclaimerPrivacyTitle": MessageLookupByLibrary.simpleMessage("数据收集与隐私"), + "disclaimerResponsibilityContent": MessageLookupByLibrary.simpleMessage( + "你应自行确认使用本软件在你所在国家或地区是合法的,并对使用本软件的全部行为及其后果独立承担法律责任。\n\n你导入的订阅、节点与配置由你自行选择和判断,其来源是否合法、内容是否安全、服务是否稳定,均由你与相关提供者自行负责。", + ), + "disclaimerResponsibilityTitle": MessageLookupByLibrary.simpleMessage( + "用户责任", + ), + "disclaimerSoftwareContent": MessageLookupByLibrary.simpleMessage( + "本软件是基于 Clash.Meta(mihomo)内核的开源网络代理客户端,仅提供配置管理、规则分流与流量转发等本地工具功能。\n\n本软件自身不提供任何代理服务器、节点、订阅、机场或网络接入服务,也不与任何此类服务的提供者存在合作、代理或担保关系。", + ), + "disclaimerSoftwareTitle": MessageLookupByLibrary.simpleMessage("软件性质"), + "disclaimerThirdPartyContent": MessageLookupByLibrary.simpleMessage( + "订阅链接、配置文件、规则集、脚本、外部资源及外部链接均由第三方提供,开发者无法也不会对其合法性、准确性、安全性和可用性进行审查或担保。\n\n因使用第三方内容导致的数据泄露、财产损失、账号封禁或其他任何损失,由你与第三方自行解决,开发者不承担任何责任。", + ), + "disclaimerThirdPartyTitle": MessageLookupByLibrary.simpleMessage("第三方内容"), + "disclaimerUsageContent": MessageLookupByLibrary.simpleMessage( + "本软件仅供学习交流、技术研究等非商业用途。严禁将本软件用于任何商业目的,包括但不限于付费分发、捆绑销售、作为商业服务的组成部分或以本软件名义开展经营活动;任何商业行为均与本软件及其开发者无关。\n\n严禁将本软件用于违反你所在国家或地区法律法规的活动,包括但不限于绕过依法设置的网络访问限制、传播违法信息、实施网络攻击或侵犯他人合法权益。", + ), + "disclaimerUsageTitle": MessageLookupByLibrary.simpleMessage("使用限制"), + "disclaimerWarrantyContent": MessageLookupByLibrary.simpleMessage( + "本软件按“现状”和“可用”的原则提供,不附带任何明示或默示的担保,包括但不限于适销性、特定用途适用性、不侵权以及持续可用、无错误、无安全漏洞的担保。\n\n开发者不保证本软件能满足你的需求,也不保证本软件的运行不会中断或不会出现错误。", + ), + "disclaimerWarrantyTitle": MessageLookupByLibrary.simpleMessage("无担保声明"), "disconnected": MessageLookupByLibrary.simpleMessage("已断开"), "discoverNewVersion": MessageLookupByLibrary.simpleMessage("发现新版本"), - "dnsDesc": MessageLookupByLibrary.simpleMessage("更新DNS相关设置"), "dnsHijacking": MessageLookupByLibrary.simpleMessage("DNS劫持"), "dnsMode": MessageLookupByLibrary.simpleMessage("DNS模式"), + "dnsQueries": MessageLookupByLibrary.simpleMessage("DNS查询"), + "docked": MessageLookupByLibrary.simpleMessage("固定"), "domain": MessageLookupByLibrary.simpleMessage("域名"), "download": MessageLookupByLibrary.simpleMessage("下载"), "edit": MessageLookupByLibrary.simpleMessage("编辑"), @@ -296,12 +433,14 @@ class MessageLookup extends MessageLookupByLibrary { "editProxyGroup": MessageLookupByLibrary.simpleMessage("编辑策略组"), "editRule": MessageLookupByLibrary.simpleMessage("编辑规则"), "editSsid": MessageLookupByLibrary.simpleMessage("编辑SSID"), - "emptyTip": m7, + "editorUnavailable": MessageLookupByLibrary.simpleMessage("编辑器不可用"), + "emptyTip": m8, "en": MessageLookupByLibrary.simpleMessage("英语"), + "enabled": MessageLookupByLibrary.simpleMessage("已开启"), "entries": MessageLookupByLibrary.simpleMessage("个条目"), - "entriesCount": m8, + "error": MessageLookupByLibrary.simpleMessage("错误"), "exclude": MessageLookupByLibrary.simpleMessage("从最近任务中隐藏"), - "excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"), + "excludeDesc": MessageLookupByLibrary.simpleMessage("应用在后台时,从最近任务中隐藏应用"), "excludeProxyFilter": MessageLookupByLibrary.simpleMessage("排除节点过滤器"), "excludeSsids": MessageLookupByLibrary.simpleMessage("排除SSIDs"), "excludeSsidsDesc": MessageLookupByLibrary.simpleMessage( @@ -322,22 +461,29 @@ class MessageLookup extends MessageLookupByLibrary { "externalControllerDesc": MessageLookupByLibrary.simpleMessage( "开启后将可以通过9090端口控制Clash内核", ), - "externalFetch": MessageLookupByLibrary.simpleMessage("外部获取"), "externalLink": MessageLookupByLibrary.simpleMessage("外部链接"), - "fakeipFilter": MessageLookupByLibrary.simpleMessage("Fakeip过滤"), - "fakeipRange": MessageLookupByLibrary.simpleMessage("Fakeip范围"), - "fallback": MessageLookupByLibrary.simpleMessage("Fallback"), - "fallbackDesc": MessageLookupByLibrary.simpleMessage("一般情况下使用境外DNS"), + "fade": MessageLookupByLibrary.simpleMessage("淡入"), + "fakeipFilter": MessageLookupByLibrary.simpleMessage("Fake-IP过滤"), + "fakeipFilterMode": MessageLookupByLibrary.simpleMessage("Fake-IP过滤模式"), + "fakeipFilterModeDesc": MessageLookupByLibrary.simpleMessage( + "blacklist排除匹配项,whitelist仅用于匹配项,rule按规则匹配", + ), + "fakeipRange": MessageLookupByLibrary.simpleMessage("Fake-IP范围"), + "fakeipRange6": MessageLookupByLibrary.simpleMessage("Fake-IP范围(IPv6)"), + "fakeipTtl": MessageLookupByLibrary.simpleMessage("Fake-IP TTL"), "fallbackFilter": MessageLookupByLibrary.simpleMessage("Fallback过滤"), "fidelityScheme": MessageLookupByLibrary.simpleMessage("高保真"), "file": MessageLookupByLibrary.simpleMessage("文件"), "fileDesc": MessageLookupByLibrary.simpleMessage("直接上传配置文件"), "fileIsUpdate": MessageLookupByLibrary.simpleMessage("文件有修改,是否保存修改"), + "filter": MessageLookupByLibrary.simpleMessage("筛选"), "findProcessMode": MessageLookupByLibrary.simpleMessage("查找进程"), - "findProcessModeDesc": MessageLookupByLibrary.simpleMessage("开启后会有一定性能损耗"), + "floating": MessageLookupByLibrary.simpleMessage("悬浮"), "followProfile": MessageLookupByLibrary.simpleMessage("跟随配置"), + "followSystem": MessageLookupByLibrary.simpleMessage("跟随系统"), "fontFamily": MessageLookupByLibrary.simpleMessage("字体"), "forceRestartCoreTip": MessageLookupByLibrary.simpleMessage("您确定要强制重启核心吗?"), + "format": MessageLookupByLibrary.simpleMessage("格式"), "fruitSaladScheme": MessageLookupByLibrary.simpleMessage("果缤纷"), "general": MessageLookupByLibrary.simpleMessage("常规"), "geoAutoUpdate": MessageLookupByLibrary.simpleMessage("自动更新"), @@ -350,8 +496,6 @@ class MessageLookup extends MessageLookupByLibrary { "geoSkipped": m10, "geoUpdated": m11, "geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低内存模式"), - "geodataLoaderDesc": MessageLookupByLibrary.simpleMessage("开启将使用Geo低内存加载器"), - "geoipCode": MessageLookupByLibrary.simpleMessage("Geoip代码"), "global": MessageLookupByLibrary.simpleMessage("全局"), "go": MessageLookupByLibrary.simpleMessage("前往"), "goDownload": MessageLookupByLibrary.simpleMessage("前往下载"), @@ -361,18 +505,32 @@ class MessageLookup extends MessageLookupByLibrary { "Helper 服务不可用,无法启用 TUN 模式,请重新安装 FlClash。", ), "hideFromList": MessageLookupByLibrary.simpleMessage("从列表中隐藏"), + "hideIp": MessageLookupByLibrary.simpleMessage("隐藏 IP"), "hidePassword": MessageLookupByLibrary.simpleMessage("隐藏密码"), + "hideTimeoutProxies": MessageLookupByLibrary.simpleMessage("隐藏超时节点"), + "hideTimeoutProxiesDesc": MessageLookupByLibrary.simpleMessage( + "不显示上次延迟测试超时的节点", + ), "host": MessageLookupByLibrary.simpleMessage("主机"), - "hostsDesc": MessageLookupByLibrary.simpleMessage("追加Hosts"), - "hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"), + "hotkeyConflictWith": m12, + "hotkeyDesc": MessageLookupByLibrary.simpleMessage( + "全局快捷键在窗口隐藏时依然生效,点击操作即可录制组合键。", + ), "hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"), - "hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage("使用键盘控制应用程序"), + "hotkeyNeedsModifier": m13, + "hotkeyNotSet": MessageLookupByLibrary.simpleMessage("未设置"), + "hotkeyUnavailable": MessageLookupByLibrary.simpleMessage( + "未能注册,可能已被其他应用占用", + ), "hours": MessageLookupByLibrary.simpleMessage("小时"), - "hoursAgo": m12, - "hoursCount": m13, + "hoursAgo": m14, + "hoursCount": m15, "icon": MessageLookupByLibrary.simpleMessage("图片"), "iconRecords": MessageLookupByLibrary.simpleMessage("图标记录"), "iconStyle": MessageLookupByLibrary.simpleMessage("图标样式"), + "iconStyleFilled": MessageLookupByLibrary.simpleMessage("色块"), + "iconStyleHidden": MessageLookupByLibrary.simpleMessage("隐藏"), + "iconStylePlain": MessageLookupByLibrary.simpleMessage("纯图标"), "iconUrl": MessageLookupByLibrary.simpleMessage("图标链接"), "ignoreBatteryOptimization": MessageLookupByLibrary.simpleMessage("忽略电池优化"), "import": MessageLookupByLibrary.simpleMessage("导入"), @@ -386,11 +544,11 @@ class MessageLookup extends MessageLookupByLibrary { ), "includeAllProxyProviders": MessageLookupByLibrary.simpleMessage("包含所有代理集"), "includeAllProxyProvidersTip": MessageLookupByLibrary.simpleMessage( - "开启后将覆盖引入的代理集", + "开启后包含本配置的全部代理集:订阅自带的,以及任一策略组引用的配置和应用代理集", ), "infiniteTime": MessageLookupByLibrary.simpleMessage("长期有效"), "init": MessageLookupByLibrary.simpleMessage("初始化"), - "inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("请输入正确的快捷键"), + "initiator": MessageLookupByLibrary.simpleMessage("发起方"), "inputProxyGroupName": MessageLookupByLibrary.simpleMessage("输入策略组名称"), "inputRuleContent": MessageLookupByLibrary.simpleMessage("输入规则内容"), "installedAppsPermissionDeniedMessage": @@ -414,13 +572,50 @@ class MessageLookup extends MessageLookupByLibrary { "interval": MessageLookupByLibrary.simpleMessage("间隔"), "intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"), "invalidBackupFile": MessageLookupByLibrary.simpleMessage("无效备份文件"), - "invalidPolicy": m14, - "invalidProxy": m15, - "invalidProxyProvider": m16, - "invalidSubRule": m17, - "ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"), + "invalidDscpContent": MessageLookupByLibrary.simpleMessage( + "DSCP 标记不能超过 63", + ), + "invalidNetworkContent": MessageLookupByLibrary.simpleMessage( + "仅支持 tcp 或 udp", + ), + "invalidPolicy": m16, + "invalidProfileQrcode": MessageLookupByLibrary.simpleMessage( + "该二维码不包含配置文件链接", + ), + "invalidProxy": m17, + "invalidProxyProvider": m18, + "invalidRangeContent": MessageLookupByLibrary.simpleMessage( + "请输入数字或范围,如 80 或 8000-9000,多个用 / 分隔", + ), + "invalidRuleSet": m19, + "invalidSubRule": m20, + "ipAddress": MessageLookupByLibrary.simpleMessage("IP 地址"), + "ipAsn": MessageLookupByLibrary.simpleMessage("ASN"), + "ipFlagAbuser": MessageLookupByLibrary.simpleMessage("滥用记录"), + "ipFlagProxy": MessageLookupByLibrary.simpleMessage("代理"), + "ipFlagTor": MessageLookupByLibrary.simpleMessage("Tor"), + "ipFlagVpn": MessageLookupByLibrary.simpleMessage("VPN"), + "ipFlags": MessageLookupByLibrary.simpleMessage("命中标记"), + "ipOrganization": MessageLookupByLibrary.simpleMessage("组织"), + "ipQualityFailed": MessageLookupByLibrary.simpleMessage("类型查询失败"), + "ipQualityGood": MessageLookupByLibrary.simpleMessage("优"), + "ipQualityLevel": MessageLookupByLibrary.simpleMessage("等级"), + "ipQualityNormal": MessageLookupByLibrary.simpleMessage("普通"), + "ipQualityRetry": MessageLookupByLibrary.simpleMessage("重新查询"), + "ipQualityRisky": MessageLookupByLibrary.simpleMessage("风险"), + "ipQualitySource": MessageLookupByLibrary.simpleMessage("采用来源"), + "ipQualitySources": MessageLookupByLibrary.simpleMessage("各来源"), + "ipSourceIpMismatch": MessageLookupByLibrary.simpleMessage("出站 IP 不一致"), + "ipSourceNoType": MessageLookupByLibrary.simpleMessage("无法判定类型"), + "ipSourceRateLimited": MessageLookupByLibrary.simpleMessage("限流"), + "ipType": MessageLookupByLibrary.simpleMessage("类型"), + "ipTypeBusiness": MessageLookupByLibrary.simpleMessage("商业"), + "ipTypeHosting": MessageLookupByLibrary.simpleMessage("机房"), + "ipTypeMobile": MessageLookupByLibrary.simpleMessage("移动网络"), + "ipTypeResidential": MessageLookupByLibrary.simpleMessage("住宅"), "ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收IPv6流量"), "ipv6InboundDesc": MessageLookupByLibrary.simpleMessage("允许IPv6入站"), + "ipv6Timeout": MessageLookupByLibrary.simpleMessage("IPv6超时(毫秒)"), "ja": MessageLookupByLibrary.simpleMessage("日语"), "justNow": MessageLookupByLibrary.simpleMessage("刚刚"), "keepAliveIntervalDesc": MessageLookupByLibrary.simpleMessage("TCP保持活动间隔"), @@ -432,11 +627,15 @@ class MessageLookup extends MessageLookupByLibrary { ), "layout": MessageLookupByLibrary.simpleMessage("布局"), "light": MessageLookupByLibrary.simpleMessage("浅色"), + "lineIssueTip": m21, + "lineWrap": MessageLookupByLibrary.simpleMessage("自动换行"), "list": MessageLookupByLibrary.simpleMessage("列表"), "listen": MessageLookupByLibrary.simpleMessage("监听"), - "loading": MessageLookupByLibrary.simpleMessage("加载中..."), + "listenRoutingMark": MessageLookupByLibrary.simpleMessage("监听路由标记"), + "listenRoutingMarkDesc": MessageLookupByLibrary.simpleMessage("仅Linux有效"), + "liveConnections": MessageLookupByLibrary.simpleMessage("实时连接"), + "loading": MessageLookupByLibrary.simpleMessage("加载中…"), "local": MessageLookupByLibrary.simpleMessage("本地"), - "localBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到本地"), "locationPermission": MessageLookupByLibrary.simpleMessage("位置权限"), "locationPermissionDeniedMessage": MessageLookupByLibrary.simpleMessage( "位置权限已被拒绝,无法获取当前 Wi-Fi 名称。请前往系统设置手动开启位置权限。", @@ -444,7 +643,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationPermissionDesc": MessageLookupByLibrary.simpleMessage( "根据系统要求,获取Wi-Fi名称需要您授予位置权限。Android 上请选择“始终允许”,否则应用在后台时无法获取 Wi-Fi 名称。", ), - "locationPermissionGuide": m18, + "locationPermissionGuide": m22, "locationPermissionRequired": MessageLookupByLibrary.simpleMessage( "需要位置权限", ), @@ -453,49 +652,73 @@ class MessageLookup extends MessageLookupByLibrary { "logcat": MessageLookupByLibrary.simpleMessage("日志捕获"), "logcatDesc": MessageLookupByLibrary.simpleMessage("禁用将会隐藏日志入口"), "logs": MessageLookupByLibrary.simpleMessage("日志"), - "logsDesc": MessageLookupByLibrary.simpleMessage("日志捕获记录"), + "logsAndDiagnostics": MessageLookupByLibrary.simpleMessage("日志与诊断"), "logsTest": MessageLookupByLibrary.simpleMessage("日志测试"), - "loopback": MessageLookupByLibrary.simpleMessage("回环解锁工具"), - "loopbackDesc": MessageLookupByLibrary.simpleMessage("用于UWP回环解锁"), + "loopback": MessageLookupByLibrary.simpleMessage("UWP 回环解锁"), "loose": MessageLookupByLibrary.simpleMessage("宽松"), "matchSourceIp": MessageLookupByLibrary.simpleMessage("匹配来源IP"), "matchTarget": MessageLookupByLibrary.simpleMessage("MATCH-TARGET"), - "matchTargetDesc": MessageLookupByLibrary.simpleMessage( - "目标为 MATCH-TARGET 的规则路由到这里,默认取本配置末尾 MATCH 规则的目标。", - ), - "matchTargetTitle": MessageLookupByLibrary.simpleMessage("匹配目标"), "maxFailedTimes": MessageLookupByLibrary.simpleMessage("最大失败次数"), - "maxLengthTip": m19, + "maxLengthTip": m23, "maximize": MessageLookupByLibrary.simpleMessage("最大化"), + "memoryAppResident": MessageLookupByLibrary.simpleMessage("常驻内存"), + "memoryAppShared": MessageLookupByLibrary.simpleMessage("应用及共享"), + "memoryCoreHeapIdle": MessageLookupByLibrary.simpleMessage("堆内存空闲"), + "memoryCoreHeapInuse": MessageLookupByLibrary.simpleMessage("堆内存使用中"), + "memoryCoreNotRunning": MessageLookupByLibrary.simpleMessage("内核未运行"), + "memoryCoreRuntime": MessageLookupByLibrary.simpleMessage("运行时开销"), + "memoryCoreStack": MessageLookupByLibrary.simpleMessage("协程栈"), + "memoryEstimateDesc": MessageLookupByLibrary.simpleMessage( + "基于进程常驻内存估算,可能与系统显示的数值不同。", + ), + "memoryEstimateSharedDesc": MessageLookupByLibrary.simpleMessage( + "内核与应用运行在同一进程,内核部分按运行时统计估算,其余计入应用及共享内存。", + ), "memoryInfo": MessageLookupByLibrary.simpleMessage("内存信息"), + "memoryReleased": MessageLookupByLibrary.simpleMessage("内存已释放"), + "memoryReleasedSize": m24, "messageTest": MessageLookupByLibrary.simpleMessage("消息测试"), "messageTestTip": MessageLookupByLibrary.simpleMessage("这是一条消息。"), "min": MessageLookupByLibrary.simpleMessage("最小"), "minimize": MessageLookupByLibrary.simpleMessage("最小化"), "minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"), - "minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"), - "minutesAgo": m20, + "minutesAgo": m25, "mixedPort": MessageLookupByLibrary.simpleMessage("混合端口"), "mode": MessageLookupByLibrary.simpleMessage("模式"), "monochromeScheme": MessageLookupByLibrary.simpleMessage("单色"), - "monthsAgo": m21, + "monthsAgo": m26, "more": MessageLookupByLibrary.simpleMessage("更多"), - "multipleValuesTip": MessageLookupByLibrary.simpleMessage("多个值使用逗号分隔"), "name": MessageLookupByLibrary.simpleMessage("名称"), - "nameserver": MessageLookupByLibrary.simpleMessage("域名服务器"), - "nameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析域名"), - "nameserverPolicy": MessageLookupByLibrary.simpleMessage("域名服务器策略"), - "nameserverPolicyDesc": MessageLookupByLibrary.simpleMessage("指定对应域名服务器策略"), + "navigationBarStyle": MessageLookupByLibrary.simpleMessage("底栏"), "network": MessageLookupByLibrary.simpleMessage("网络"), - "networkDesc": MessageLookupByLibrary.simpleMessage("修改网络相关设置"), + "networkAccessDeniedError": m27, + "networkBadResponseError": m28, + "networkCancelledError": MessageLookupByLibrary.simpleMessage("请求已取消"), + "networkConnectionError": MessageLookupByLibrary.simpleMessage( + "无法连接到服务器,请检查网络连接或代理设置", + ), "networkDetection": MessageLookupByLibrary.simpleMessage("网络检测"), - "networkException": MessageLookupByLibrary.simpleMessage("网络异常,请检查连接后重试"), + "networkHostLookupError": MessageLookupByLibrary.simpleMessage( + "无法解析服务器地址,请确认链接正确且 DNS 可用", + ), + "networkNotFoundError": m29, + "networkRateLimitedError": MessageLookupByLibrary.simpleMessage( + "请求过于频繁(HTTP 429),请稍后再试", + ), + "networkRequestFailed": m30, + "networkServerError": m31, "networkSpeed": MessageLookupByLibrary.simpleMessage("网络速度"), + "networkTimeoutError": MessageLookupByLibrary.simpleMessage( + "请求超时,请检查网络或代理后重试", + ), + "networkTlsError": MessageLookupByLibrary.simpleMessage( + "安全连接失败,服务器证书可能无效,或连接被拦截", + ), "networkType": MessageLookupByLibrary.simpleMessage("网络类型"), "neutralScheme": MessageLookupByLibrary.simpleMessage("中性"), "nextMatch": MessageLookupByLibrary.simpleMessage("下一个匹配"), + "no": MessageLookupByLibrary.simpleMessage("否"), "noData": MessageLookupByLibrary.simpleMessage("暂无数据"), - "noHotKey": MessageLookupByLibrary.simpleMessage("暂无快捷键"), "noInfo": MessageLookupByLibrary.simpleMessage("暂无信息"), "noLongerRemind": MessageLookupByLibrary.simpleMessage("不再提示"), "noNetwork": MessageLookupByLibrary.simpleMessage("无网络"), @@ -503,31 +726,46 @@ class MessageLookup extends MessageLookupByLibrary { "noRecords": MessageLookupByLibrary.simpleMessage("暂无记录"), "noResolve": MessageLookupByLibrary.simpleMessage("不解析IP"), "noResolveHostname": MessageLookupByLibrary.simpleMessage("不解析主机名"), + "noSearchResults": MessageLookupByLibrary.simpleMessage("没有匹配的结果"), + "nonTextProviderFile": MessageLookupByLibrary.simpleMessage("该外部资源不是文本文件"), "none": MessageLookupByLibrary.simpleMessage("无"), "notSelectedTip": MessageLookupByLibrary.simpleMessage("当前代理组无法选中"), - "nullProfileDesc": MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"), - "nullTip": m22, - "numberTip": m23, + "ntpInterval": MessageLookupByLibrary.simpleMessage("同步间隔(分钟)"), + "ntpStatusDesc": MessageLookupByLibrary.simpleMessage("从NTP服务器获取时间,而非系统时钟"), + "nullProfileDesc": MessageLookupByLibrary.simpleMessage("添加一个配置文件后即可开始使用"), + "nullTip": m32, + "numberTip": m33, "onDemand": MessageLookupByLibrary.simpleMessage("按需运行"), "onDemandDesc": MessageLookupByLibrary.simpleMessage("配置程序特定场景运行状态"), - "onlyIcon": MessageLookupByLibrary.simpleMessage("仅图标"), - "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage("仅统计代理"), - "onlyStatisticsProxyDesc": MessageLookupByLibrary.simpleMessage( - "开启后,将只统计代理流量", - ), + "onlyStatisticsProxy": MessageLookupByLibrary.simpleMessage("仅统计代理流量"), "optional": MessageLookupByLibrary.simpleMessage("可选"), "options": MessageLookupByLibrary.simpleMessage("选项"), "other": MessageLookupByLibrary.simpleMessage("其他"), "otherContributors": MessageLookupByLibrary.simpleMessage("其他贡献者"), + "outboundIp": MessageLookupByLibrary.simpleMessage("出站 IP"), "outboundMode": MessageLookupByLibrary.simpleMessage("出站模式"), "override": MessageLookupByLibrary.simpleMessage("覆写"), "overrideDns": MessageLookupByLibrary.simpleMessage("覆写DNS"), - "overrideDnsDesc": MessageLookupByLibrary.simpleMessage("开启后将覆盖配置中的DNS选项"), + "overrideEntries": MessageLookupByLibrary.simpleMessage("覆写项"), "overrideMode": MessageLookupByLibrary.simpleMessage("覆写模式"), + "overrideNtp": MessageLookupByLibrary.simpleMessage("覆写NTP"), "overrideScript": MessageLookupByLibrary.simpleMessage("覆写脚本"), + "overwriteIssueCoreRejected": m34, + "overwriteIssueDuplicateName": m35, + "overwriteIssueEmptyName": MessageLookupByLibrary.simpleMessage("名称为空"), + "overwriteIssueGroupLoop": m36, + "overwriteIssueMissingProviders": m37, + "overwriteIssueMissingProxies": m38, + "overwriteIssueNoProxySource": MessageLookupByLibrary.simpleMessage( + "未选择任何代理或代理集,内核会拒绝该策略组", + ), + "overwriteIssueProviderShadowed": m39, + "overwriteIssueReservedName": m40, + "overwriteIssueSubscriptionGroupMissingProxies": m41, + "overwriteIssuesSummary": m42, "overwriteTypeCustom": MessageLookupByLibrary.simpleMessage("自定义"), "overwriteTypeCustomDesc": MessageLookupByLibrary.simpleMessage( - "自定义模式,支持完全自定义修改代理组以及规则", + "自定义模式,支持完全自定义修改代理、策略组以及规则", ), "palette": MessageLookupByLibrary.simpleMessage("调色板"), "password": MessageLookupByLibrary.simpleMessage("密码"), @@ -541,10 +779,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "port": MessageLookupByLibrary.simpleMessage("端口"), "portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"), - "portTip": m24, - "preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"), + "portTip": m43, "prerequisites": MessageLookupByLibrary.simpleMessage("前置条件"), - "pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"), + "pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下组合键"), "preview": MessageLookupByLibrary.simpleMessage("预览"), "previousMatch": MessageLookupByLibrary.simpleMessage("上一个匹配"), "process": MessageLookupByLibrary.simpleMessage("进程"), @@ -554,7 +791,7 @@ class MessageLookup extends MessageLookupByLibrary { "profileAutoUpdateIntervalNullValidationDesc": MessageLookupByLibrary.simpleMessage("请输入自动更新间隔时间"), "profileHasUpdate": MessageLookupByLibrary.simpleMessage( - "配置文件已经修改,是否关闭自动更新 ", + "配置文件已经修改,是否关闭自动更新?", ), "profileNameNullValidationDesc": MessageLookupByLibrary.simpleMessage( "请输入配置名称", @@ -568,73 +805,73 @@ class MessageLookup extends MessageLookupByLibrary { "profiles": MessageLookupByLibrary.simpleMessage("配置"), "profilesSort": MessageLookupByLibrary.simpleMessage("配置排序"), "project": MessageLookupByLibrary.simpleMessage("项目"), + "providerInUse": m44, + "providerRenameShadowed": m45, + "providerSourceSubscription": MessageLookupByLibrary.simpleMessage("订阅"), + "providerUrlTip": MessageLookupByLibrary.simpleMessage("仅支持远程资源"), "providers": MessageLookupByLibrary.simpleMessage("外部资源"), "proxies": MessageLookupByLibrary.simpleMessage("代理"), - "proxiesCount": m25, + "proxiesCount": m46, "proxiesEmpty": MessageLookupByLibrary.simpleMessage("代理为空"), "proxyChains": MessageLookupByLibrary.simpleMessage("代理链"), - "proxyDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "检测到选中的代理存在异常", + "proxyDefinition": MessageLookupByLibrary.simpleMessage("完整配置"), + "proxyDefinitionNotMap": MessageLookupByLibrary.simpleMessage( + "配置必须是包含 name 和 type 的 YAML 映射", ), "proxyFilter": MessageLookupByLibrary.simpleMessage("节点过滤器"), "proxyGroup": MessageLookupByLibrary.simpleMessage("策略组"), - "proxyGroupDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "检测到当前策略组异常", - ), "proxyGroupEmpty": MessageLookupByLibrary.simpleMessage("策略组为空"), "proxyGroupNameDuplicate": MessageLookupByLibrary.simpleMessage("策略组名称重复"), - "proxyGroupNameEmpty": MessageLookupByLibrary.simpleMessage("策略组名称不能为空"), - "proxyNameserver": MessageLookupByLibrary.simpleMessage("代理域名服务器"), - "proxyNameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析代理节点的域名"), - "proxyProviderDetectedAbnormal": MessageLookupByLibrary.simpleMessage( - "检测到选中的代理集存在异常", - ), + "proxyNode": MessageLookupByLibrary.simpleMessage("代理节点"), "proxyProviders": MessageLookupByLibrary.simpleMessage("代理集"), "proxyProvidersEmpty": MessageLookupByLibrary.simpleMessage("代理集为空"), "proxyProvidersNotEmpty": MessageLookupByLibrary.simpleMessage("代理集不能为空"), "proxyType": MessageLookupByLibrary.simpleMessage("代理类型"), "pruneCache": MessageLookupByLibrary.simpleMessage("修剪缓存"), + "pureBlack": MessageLookupByLibrary.simpleMessage("纯黑"), "pureBlackMode": MessageLookupByLibrary.simpleMessage("纯黑模式"), "qrcode": MessageLookupByLibrary.simpleMessage("二维码"), "qrcodeDesc": MessageLookupByLibrary.simpleMessage("扫描二维码获取配置文件"), + "quickAdd": MessageLookupByLibrary.simpleMessage("快捷添加"), + "quickEdit": MessageLookupByLibrary.simpleMessage("快速编辑"), "quickFill": MessageLookupByLibrary.simpleMessage("一键填入"), "rainbowScheme": MessageLookupByLibrary.simpleMessage("彩虹"), + "recentRequests": MessageLookupByLibrary.simpleMessage("最近请求"), + "recordType": MessageLookupByLibrary.simpleMessage("记录类型"), "redirPort": MessageLookupByLibrary.simpleMessage("Redir端口"), "redo": MessageLookupByLibrary.simpleMessage("重做"), + "releaseMemory": MessageLookupByLibrary.simpleMessage("释放内存"), + "releaseMemoryFailed": MessageLookupByLibrary.simpleMessage("释放内存失败"), "remote": MessageLookupByLibrary.simpleMessage("远程"), - "remoteBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到WebDAV"), "remoteDestination": MessageLookupByLibrary.simpleMessage("远程目标"), "remove": MessageLookupByLibrary.simpleMessage("移除"), + "replace": MessageLookupByLibrary.simpleMessage("替换"), + "replaceAll": MessageLookupByLibrary.simpleMessage("全部替换"), "request": MessageLookupByLibrary.simpleMessage("请求"), "requests": MessageLookupByLibrary.simpleMessage("请求"), - "requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"), + "requestsAndUpdates": MessageLookupByLibrary.simpleMessage("请求与更新"), "reset": MessageLookupByLibrary.simpleMessage("重置"), "resetPageChangesTip": MessageLookupByLibrary.simpleMessage( "当前页面存在更改,确定重置吗?", ), - "resetTip": MessageLookupByLibrary.simpleMessage("确定要重置吗?"), + "resetTip": MessageLookupByLibrary.simpleMessage("确定要重置吗?"), "resources": MessageLookupByLibrary.simpleMessage("资源"), - "resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"), "respectRules": MessageLookupByLibrary.simpleMessage("遵守规则"), "respectRulesDesc": MessageLookupByLibrary.simpleMessage( - "DNS连接跟随rules,需配置proxy-server-nameserver", + "DNS连接遵守规则,需配置Proxy Server Nameserver", ), + "responseCode": MessageLookupByLibrary.simpleMessage("响应码"), "restart": MessageLookupByLibrary.simpleMessage("重启"), "restartCoreTip": MessageLookupByLibrary.simpleMessage("您确定要重启核心吗?"), "restore": MessageLookupByLibrary.simpleMessage("恢复"), "restoreAllData": MessageLookupByLibrary.simpleMessage("恢复所有数据"), - "restoreException": MessageLookupByLibrary.simpleMessage("恢复异常"), - "restoreFromFileDesc": MessageLookupByLibrary.simpleMessage("通过文件恢复数据"), - "restoreFromWebDAVDesc": MessageLookupByLibrary.simpleMessage( - "通过WebDAV恢复数据", - ), "restoreOnlyConfig": MessageLookupByLibrary.simpleMessage("仅恢复配置文件"), "restoreStrategy": MessageLookupByLibrary.simpleMessage("恢复策略"), "restoreStrategyCompatible": MessageLookupByLibrary.simpleMessage("兼容"), "restoreStrategyOverride": MessageLookupByLibrary.simpleMessage("覆盖"), "restoreSuccess": MessageLookupByLibrary.simpleMessage("恢复成功"), + "retry": MessageLookupByLibrary.simpleMessage("重试"), "routeAddress": MessageLookupByLibrary.simpleMessage("路由地址"), - "routeAddressDesc": MessageLookupByLibrary.simpleMessage("配置监听路由地址"), "routeMode": MessageLookupByLibrary.simpleMessage("路由模式"), "routeModeBypassPrivate": MessageLookupByLibrary.simpleMessage("绕过私有路由地址"), "routeModeConfig": MessageLookupByLibrary.simpleMessage("使用配置"), @@ -655,7 +892,7 @@ class MessageLookup extends MessageLookupByLibrary { "通配符匹配,仅支持*和?通配符", ), "ruleActionDscpDesc": MessageLookupByLibrary.simpleMessage( - "匹配DSCP标记 (仅限 tproxy udp 入站)", + "匹配DSCP标记(仅限 tproxy udp 入站)", ), "ruleActionDstPortDesc": MessageLookupByLibrary.simpleMessage("匹配请求目标端口范围"), "ruleActionGeoipDesc": MessageLookupByLibrary.simpleMessage("匹配 IP 所属国家代码"), @@ -670,7 +907,7 @@ class MessageLookup extends MessageLookupByLibrary { ), "ruleActionIpAsnDesc": MessageLookupByLibrary.simpleMessage("匹配 IP 所属 ASN"), "ruleActionIpCidr6Desc": MessageLookupByLibrary.simpleMessage( - "匹配 IP 地址范围, IP-CIDR6 只是一个别名", + "匹配 IP 地址范围,IP-CIDR6 只是一个别名", ), "ruleActionIpCidrDesc": MessageLookupByLibrary.simpleMessage("匹配 IP 地址范围"), "ruleActionIpSuffixDesc": MessageLookupByLibrary.simpleMessage( @@ -718,17 +955,32 @@ class MessageLookup extends MessageLookupByLibrary { ), "ruleActionSrcPortDesc": MessageLookupByLibrary.simpleMessage("匹配请求来源端口范围"), "ruleActionSubRuleDesc": MessageLookupByLibrary.simpleMessage( - "匹配至子规则,需要注意括号的使用", + "匹配至子规则,需要注意括号的使用", ), "ruleActionUidDesc": MessageLookupByLibrary.simpleMessage( "匹配 Linux USER ID", ), "ruleEmpty": MessageLookupByLibrary.simpleMessage("规则为空"), "ruleName": MessageLookupByLibrary.simpleMessage("规则名称"), + "rulePresetBittorrentDirect": MessageLookupByLibrary.simpleMessage( + "BT 下载直连", + ), + "rulePresetBlockDot": MessageLookupByLibrary.simpleMessage( + "屏蔽 DNS over TLS", + ), + "rulePresetBlockQuic": MessageLookupByLibrary.simpleMessage("屏蔽 QUIC"), + "rulePresetBlockStun": MessageLookupByLibrary.simpleMessage("屏蔽 STUN"), + "rulePresetLanDirect": MessageLookupByLibrary.simpleMessage("局域网直连"), + "rulePresetSystemServicesDirect": MessageLookupByLibrary.simpleMessage( + "Apple 与 Microsoft 直连", + ), + "ruleProviders": MessageLookupByLibrary.simpleMessage("规则集"), "ruleSet": MessageLookupByLibrary.simpleMessage("规则集"), "ruleTarget": MessageLookupByLibrary.simpleMessage("规则目标"), "rules": MessageLookupByLibrary.simpleMessage("规则"), - "rulesCount": m26, + "rulesCount": m47, + "safeMode": MessageLookupByLibrary.simpleMessage("安全模式"), + "safeModeAppTitle": m48, "save": MessageLookupByLibrary.simpleMessage("保存"), "saveChanges": MessageLookupByLibrary.simpleMessage("是否保存更改?"), "script": MessageLookupByLibrary.simpleMessage("脚本"), @@ -738,18 +990,31 @@ class MessageLookup extends MessageLookupByLibrary { "scrollToSelected": MessageLookupByLibrary.simpleMessage("滚动到已选"), "search": MessageLookupByLibrary.simpleMessage("搜索"), "seconds": MessageLookupByLibrary.simpleMessage("秒"), - "secondsCount": m27, + "secondsCount": m49, "selectAll": MessageLookupByLibrary.simpleMessage("全选"), - "selectMatchTarget": MessageLookupByLibrary.simpleMessage( - "选择 MATCH-TARGET", - ), "selectProxies": MessageLookupByLibrary.simpleMessage("选择代理"), "selectProxyProviders": MessageLookupByLibrary.simpleMessage("选择代理集"), "selectRuleSet": MessageLookupByLibrary.simpleMessage("请选择规则集"), "selectSplitStrategy": MessageLookupByLibrary.simpleMessage("请选择分流策略"), "selectSubRule": MessageLookupByLibrary.simpleMessage("请选择子规则"), "selected": MessageLookupByLibrary.simpleMessage("已选择"), - "selectedCountTitle": m28, + "selectedCountTitle": m50, + "server": MessageLookupByLibrary.simpleMessage("服务器"), + "serviceAvailable": MessageLookupByLibrary.simpleMessage("可用"), + "serviceBlocked": MessageLookupByLibrary.simpleMessage("已被封禁"), + "serviceCheck": MessageLookupByLibrary.simpleMessage("检测"), + "serviceCheckAll": MessageLookupByLibrary.simpleMessage("全部检测"), + "serviceCheckedAt": m51, + "serviceComingSoon": MessageLookupByLibrary.simpleMessage("即将上线"), + "serviceDisallowedIsp": MessageLookupByLibrary.simpleMessage("不允许的 ISP"), + "serviceFailed": MessageLookupByLibrary.simpleMessage("检测失败"), + "serviceManage": MessageLookupByLibrary.simpleMessage("管理服务"), + "serviceOriginalsOnly": MessageLookupByLibrary.simpleMessage("仅限自制内容"), + "servicePending": MessageLookupByLibrary.simpleMessage("待检测"), + "serviceRestricted": MessageLookupByLibrary.simpleMessage("访问受限"), + "serviceStatus": MessageLookupByLibrary.simpleMessage("服务状态"), + "serviceUnavailable": MessageLookupByLibrary.simpleMessage("不可用"), + "serviceUnsupportedRegion": MessageLookupByLibrary.simpleMessage("地区不支持"), "settings": MessageLookupByLibrary.simpleMessage("设置"), "show": MessageLookupByLibrary.simpleMessage("显示"), "showLess": MessageLookupByLibrary.simpleMessage("收起"), @@ -757,14 +1022,16 @@ class MessageLookup extends MessageLookupByLibrary { "showNotificationStopAction": MessageLookupByLibrary.simpleMessage( "通知栏显示停止按钮", ), - "showNotificationStopActionDesc": MessageLookupByLibrary.simpleMessage( - "在常驻通知上显示停止按钮。若系统因此总是展开通知,可关闭", - ), "showPassword": MessageLookupByLibrary.simpleMessage("显示密码"), "shrink": MessageLookupByLibrary.simpleMessage("紧凑"), + "sidebarBlur": MessageLookupByLibrary.simpleMessage("侧边栏背景模糊"), + "sidebarBlurDesc": MessageLookupByLibrary.simpleMessage("侧边栏透出窗口后方模糊的桌面"), "silentLaunch": MessageLookupByLibrary.simpleMessage("静默启动"), - "silentLaunchDesc": MessageLookupByLibrary.simpleMessage("后台启动"), + "silentLaunchDesc": MessageLookupByLibrary.simpleMessage("启动时不显示窗口"), + "singleAdd": MessageLookupByLibrary.simpleMessage("单条添加"), + "singleValueTip": m52, "size": MessageLookupByLibrary.simpleMessage("尺寸"), + "slide": MessageLookupByLibrary.simpleMessage("滑动"), "socksPort": MessageLookupByLibrary.simpleMessage("Socks端口"), "sort": MessageLookupByLibrary.simpleMessage("排序"), "source": MessageLookupByLibrary.simpleMessage("来源"), @@ -781,33 +1048,34 @@ class MessageLookup extends MessageLookupByLibrary { "标准模式,覆写基础配置,提供简单追加规则能力", ), "start": MessageLookupByLibrary.simpleMessage("启动"), - "startVpn": MessageLookupByLibrary.simpleMessage("正在启动VPN..."), + "startFromScratch": MessageLookupByLibrary.simpleMessage("从零开始"), + "startVpn": MessageLookupByLibrary.simpleMessage("正在启动VPN…"), + "startupAndBackground": MessageLookupByLibrary.simpleMessage("启动与后台"), "status": MessageLookupByLibrary.simpleMessage("状态"), "statusDesc": MessageLookupByLibrary.simpleMessage("关闭后将使用系统DNS"), "stop": MessageLookupByLibrary.simpleMessage("暂停"), - "stopVpn": MessageLookupByLibrary.simpleMessage("正在停止VPN..."), + "stopVpn": MessageLookupByLibrary.simpleMessage("正在停止VPN…"), + "strategy": MessageLookupByLibrary.simpleMessage("策略"), "style": MessageLookupByLibrary.simpleMessage("风格"), "subRule": MessageLookupByLibrary.simpleMessage("子规则"), "subRuleEmpty": MessageLookupByLibrary.simpleMessage("子规则为空"), "subRuleNotEmpty": MessageLookupByLibrary.simpleMessage("子规则不能为空"), "submit": MessageLookupByLibrary.simpleMessage("提交"), "subscriptionInfo": MessageLookupByLibrary.simpleMessage("订阅信息"), - "suspended": MessageLookupByLibrary.simpleMessage("挂起中..."), + "suspended": MessageLookupByLibrary.simpleMessage("挂起中…"), "sync": MessageLookupByLibrary.simpleMessage("同步"), "system": MessageLookupByLibrary.simpleMessage("系统"), "systemApp": MessageLookupByLibrary.simpleMessage("系统应用"), "systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"), - "systemProxyDesc": MessageLookupByLibrary.simpleMessage("设置系统代理"), "tab": MessageLookupByLibrary.simpleMessage("标签页"), "tabAnimation": MessageLookupByLibrary.simpleMessage("选项卡动画"), - "tabAnimationDesc": MessageLookupByLibrary.simpleMessage("仅在移动视图中有效"), "tapToAuthorize": MessageLookupByLibrary.simpleMessage("点击授权"), "tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"), - "tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"), "testInterval": MessageLookupByLibrary.simpleMessage("测试间隔"), "testUrl": MessageLookupByLibrary.simpleMessage("测速链接"), "testWhenUsed": MessageLookupByLibrary.simpleMessage("使用时测试"), "textScale": MessageLookupByLibrary.simpleMessage("文本缩放"), + "textScalePreview": MessageLookupByLibrary.simpleMessage("应用内的文字将以这个大小显示"), "theme": MessageLookupByLibrary.simpleMessage("主题"), "themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"), "themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"), @@ -817,10 +1085,11 @@ class MessageLookup extends MessageLookupByLibrary { "timeout": MessageLookupByLibrary.simpleMessage("超时"), "tip": MessageLookupByLibrary.simpleMessage("提示"), "toggle": MessageLookupByLibrary.simpleMessage("切换"), - "toggleLabel": MessageLookupByLibrary.simpleMessage("切换标签"), + "tolerance": MessageLookupByLibrary.simpleMessage("容差"), "tonalSpotScheme": MessageLookupByLibrary.simpleMessage("调性点缀"), "tools": MessageLookupByLibrary.simpleMessage("工具"), "torch": MessageLookupByLibrary.simpleMessage("手电筒"), + "total": MessageLookupByLibrary.simpleMessage("总计"), "totalTraffic": MessageLookupByLibrary.simpleMessage("总流量"), "tproxyPort": MessageLookupByLibrary.simpleMessage("Tproxy端口"), "trafficUsage": MessageLookupByLibrary.simpleMessage("流量统计"), @@ -830,7 +1099,6 @@ class MessageLookup extends MessageLookupByLibrary { "turnOn": MessageLookupByLibrary.simpleMessage("开启"), "undo": MessageLookupByLibrary.simpleMessage("撤销"), "unifiedDelay": MessageLookupByLibrary.simpleMessage("统一延迟"), - "unifiedDelayDesc": MessageLookupByLibrary.simpleMessage("去除握手等额外延迟"), "unknown": MessageLookupByLibrary.simpleMessage("未知"), "unknownNetworkError": MessageLookupByLibrary.simpleMessage("未知网络错误"), "unmaximize": MessageLookupByLibrary.simpleMessage("向下还原"), @@ -840,7 +1108,7 @@ class MessageLookup extends MessageLookupByLibrary { "upload": MessageLookupByLibrary.simpleMessage("上传"), "url": MessageLookupByLibrary.simpleMessage("URL"), "urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"), - "urlTip": m29, + "urlTip": m53, "useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"), "useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"), "usedTraffic": MessageLookupByLibrary.simpleMessage("已用流量"), @@ -857,7 +1125,12 @@ class MessageLookup extends MessageLookupByLibrary { "vpnTip": MessageLookupByLibrary.simpleMessage("重启VPN后改变生效"), "webDAVConfiguration": MessageLookupByLibrary.simpleMessage("WebDAV配置"), "whitelistMode": MessageLookupByLibrary.simpleMessage("白名单模式"), - "yearsAgo": m30, + "writeToSystem": MessageLookupByLibrary.simpleMessage("写入系统"), + "writeToSystemDesc": MessageLookupByLibrary.simpleMessage( + "同时设置系统时钟,Android上不生效", + ), + "yearsAgo": m54, + "yes": MessageLookupByLibrary.simpleMessage("是"), "zhCN": MessageLookupByLibrary.simpleMessage("中文简体"), }; } diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index a25fcbdf..8ab850c9 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -105,31 +105,11 @@ class AppLocalizations { return Intl.message('Logs', name: 'logs', desc: '', args: []); } - /// `Captured log records` - String get logsDesc { - return Intl.message( - 'Captured log records', - name: 'logsDesc', - desc: '', - args: [], - ); - } - /// `Resources` String get resources { return Intl.message('Resources', name: 'resources', desc: '', args: []); } - /// `Information about external resources` - String get resourcesDesc { - return Intl.message( - 'Information about external resources', - name: 'resourcesDesc', - desc: '', - args: [], - ); - } - /// `Traffic usage` String get trafficUsage { return Intl.message( @@ -170,6 +150,146 @@ class AppLocalizations { ); } + /// `Service status` + String get serviceStatus { + return Intl.message( + 'Service status', + name: 'serviceStatus', + desc: '', + args: [], + ); + } + + /// `Access restricted` + String get serviceRestricted { + return Intl.message( + 'Access restricted', + name: 'serviceRestricted', + desc: '', + args: [], + ); + } + + /// `Available` + String get serviceAvailable { + return Intl.message( + 'Available', + name: 'serviceAvailable', + desc: '', + args: [], + ); + } + + /// `Unavailable` + String get serviceUnavailable { + return Intl.message( + 'Unavailable', + name: 'serviceUnavailable', + desc: '', + args: [], + ); + } + + /// `Check failed` + String get serviceFailed { + return Intl.message( + 'Check failed', + name: 'serviceFailed', + desc: '', + args: [], + ); + } + + /// `Disallowed ISP` + String get serviceDisallowedIsp { + return Intl.message( + 'Disallowed ISP', + name: 'serviceDisallowedIsp', + desc: '', + args: [], + ); + } + + /// `Blocked` + String get serviceBlocked { + return Intl.message('Blocked', name: 'serviceBlocked', desc: '', args: []); + } + + /// `Region not supported` + String get serviceUnsupportedRegion { + return Intl.message( + 'Region not supported', + name: 'serviceUnsupportedRegion', + desc: '', + args: [], + ); + } + + /// `Originals only` + String get serviceOriginalsOnly { + return Intl.message( + 'Originals only', + name: 'serviceOriginalsOnly', + desc: '', + args: [], + ); + } + + /// `Coming soon` + String get serviceComingSoon { + return Intl.message( + 'Coming soon', + name: 'serviceComingSoon', + desc: '', + args: [], + ); + } + + /// `Not checked` + String get servicePending { + return Intl.message( + 'Not checked', + name: 'servicePending', + desc: '', + args: [], + ); + } + + /// `Manage services` + String get serviceManage { + return Intl.message( + 'Manage services', + name: 'serviceManage', + desc: '', + args: [], + ); + } + + /// `Check` + String get serviceCheck { + return Intl.message('Check', name: 'serviceCheck', desc: '', args: []); + } + + /// `Check all` + String get serviceCheckAll { + return Intl.message( + 'Check all', + name: 'serviceCheckAll', + desc: '', + args: [], + ); + } + + /// `Checked at {time}` + String serviceCheckedAt(Object time) { + return Intl.message( + 'Checked at $time', + name: 'serviceCheckedAt', + desc: '', + args: [time], + ); + } + /// `Upload` String get upload { return Intl.message('Upload', name: 'upload', desc: '', args: []); @@ -210,10 +330,10 @@ class AppLocalizations { ); } - /// `No profiles yet, please add one first` + /// `Add a profile to get started` String get nullProfileDesc { return Intl.message( - 'No profiles yet, please add one first', + 'Add a profile to get started', name: 'nullProfileDesc', desc: '', args: [], @@ -295,16 +415,6 @@ class AppLocalizations { return Intl.message('Allow LAN', name: 'allowLan', desc: '', args: []); } - /// `Allow proxy access over the LAN` - String get allowLanDesc { - return Intl.message( - 'Allow proxy access over the LAN', - name: 'allowLanDesc', - desc: '', - args: [], - ); - } - /// `TUN` String get tun { return Intl.message('TUN', name: 'tun', desc: '', args: []); @@ -330,16 +440,6 @@ class AppLocalizations { ); } - /// `Override the default system exit behavior` - String get minimizeOnExitDesc { - return Intl.message( - 'Override the default system exit behavior', - name: 'minimizeOnExitDesc', - desc: '', - args: [], - ); - } - /// `Auto launch` String get autoLaunch { return Intl.message('Auto launch', name: 'autoLaunch', desc: '', args: []); @@ -365,10 +465,10 @@ class AppLocalizations { ); } - /// `Start in the background` + /// `Start without showing the window` String get silentLaunchDesc { return Intl.message( - 'Start in the background', + 'Start without showing the window', name: 'silentLaunchDesc', desc: '', args: [], @@ -415,16 +515,6 @@ class AppLocalizations { ); } - /// `Check for updates automatically when the app starts` - String get autoCheckUpdateDesc { - return Intl.message( - 'Check for updates automatically when the app starts', - name: 'autoCheckUpdateDesc', - desc: '', - args: [], - ); - } - /// `Verify TLS certificates` String get checkCertificate { return Intl.message( @@ -465,21 +555,6 @@ class AppLocalizations { ); } - /// `Application` - String get application { - return Intl.message('Application', name: 'application', desc: '', args: []); - } - - /// `Adjust application settings` - String get applicationDesc { - return Intl.message( - 'Adjust application settings', - name: 'applicationDesc', - desc: '', - args: [], - ); - } - /// `Edit` String get edit { return Intl.message('Edit', name: 'edit', desc: '', args: []); @@ -810,6 +885,21 @@ class AppLocalizations { ); } + /// `Safe mode` + String get safeMode { + return Intl.message('Safe mode', name: 'safeMode', desc: '', args: []); + } + + /// `{appName} (Safe mode)` + String safeModeAppTitle(Object appName) { + return Intl.message( + '$appName (Safe mode)', + name: 'safeModeAppTitle', + desc: '', + args: [appName], + ); + } + /// `Project` String get project { return Intl.message('Project', name: 'project', desc: '', args: []); @@ -840,19 +930,14 @@ class AppLocalizations { ); } - /// `Starting VPN...` + /// `Starting VPN…` String get startVpn { - return Intl.message( - 'Starting VPN...', - name: 'startVpn', - desc: '', - args: [], - ); + return Intl.message('Starting VPN…', name: 'startVpn', desc: '', args: []); } - /// `Stopping VPN...` + /// `Stopping VPN…` String get stopVpn { - return Intl.message('Stopping VPN...', name: 'stopVpn', desc: '', args: []); + return Intl.message('Stopping VPN…', name: 'stopVpn', desc: '', args: []); } /// `Compatibility mode` @@ -1080,16 +1165,6 @@ class AppLocalizations { ); } - /// `When enabled, some apps can bypass the VPN` - String get allowBypassDesc { - return Intl.message( - 'When enabled, some apps can bypass the VPN', - name: 'allowBypassDesc', - desc: '', - args: [], - ); - } - /// `External controller` String get externalController { return Intl.message( @@ -1130,11 +1205,31 @@ class AppLocalizations { return Intl.message('General', name: 'general', desc: '', args: []); } - /// `Set the system proxy` - String get systemProxyDesc { + /// `Startup and background` + String get startupAndBackground { return Intl.message( - 'Set the system proxy', - name: 'systemProxyDesc', + 'Startup and background', + name: 'startupAndBackground', + desc: '', + args: [], + ); + } + + /// `Requests and updates` + String get requestsAndUpdates { + return Intl.message( + 'Requests and updates', + name: 'requestsAndUpdates', + desc: '', + args: [], + ); + } + + /// `Logs and diagnostics` + String get logsAndDiagnostics { + return Intl.message( + 'Logs and diagnostics', + name: 'logsAndDiagnostics', desc: '', args: [], ); @@ -1155,16 +1250,6 @@ class AppLocalizations { ); } - /// `Remove extra delays such as handshakes` - String get unifiedDelayDesc { - return Intl.message( - 'Remove extra delays such as handshakes', - name: 'unifiedDelayDesc', - desc: '', - args: [], - ); - } - /// `TCP concurrent` String get tcpConcurrent { return Intl.message( @@ -1175,16 +1260,6 @@ class AppLocalizations { ); } - /// `Allow concurrent TCP connections` - String get tcpConcurrentDesc { - return Intl.message( - 'Allow concurrent TCP connections', - name: 'tcpConcurrentDesc', - desc: '', - args: [], - ); - } - /// `Geo low-memory mode` String get geodataLoader { return Intl.message( @@ -1195,26 +1270,16 @@ class AppLocalizations { ); } - /// `Use the low-memory Geo loader` - String get geodataLoaderDesc { - return Intl.message( - 'Use the low-memory Geo loader', - name: 'geodataLoaderDesc', - desc: '', - args: [], - ); - } - /// `Requests` String get requests { return Intl.message('Requests', name: 'requests', desc: '', args: []); } - /// `View recent request records` - String get requestsDesc { + /// `Recent requests` + String get recentRequests { return Intl.message( - 'View recent request records', - name: 'requestsDesc', + 'Recent requests', + name: 'recentRequests', desc: '', args: [], ); @@ -1250,21 +1315,21 @@ class AppLocalizations { return Intl.message('Connections', name: 'connections', desc: '', args: []); } - /// `Inbound` - String get inbound { - return Intl.message('Inbound', name: 'inbound', desc: '', args: []); - } - - /// `View current connection data` - String get connectionsDesc { + /// `Live connections` + String get liveConnections { return Intl.message( - 'View current connection data', - name: 'connectionsDesc', + 'Live connections', + name: 'liveConnections', desc: '', args: [], ); } + /// `Inbound` + String get inbound { + return Intl.message('Inbound', name: 'inbound', desc: '', args: []); + } + /// `Intranet IP` String get intranetIP { return Intl.message('Intranet IP', name: 'intranetIP', desc: '', args: []); @@ -1400,6 +1465,16 @@ class AppLocalizations { ); } + /// `App icon design` + String get appIconDesign { + return Intl.message( + 'App icon design', + name: 'appIconDesign', + desc: '', + args: [], + ); + } + /// `Auto close connections` String get autoCloseConnections { return Intl.message( @@ -1430,16 +1505,6 @@ class AppLocalizations { ); } - /// `When enabled, only proxy traffic is counted` - String get onlyStatisticsProxyDesc { - return Intl.message( - 'When enabled, only proxy traffic is counted', - name: 'onlyStatisticsProxyDesc', - desc: '', - args: [], - ); - } - /// `Stop button in notification` String get showNotificationStopAction { return Intl.message( @@ -1450,16 +1515,6 @@ class AppLocalizations { ); } - /// `Show a stop button on the persistent notification. Turn it off if your system keeps the notification expanded because of it` - String get showNotificationStopActionDesc { - return Intl.message( - 'Show a stop button on the persistent notification. Turn it off if your system keeps the notification expanded because of it', - name: 'showNotificationStopActionDesc', - desc: '', - args: [], - ); - } - /// `Pure black mode` String get pureBlackMode { return Intl.message( @@ -1470,6 +1525,26 @@ class AppLocalizations { ); } + /// `Sidebar blur` + String get sidebarBlur { + return Intl.message( + 'Sidebar blur', + name: 'sidebarBlur', + desc: '', + args: [], + ); + } + + /// `Show the blurred desktop behind the window through the sidebar` + String get sidebarBlurDesc { + return Intl.message( + 'Show the blurred desktop behind the window through the sidebar', + name: 'sidebarBlurDesc', + desc: '', + args: [], + ); + } + /// `TCP keep-alive interval` String get keepAliveIntervalDesc { return Intl.message( @@ -1495,26 +1570,6 @@ class AppLocalizations { return Intl.message('Remote', name: 'remote', desc: '', args: []); } - /// `Back up data to WebDAV` - String get remoteBackupDesc { - return Intl.message( - 'Back up data to WebDAV', - name: 'remoteBackupDesc', - desc: '', - args: [], - ); - } - - /// `Back up data locally` - String get localBackupDesc { - return Intl.message( - 'Back up data locally', - name: 'localBackupDesc', - desc: '', - args: [], - ); - } - /// `Mode` String get mode { return Intl.message('Mode', name: 'mode', desc: '', args: []); @@ -1605,16 +1660,6 @@ class AppLocalizations { return Intl.message('Stop', name: 'stop', desc: '', args: []); } - /// `Update DNS-related settings` - String get dnsDesc { - return Intl.message( - 'Update DNS-related settings', - name: 'dnsDesc', - desc: '', - args: [], - ); - } - /// `Key` String get key { return Intl.message('Key', name: 'key', desc: '', args: []); @@ -1625,11 +1670,6 @@ class AppLocalizations { return Intl.message('Value', name: 'value', desc: '', args: []); } - /// `Append hosts` - String get hostsDesc { - return Intl.message('Append hosts', name: 'hostsDesc', desc: '', args: []); - } - /// `Changes take effect after restarting the VPN` String get vpnTip { return Intl.message( @@ -1655,21 +1695,21 @@ class AppLocalizations { return Intl.message('Options', name: 'options', desc: '', args: []); } - /// `Loopback unlock tool` - String get loopback { - return Intl.message( - 'Loopback unlock tool', - name: 'loopback', - desc: '', - args: [], - ); + /// `Enabled` + String get enabled { + return Intl.message('Enabled', name: 'enabled', desc: '', args: []); } - /// `Used for UWP loopback exemption` - String get loopbackDesc { + /// `Disabled` + String get disabled { + return Intl.message('Disabled', name: 'disabled', desc: '', args: []); + } + + /// `UWP loopback exemption` + String get loopback { return Intl.message( - 'Used for UWP loopback exemption', - name: 'loopbackDesc', + 'UWP loopback exemption', + name: 'loopback', desc: '', args: [], ); @@ -1695,6 +1735,56 @@ class AppLocalizations { ); } + /// `Rule providers` + String get ruleProviders { + return Intl.message( + 'Rule providers', + name: 'ruleProviders', + desc: '', + args: [], + ); + } + + /// `App proxy providers` + String get appProxyProviders { + return Intl.message( + 'App proxy providers', + name: 'appProxyProviders', + desc: '', + args: [], + ); + } + + /// `App rule providers` + String get appRuleProviders { + return Intl.message( + 'App rule providers', + name: 'appRuleProviders', + desc: '', + args: [], + ); + } + + /// `Behavior` + String get behavior { + return Intl.message('Behavior', name: 'behavior', desc: '', args: []); + } + + /// `Format` + String get format { + return Intl.message('Format', name: 'format', desc: '', args: []); + } + + /// `Only remote providers are supported` + String get providerUrlTip { + return Intl.message( + 'Only remote providers are supported', + name: 'providerUrlTip', + desc: '', + args: [], + ); + } + /// `Subscription info` String get subscriptionInfo { return Intl.message( @@ -1715,16 +1805,116 @@ class AppLocalizations { ); } - /// `When enabled, the DNS options in the profile are overridden` - String get overrideDnsDesc { + /// `Override NTP` + String get overrideNtp { return Intl.message( - 'When enabled, the DNS options in the profile are overridden', - name: 'overrideDnsDesc', + 'Override NTP', + name: 'overrideNtp', desc: '', args: [], ); } + /// `Take the time from an NTP server instead of the system clock` + String get ntpStatusDesc { + return Intl.message( + 'Take the time from an NTP server instead of the system clock', + name: 'ntpStatusDesc', + desc: '', + args: [], + ); + } + + /// `Server` + String get server { + return Intl.message('Server', name: 'server', desc: '', args: []); + } + + /// `Sync interval (minutes)` + String get ntpInterval { + return Intl.message( + 'Sync interval (minutes)', + name: 'ntpInterval', + desc: '', + args: [], + ); + } + + /// `Dialer proxy` + String get dialerProxy { + return Intl.message( + 'Dialer proxy', + name: 'dialerProxy', + desc: '', + args: [], + ); + } + + /// `The outbound used to reach the NTP server` + String get dialerProxyDesc { + return Intl.message( + 'The outbound used to reach the NTP server', + name: 'dialerProxyDesc', + desc: '', + args: [], + ); + } + + /// `Write to system` + String get writeToSystem { + return Intl.message( + 'Write to system', + name: 'writeToSystem', + desc: '', + args: [], + ); + } + + /// `Also set the system clock; Android ignores it` + String get writeToSystemDesc { + return Intl.message( + 'Also set the system clock; Android ignores it', + name: 'writeToSystemDesc', + desc: '', + args: [], + ); + } + + /// `Override entries` + String get overrideEntries { + return Intl.message( + 'Override entries', + name: 'overrideEntries', + desc: '', + args: [], + ); + } + + /// `Add override entry` + String get addOverrideEntry { + return Intl.message( + 'Add override entry', + name: 'addOverrideEntry', + desc: '', + args: [], + ); + } + + /// `Discard the changes?` + String get discardChanges { + return Intl.message( + 'Discard the changes?', + name: 'discardChanges', + desc: '', + args: [], + ); + } + + /// `Quick edit` + String get quickEdit { + return Intl.message('Quick edit', name: 'quickEdit', desc: '', args: []); + } + /// `Status` String get status { return Intl.message('Status', name: 'status', desc: '', args: []); @@ -1740,16 +1930,6 @@ class AppLocalizations { ); } - /// `Prefer HTTP/3 for DoH` - String get preferH3Desc { - return Intl.message( - 'Prefer HTTP/3 for DoH', - name: 'preferH3Desc', - desc: '', - args: [], - ); - } - /// `Respect rules` String get respectRules { return Intl.message( @@ -1760,10 +1940,10 @@ class AppLocalizations { ); } - /// `DNS connections follow rules; requires proxy-server-nameserver` + /// `DNS connections follow rules; requires Proxy Server Nameserver` String get respectRulesDesc { return Intl.message( - 'DNS connections follow rules; requires proxy-server-nameserver', + 'DNS connections follow rules; requires Proxy Server Nameserver', name: 'respectRulesDesc', desc: '', args: [], @@ -1795,41 +1975,6 @@ class AppLocalizations { ); } - /// `Default nameserver` - String get defaultNameserver { - return Intl.message( - 'Default nameserver', - name: 'defaultNameserver', - desc: '', - args: [], - ); - } - - /// `Used to resolve DNS servers` - String get defaultNameserverDesc { - return Intl.message( - 'Used to resolve DNS servers', - name: 'defaultNameserverDesc', - desc: '', - args: [], - ); - } - - /// `Nameserver` - String get nameserver { - return Intl.message('Nameserver', name: 'nameserver', desc: '', args: []); - } - - /// `Used to resolve domains` - String get nameserverDesc { - return Intl.message( - 'Used to resolve domains', - name: 'nameserverDesc', - desc: '', - args: [], - ); - } - /// `Use hosts` String get useHosts { return Intl.message('Use hosts', name: 'useHosts', desc: '', args: []); @@ -1845,61 +1990,6 @@ class AppLocalizations { ); } - /// `Nameserver policy` - String get nameserverPolicy { - return Intl.message( - 'Nameserver policy', - name: 'nameserverPolicy', - desc: '', - args: [], - ); - } - - /// `Specify the nameserver policy for matching domains` - String get nameserverPolicyDesc { - return Intl.message( - 'Specify the nameserver policy for matching domains', - name: 'nameserverPolicyDesc', - desc: '', - args: [], - ); - } - - /// `Proxy nameserver` - String get proxyNameserver { - return Intl.message( - 'Proxy nameserver', - name: 'proxyNameserver', - desc: '', - args: [], - ); - } - - /// `Used to resolve proxy node domains` - String get proxyNameserverDesc { - return Intl.message( - 'Used to resolve proxy node domains', - name: 'proxyNameserverDesc', - desc: '', - args: [], - ); - } - - /// `Fallback` - String get fallback { - return Intl.message('Fallback', name: 'fallback', desc: '', args: []); - } - - /// `Usually an overseas DNS` - String get fallbackDesc { - return Intl.message( - 'Usually an overseas DNS', - name: 'fallbackDesc', - desc: '', - args: [], - ); - } - /// `Fallback filter` String get fallbackFilter { return Intl.message( @@ -1910,21 +2000,91 @@ class AppLocalizations { ); } - /// `GeoIP code` - String get geoipCode { - return Intl.message('GeoIP code', name: 'geoipCode', desc: '', args: []); - } - - /// `IP/CIDR` - String get ipcidr { - return Intl.message('IP/CIDR', name: 'ipcidr', desc: '', args: []); - } - /// `Domain` String get domain { return Intl.message('Domain', name: 'domain', desc: '', args: []); } + /// `Listen routing mark` + String get listenRoutingMark { + return Intl.message( + 'Listen routing mark', + name: 'listenRoutingMark', + desc: '', + args: [], + ); + } + + /// `Linux only` + String get listenRoutingMarkDesc { + return Intl.message( + 'Linux only', + name: 'listenRoutingMarkDesc', + desc: '', + args: [], + ); + } + + /// `IPv6 timeout (ms)` + String get ipv6Timeout { + return Intl.message( + 'IPv6 timeout (ms)', + name: 'ipv6Timeout', + desc: '', + args: [], + ); + } + + /// `Cache algorithm` + String get cacheAlgorithm { + return Intl.message( + 'Cache algorithm', + name: 'cacheAlgorithm', + desc: '', + args: [], + ); + } + + /// `Cache size` + String get cacheMaxSize { + return Intl.message('Cache size', name: 'cacheMaxSize', desc: '', args: []); + } + + /// `Fake-IP range (IPv6)` + String get fakeipRange6 { + return Intl.message( + 'Fake-IP range (IPv6)', + name: 'fakeipRange6', + desc: '', + args: [], + ); + } + + /// `Fake-IP filter mode` + String get fakeipFilterMode { + return Intl.message( + 'Fake-IP filter mode', + name: 'fakeipFilterMode', + desc: '', + args: [], + ); + } + + /// `blacklist excludes matches, whitelist fakes only matches, rule matches as rules` + String get fakeipFilterModeDesc { + return Intl.message( + 'blacklist excludes matches, whitelist fakes only matches, rule matches as rules', + name: 'fakeipFilterModeDesc', + desc: '', + args: [], + ); + } + + /// `Fake-IP TTL` + String get fakeipTtl { + return Intl.message('Fake-IP TTL', name: 'fakeipTtl', desc: '', args: []); + } + /// `Reset` String get reset { return Intl.message('Reset', name: 'reset', desc: '', args: []); @@ -1960,21 +2120,351 @@ class AppLocalizations { return Intl.message('TUN', name: 'actionTun', desc: '', args: []); } + /// `Rule mode` + String get actionRuleMode { + return Intl.message( + 'Rule mode', + name: 'actionRuleMode', + desc: '', + args: [], + ); + } + + /// `Global mode` + String get actionGlobalMode { + return Intl.message( + 'Global mode', + name: 'actionGlobalMode', + desc: '', + args: [], + ); + } + + /// `Direct mode` + String get actionDirectMode { + return Intl.message( + 'Direct mode', + name: 'actionDirectMode', + desc: '', + args: [], + ); + } + + /// `Test all delays` + String get actionDelayTest { + return Intl.message( + 'Test all delays', + name: 'actionDelayTest', + desc: '', + args: [], + ); + } + + /// `Update profiles` + String get actionUpdateProfiles { + return Intl.message( + 'Update profiles', + name: 'actionUpdateProfiles', + desc: '', + args: [], + ); + } + /// `Disclaimer` String get disclaimer { return Intl.message('Disclaimer', name: 'disclaimer', desc: '', args: []); } - /// `This software is intended only for non-commercial uses such as learning and research. Using it for any commercial purpose is strictly prohibited; any commercial activity is unrelated to this software.` + /// `Before using FlClash ("the Software"), please read this statement carefully and make sure you understand all of it. Tapping "Agree" means you have read, understood, and accept every term below. If you do not agree, tap "Exit" and stop using the Software.` String get disclaimerDesc { return Intl.message( - 'This software is intended only for non-commercial uses such as learning and research. Using it for any commercial purpose is strictly prohibited; any commercial activity is unrelated to this software.', + 'Before using FlClash ("the Software"), please read this statement carefully and make sure you understand all of it. Tapping "Agree" means you have read, understood, and accept every term below. If you do not agree, tap "Exit" and stop using the Software.', name: 'disclaimerDesc', desc: '', args: [], ); } + /// `Nature of the software` + String get disclaimerSoftwareTitle { + return Intl.message( + 'Nature of the software', + name: 'disclaimerSoftwareTitle', + desc: '', + args: [], + ); + } + + /// `The Software is an open-source network proxy client built on the Clash.Meta (mihomo) core. It only provides local tooling such as configuration management, rule-based routing, and traffic forwarding.\n\nThe Software itself does not provide any proxy server, node, subscription, or network access service, and has no partnership, agency, or guarantee relationship with any provider of such services.` + String get disclaimerSoftwareContent { + return Intl.message( + 'The Software is an open-source network proxy client built on the Clash.Meta (mihomo) core. It only provides local tooling such as configuration management, rule-based routing, and traffic forwarding.\n\nThe Software itself does not provide any proxy server, node, subscription, or network access service, and has no partnership, agency, or guarantee relationship with any provider of such services.', + name: 'disclaimerSoftwareContent', + desc: '', + args: [], + ); + } + + /// `Restrictions on use` + String get disclaimerUsageTitle { + return Intl.message( + 'Restrictions on use', + name: 'disclaimerUsageTitle', + desc: '', + args: [], + ); + } + + /// `The Software is intended only for non-commercial uses such as learning, exchange, and technical research. Using it for any commercial purpose is strictly prohibited, including but not limited to paid distribution, bundled sales, use as part of a commercial service, or doing business in the name of the Software. Any commercial activity is unrelated to the Software and its developers.\n\nUsing the Software for anything that violates the laws and regulations of your country or region is strictly prohibited, including but not limited to bypassing lawfully imposed network access restrictions, spreading illegal content, launching network attacks, or infringing the lawful rights of others.` + String get disclaimerUsageContent { + return Intl.message( + 'The Software is intended only for non-commercial uses such as learning, exchange, and technical research. Using it for any commercial purpose is strictly prohibited, including but not limited to paid distribution, bundled sales, use as part of a commercial service, or doing business in the name of the Software. Any commercial activity is unrelated to the Software and its developers.\n\nUsing the Software for anything that violates the laws and regulations of your country or region is strictly prohibited, including but not limited to bypassing lawfully imposed network access restrictions, spreading illegal content, launching network attacks, or infringing the lawful rights of others.', + name: 'disclaimerUsageContent', + desc: '', + args: [], + ); + } + + /// `Your responsibility` + String get disclaimerResponsibilityTitle { + return Intl.message( + 'Your responsibility', + name: 'disclaimerResponsibilityTitle', + desc: '', + args: [], + ); + } + + /// `You are responsible for making sure that using the Software is lawful where you live, and you alone bear the legal responsibility for everything you do with it and its consequences.\n\nThe subscriptions, nodes, and configurations you import are your own choice. Whether their source is lawful, their content is safe, and their service is reliable is a matter between you and their providers.` + String get disclaimerResponsibilityContent { + return Intl.message( + 'You are responsible for making sure that using the Software is lawful where you live, and you alone bear the legal responsibility for everything you do with it and its consequences.\n\nThe subscriptions, nodes, and configurations you import are your own choice. Whether their source is lawful, their content is safe, and their service is reliable is a matter between you and their providers.', + name: 'disclaimerResponsibilityContent', + desc: '', + args: [], + ); + } + + /// `Third-party content` + String get disclaimerThirdPartyTitle { + return Intl.message( + 'Third-party content', + name: 'disclaimerThirdPartyTitle', + desc: '', + args: [], + ); + } + + /// `Subscription links, configuration files, rule sets, scripts, external resources, and external links are all provided by third parties. The developers cannot and do not review or guarantee their legality, accuracy, security, or availability.\n\nAny data leak, financial loss, account ban, or other loss caused by third-party content is to be settled between you and the third party; the developers bear no responsibility for it.` + String get disclaimerThirdPartyContent { + return Intl.message( + 'Subscription links, configuration files, rule sets, scripts, external resources, and external links are all provided by third parties. The developers cannot and do not review or guarantee their legality, accuracy, security, or availability.\n\nAny data leak, financial loss, account ban, or other loss caused by third-party content is to be settled between you and the third party; the developers bear no responsibility for it.', + name: 'disclaimerThirdPartyContent', + desc: '', + args: [], + ); + } + + /// `No warranty` + String get disclaimerWarrantyTitle { + return Intl.message( + 'No warranty', + name: 'disclaimerWarrantyTitle', + desc: '', + args: [], + ); + } + + /// `The Software is provided "as is" and "as available", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, non-infringement, uninterrupted availability, freedom from errors, or freedom from security vulnerabilities.\n\nThe developers do not guarantee that the Software will meet your needs or that it will run without interruption or error.` + String get disclaimerWarrantyContent { + return Intl.message( + 'The Software is provided "as is" and "as available", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, non-infringement, uninterrupted availability, freedom from errors, or freedom from security vulnerabilities.\n\nThe developers do not guarantee that the Software will meet your needs or that it will run without interruption or error.', + name: 'disclaimerWarrantyContent', + desc: '', + args: [], + ); + } + + /// `Limitation of liability` + String get disclaimerLiabilityTitle { + return Intl.message( + 'Limitation of liability', + name: 'disclaimerLiabilityTitle', + desc: '', + args: [], + ); + } + + /// `To the maximum extent permitted by applicable law, neither the developers nor any contributor shall be liable for any direct, indirect, incidental, special, punitive, or consequential damages arising from the use of or inability to use the Software, including but not limited to data loss, device damage, network failures, business interruption, lost profits, or any resulting legal dispute, even if advised of the possibility of such damages.` + String get disclaimerLiabilityContent { + return Intl.message( + 'To the maximum extent permitted by applicable law, neither the developers nor any contributor shall be liable for any direct, indirect, incidental, special, punitive, or consequential damages arising from the use of or inability to use the Software, including but not limited to data loss, device damage, network failures, business interruption, lost profits, or any resulting legal dispute, even if advised of the possibility of such damages.', + name: 'disclaimerLiabilityContent', + desc: '', + args: [], + ); + } + + /// `Data collection and privacy` + String get disclaimerPrivacyTitle { + return Intl.message( + 'Data collection and privacy', + name: 'disclaimerPrivacyTitle', + desc: '', + args: [], + ); + } + + /// `The Software does not collect or upload your subscription URLs, node details, configuration content, visited websites, connection records, traffic content, or logs. This data stays on your device and the developers have no access to it.\n\nThe Software only reaches the network when you use a feature that needs it, such as fetching the subscription URL you provided when updating a profile, or contacting GitHub when checking for updates.\n\nThe desktop versions (Windows, macOS, Linux) include no analytics or crash reporting service. The Android version includes the following two Google Firebase services to improve stability:` + String get disclaimerPrivacyContent { + return Intl.message( + 'The Software does not collect or upload your subscription URLs, node details, configuration content, visited websites, connection records, traffic content, or logs. This data stays on your device and the developers have no access to it.\n\nThe Software only reaches the network when you use a feature that needs it, such as fetching the subscription URL you provided when updating a profile, or contacting GitHub when checking for updates.\n\nThe desktop versions (Windows, macOS, Linux) include no analytics or crash reporting service. The Android version includes the following two Google Firebase services to improve stability:', + name: 'disclaimerPrivacyContent', + desc: '', + args: [], + ); + } + + /// `Firebase Crashlytics (crash analytics)` + String get disclaimerCrashlyticsTitle { + return Intl.message( + 'Firebase Crashlytics (crash analytics)', + name: 'disclaimerCrashlyticsTitle', + desc: '', + args: [], + ); + } + + /// `When the app crashes, a crash report is uploaded automatically.\n\nWhat is collected: the crash stack trace and error message, the time of the crash, the app version and build number, the device brand and model, the Android version, screen orientation, free memory and storage, whether the device is rooted, and a random installation ID that is created on install and reset on reinstall.\n\nPurpose: only to locate and fix crashes.\n\nYou can turn it off at any time under "Tools > General > Crash analytics".` + String get disclaimerCrashlyticsContent { + return Intl.message( + 'When the app crashes, a crash report is uploaded automatically.\n\nWhat is collected: the crash stack trace and error message, the time of the crash, the app version and build number, the device brand and model, the Android version, screen orientation, free memory and storage, whether the device is rooted, and a random installation ID that is created on install and reset on reinstall.\n\nPurpose: only to locate and fix crashes.\n\nYou can turn it off at any time under "Tools > General > Crash analytics".', + name: 'disclaimerCrashlyticsContent', + desc: '', + args: [], + ); + } + + /// `Firebase Analytics (usage statistics)` + String get disclaimerAnalyticsTitle { + return Intl.message( + 'Firebase Analytics (usage statistics)', + name: 'disclaimerAnalyticsTitle', + desc: '', + args: [], + ); + } + + /// `Basic app usage statistics are collected automatically with Firebase.\n\nWhat is collected: basic events such as first launch, app opens and session length, and app updates; an app instance ID; the device model, OS version, and system language; and an approximate country- or region-level location inferred from the IP address.\n\nPurpose: only to understand the number of active devices, version distribution, and OS compatibility. The developers do not use this data for advertising, do not sell it, and do not link it to your subscriptions or configurations.` + String get disclaimerAnalyticsContent { + return Intl.message( + 'Basic app usage statistics are collected automatically with Firebase.\n\nWhat is collected: basic events such as first launch, app opens and session length, and app updates; an app instance ID; the device model, OS version, and system language; and an approximate country- or region-level location inferred from the IP address.\n\nPurpose: only to understand the number of active devices, version distribution, and OS compatibility. The developers do not use this data for advertising, do not sell it, and do not link it to your subscriptions or configurations.', + name: 'disclaimerAnalyticsContent', + desc: '', + args: [], + ); + } + + /// `This data is processed and stored by Google on our behalf, may be transferred to servers outside your country or region (such as in the United States), and is governed by the Google Privacy Policy and the Firebase privacy and security documentation. Crash reports are kept for up to 90 days; statistics are kept under the Firebase default retention policy.` + String get disclaimerDataProcessingContent { + return Intl.message( + 'This data is processed and stored by Google on our behalf, may be transferred to servers outside your country or region (such as in the United States), and is governed by the Google Privacy Policy and the Firebase privacy and security documentation. Crash reports are kept for up to 90 days; statistics are kept under the Firebase default retention policy.', + name: 'disclaimerDataProcessingContent', + desc: '', + args: [], + ); + } + + /// `Open-source license` + String get disclaimerLicenseTitle { + return Intl.message( + 'Open-source license', + name: 'disclaimerLicenseTitle', + desc: '', + args: [], + ); + } + + /// `The Software is open source under the GPL-3.0 license. You may use, modify, and distribute it freely as long as you comply with that license, which requires derivative works to be released under GPL-3.0 as well and the original copyright notices to be kept.\n\nThird-party components in the Software, including the Clash.Meta core, follow their own licenses. The original authors are not responsible for any issue arising from modified or redistributed versions.` + String get disclaimerLicenseContent { + return Intl.message( + 'The Software is open source under the GPL-3.0 license. You may use, modify, and distribute it freely as long as you comply with that license, which requires derivative works to be released under GPL-3.0 as well and the original copyright notices to be kept.\n\nThird-party components in the Software, including the Clash.Meta core, follow their own licenses. The original authors are not responsible for any issue arising from modified or redistributed versions.', + name: 'disclaimerLicenseContent', + desc: '', + args: [], + ); + } + + /// `Changes to this statement` + String get disclaimerChangesTitle { + return Intl.message( + 'Changes to this statement', + name: 'disclaimerChangesTitle', + desc: '', + args: [], + ); + } + + /// `The developers may revise this statement with any release, and the revision takes effect when that release is published. Continuing to use the Software after updating means you accept the revised statement.` + String get disclaimerChangesContent { + return Intl.message( + 'The developers may revise this statement with any release, and the revision takes effect when that release is published. Continuing to use the Software after updating means you accept the revised statement.', + name: 'disclaimerChangesContent', + desc: '', + args: [], + ); + } + + /// `Acceptance` + String get disclaimerAcceptTitle { + return Intl.message( + 'Acceptance', + name: 'disclaimerAcceptTitle', + desc: '', + args: [], + ); + } + + /// `By installing, copying, or using the Software, you are deemed to have read and agreed to this entire statement. If you disagree with any of its terms, stop using and uninstall the Software immediately.` + String get disclaimerAcceptContent { + return Intl.message( + 'By installing, copying, or using the Software, you are deemed to have read and agreed to this entire statement. If you disagree with any of its terms, stop using and uninstall the Software immediately.', + name: 'disclaimerAcceptContent', + desc: '', + args: [], + ); + } + + /// `Android only` + String get disclaimerAndroidOnly { + return Intl.message( + 'Android only', + name: 'disclaimerAndroidOnly', + desc: '', + args: [], + ); + } + + /// `Google Privacy Policy` + String get disclaimerGooglePrivacy { + return Intl.message( + 'Google Privacy Policy', + name: 'disclaimerGooglePrivacy', + desc: '', + args: [], + ); + } + + /// `Firebase privacy and security` + String get disclaimerFirebasePrivacy { + return Intl.message( + 'Firebase privacy and security', + name: 'disclaimerFirebasePrivacy', + desc: '', + args: [], + ); + } + /// `Agree` String get agree { return Intl.message('Agree', name: 'agree', desc: '', args: []); @@ -1990,41 +2480,56 @@ class AppLocalizations { ); } - /// `Control the app with the keyboard` - String get hotkeyManagementDesc { + /// `Global hotkeys work even while the window is hidden. Tap an action to record its key combination.` + String get hotkeyDesc { return Intl.message( - 'Control the app with the keyboard', - name: 'hotkeyManagementDesc', + 'Global hotkeys work even while the window is hidden. Tap an action to record its key combination.', + name: 'hotkeyDesc', desc: '', args: [], ); } - /// `Please press a key` + /// `Not set` + String get hotkeyNotSet { + return Intl.message('Not set', name: 'hotkeyNotSet', desc: '', args: []); + } + + /// `Press a key combination` String get pressKeyboard { return Intl.message( - 'Please press a key', + 'Press a key combination', name: 'pressKeyboard', desc: '', args: [], ); } - /// `Please enter a valid hotkey` - String get inputCorrectHotkey { + /// `Include at least one of {modifiers}` + String hotkeyNeedsModifier(Object modifiers) { return Intl.message( - 'Please enter a valid hotkey', - name: 'inputCorrectHotkey', + 'Include at least one of $modifiers', + name: 'hotkeyNeedsModifier', desc: '', - args: [], + args: [modifiers], ); } - /// `Hotkey conflict` - String get hotkeyConflict { + /// `Already used by “{action}”. Saving moves it here.` + String hotkeyConflictWith(Object action) { return Intl.message( - 'Hotkey conflict', - name: 'hotkeyConflict', + 'Already used by “$action”. Saving moves it here.', + name: 'hotkeyConflictWith', + desc: '', + args: [action], + ); + } + + /// `Not registered, it may be taken by another app` + String get hotkeyUnavailable { + return Intl.message( + 'Not registered, it may be taken by another app', + name: 'hotkeyUnavailable', desc: '', args: [], ); @@ -2035,11 +2540,6 @@ class AppLocalizations { return Intl.message('Remove', name: 'remove', desc: '', args: []); } - /// `No hotkeys yet` - String get noHotKey { - return Intl.message('No hotkeys yet', name: 'noHotKey', desc: '', args: []); - } - /// `No network` String get noNetwork { return Intl.message('No network', name: 'noNetwork', desc: '', args: []); @@ -2075,9 +2575,44 @@ class AppLocalizations { return Intl.message('Icon style', name: 'iconStyle', desc: '', args: []); } - /// `Icon only` - String get onlyIcon { - return Intl.message('Icon only', name: 'onlyIcon', desc: '', args: []); + /// `Filled` + String get iconStyleFilled { + return Intl.message('Filled', name: 'iconStyleFilled', desc: '', args: []); + } + + /// `Plain` + String get iconStylePlain { + return Intl.message('Plain', name: 'iconStylePlain', desc: '', args: []); + } + + /// `Hidden` + String get iconStyleHidden { + return Intl.message('Hidden', name: 'iconStyleHidden', desc: '', args: []); + } + + /// `Filter` + String get filter { + return Intl.message('Filter', name: 'filter', desc: '', args: []); + } + + /// `Hide timed-out nodes` + String get hideTimeoutProxies { + return Intl.message( + 'Hide timed-out nodes', + name: 'hideTimeoutProxies', + desc: '', + args: [], + ); + } + + /// `Leave out nodes whose last delay test timed out` + String get hideTimeoutProxiesDesc { + return Intl.message( + 'Leave out nodes whose last delay test timed out', + name: 'hideTimeoutProxiesDesc', + desc: '', + args: [], + ); } /// `Stack mode` @@ -2090,16 +2625,6 @@ class AppLocalizations { return Intl.message('Network', name: 'network', desc: '', args: []); } - /// `Adjust network-related settings` - String get networkDesc { - return Intl.message( - 'Adjust network-related settings', - name: 'networkDesc', - desc: '', - args: [], - ); - } - /// `Bypass domains` String get bypassDomain { return Intl.message( @@ -2190,16 +2715,6 @@ class AppLocalizations { ); } - /// `Configure the listened route addresses` - String get routeAddressDesc { - return Intl.message( - 'Configure the listened route addresses', - name: 'routeAddressDesc', - desc: '', - args: [], - ); - } - /// `Outbound interface` String get interfaceNameMode { return Intl.message( @@ -2275,6 +2790,141 @@ class AppLocalizations { return Intl.message('Memory info', name: 'memoryInfo', desc: '', args: []); } + /// `Total` + String get total { + return Intl.message('Total', name: 'total', desc: '', args: []); + } + + /// `Release memory` + String get releaseMemory { + return Intl.message( + 'Release memory', + name: 'releaseMemory', + desc: '', + args: [], + ); + } + + /// `Heap in use` + String get memoryCoreHeapInuse { + return Intl.message( + 'Heap in use', + name: 'memoryCoreHeapInuse', + desc: '', + args: [], + ); + } + + /// `Heap idle` + String get memoryCoreHeapIdle { + return Intl.message( + 'Heap idle', + name: 'memoryCoreHeapIdle', + desc: '', + args: [], + ); + } + + /// `Goroutine stacks` + String get memoryCoreStack { + return Intl.message( + 'Goroutine stacks', + name: 'memoryCoreStack', + desc: '', + args: [], + ); + } + + /// `Runtime overhead` + String get memoryCoreRuntime { + return Intl.message( + 'Runtime overhead', + name: 'memoryCoreRuntime', + desc: '', + args: [], + ); + } + + /// `Core is not running` + String get memoryCoreNotRunning { + return Intl.message( + 'Core is not running', + name: 'memoryCoreNotRunning', + desc: '', + args: [], + ); + } + + /// `Resident memory` + String get memoryAppResident { + return Intl.message( + 'Resident memory', + name: 'memoryAppResident', + desc: '', + args: [], + ); + } + + /// `App & shared` + String get memoryAppShared { + return Intl.message( + 'App & shared', + name: 'memoryAppShared', + desc: '', + args: [], + ); + } + + /// `Estimated from process resident memory; it may differ from what the system reports.` + String get memoryEstimateDesc { + return Intl.message( + 'Estimated from process resident memory; it may differ from what the system reports.', + name: 'memoryEstimateDesc', + desc: '', + args: [], + ); + } + + /// `The Core runs inside the app process. Its share is estimated from runtime stats, and the rest counts as app and shared memory.` + String get memoryEstimateSharedDesc { + return Intl.message( + 'The Core runs inside the app process. Its share is estimated from runtime stats, and the rest counts as app and shared memory.', + name: 'memoryEstimateSharedDesc', + desc: '', + args: [], + ); + } + + /// `Memory released` + String get memoryReleased { + return Intl.message( + 'Memory released', + name: 'memoryReleased', + desc: '', + args: [], + ); + } + + /// `Released {size}` + String memoryReleasedSize(Object size) { + return Intl.message( + 'Released $size', + name: 'memoryReleasedSize', + desc: '', + args: [size], + ); + } + + /// `Failed to release memory` + String get releaseMemoryFailed { + return Intl.message( + 'Failed to release memory', + name: 'releaseMemoryFailed', + desc: '', + args: [], + ); + } + /// `Cancel` String get cancel { return Intl.message('Cancel', name: 'cancel', desc: '', args: []); @@ -2365,31 +3015,16 @@ class AppLocalizations { return Intl.message('Redo', name: 'redo', desc: '', args: []); } + /// `Word wrap` + String get lineWrap { + return Intl.message('Word wrap', name: 'lineWrap', desc: '', args: []); + } + /// `None` String get none { return Intl.message('None', name: 'none', desc: '', args: []); } - /// `Basic configuration` - String get basicConfig { - return Intl.message( - 'Basic configuration', - name: 'basicConfig', - desc: '', - args: [], - ); - } - - /// `Modify the basic configuration globally` - String get basicConfigDesc { - return Intl.message( - 'Modify the basic configuration globally', - name: 'basicConfigDesc', - desc: '', - args: [], - ); - } - /// `Advanced configuration` String get advancedConfig { return Intl.message( @@ -2400,10 +3035,10 @@ class AppLocalizations { ); } - /// `Provides diverse configuration options` + /// `Network, DNS, added rules, and scripts` String get advancedConfigDesc { return Intl.message( - 'Provides diverse configuration options', + 'Network, DNS, added rules, and scripts', name: 'advancedConfigDesc', desc: '', args: [], @@ -2445,16 +3080,6 @@ class AppLocalizations { return Intl.message('Rule target', name: 'ruleTarget', desc: '', args: []); } - /// `Match target` - String get matchTargetTitle { - return Intl.message( - 'Match target', - name: 'matchTargetTitle', - desc: '', - args: [], - ); - } - /// `MATCH-TARGET` String get matchTarget { return Intl.message( @@ -2475,26 +3100,6 @@ class AppLocalizations { ); } - /// `Where rules targeting MATCH-TARGET go. Defaults to the target of the final MATCH rule in this profile.` - String get matchTargetDesc { - return Intl.message( - 'Where rules targeting MATCH-TARGET go. Defaults to the target of the final MATCH rule in this profile.', - name: 'matchTargetDesc', - desc: '', - args: [], - ); - } - - /// `Select MATCH-TARGET` - String get selectMatchTarget { - return Intl.message( - 'Select MATCH-TARGET', - name: 'selectMatchTarget', - desc: '', - args: [], - ); - } - /// `Source IP` String get sourceIp { return Intl.message('Source IP', name: 'sourceIp', desc: '', args: []); @@ -2520,24 +3125,39 @@ class AppLocalizations { ); } - /// `Enabling causes some performance loss` - String get findProcessModeDesc { + /// `Bottom bar` + String get navigationBarStyle { return Intl.message( - 'Enabling causes some performance loss', - name: 'findProcessModeDesc', + 'Bottom bar', + name: 'navigationBarStyle', desc: '', args: [], ); } - /// `Only effective in mobile view` - String get tabAnimationDesc { - return Intl.message( - 'Only effective in mobile view', - name: 'tabAnimationDesc', - desc: '', - args: [], - ); + /// `Floating` + String get floating { + return Intl.message('Floating', name: 'floating', desc: '', args: []); + } + + /// `Docked` + String get docked { + return Intl.message('Docked', name: 'docked', desc: '', args: []); + } + + /// `Slide` + String get slide { + return Intl.message('Slide', name: 'slide', desc: '', args: []); + } + + /// `Fade` + String get fade { + return Intl.message('Fade', name: 'fade', desc: '', args: []); + } + + /// `Pure black` + String get pureBlack { + return Intl.message('Pure black', name: 'pureBlack', desc: '', args: []); } /// `Color schemes` @@ -2715,6 +3335,26 @@ class AppLocalizations { return Intl.message('Text scaling', name: 'textScale', desc: '', args: []); } + /// `Text in the app will look like this` + String get textScalePreview { + return Intl.message( + 'Text in the app will look like this', + name: 'textScalePreview', + desc: '', + args: [], + ); + } + + /// `Follow system` + String get followSystem { + return Intl.message( + 'Follow system', + name: 'followSystem', + desc: '', + args: [], + ); + } + /// `Internet` String get internet { return Intl.message('Internet', name: 'internet', desc: '', args: []); @@ -2825,16 +3465,66 @@ class AppLocalizations { ); } - /// `Separate multiple values with commas` - String get multipleValuesTip { + /// `Single add` + String get singleAdd { + return Intl.message('Single add', name: 'singleAdd', desc: '', args: []); + } + + /// `Batch add` + String get batchAdd { + return Intl.message('Batch add', name: 'batchAdd', desc: '', args: []); + } + + /// `One item per line, or separated by commas` + String get batchListInputTip { return Intl.message( - 'Separate multiple values with commas', - name: 'multipleValuesTip', + 'One item per line, or separated by commas', + name: 'batchListInputTip', desc: '', args: [], ); } + /// `One entry per line: key, a space, then value` + String get batchMapInputTip { + return Intl.message( + 'One entry per line: key, a space, then value', + name: 'batchMapInputTip', + desc: '', + args: [], + ); + } + + /// `{count} to add, {skipped} skipped as existing` + String batchPreviewTip(Object count, Object skipped) { + return Intl.message( + '$count to add, $skipped skipped as existing', + name: 'batchPreviewTip', + desc: '', + args: [count, skipped], + ); + } + + /// `Line {line}: {message}` + String lineIssueTip(Object line, Object message) { + return Intl.message( + 'Line $line: $message', + name: 'lineIssueTip', + desc: '', + args: [line, message], + ); + } + + /// `{label} must be a single item` + String singleValueTip(Object label) { + return Intl.message( + '$label must be a single item', + name: 'singleValueTip', + desc: '', + args: [label], + ); + } + /// `Are you sure you want to delete this {label}?` String deleteTip(Object label) { return Intl.message( @@ -2955,6 +3645,16 @@ class AppLocalizations { ); } + /// `Start from scratch` + String get startFromScratch { + return Intl.message( + 'Start from scratch', + name: 'startFromScratch', + desc: '', + args: [], + ); + } + /// `Auto-set system DNS` String get autoSetSystemDns { return Intl.message( @@ -3095,14 +3795,9 @@ class AppLocalizations { ); } - /// `Connecting...` + /// `Connecting…` String get connecting { - return Intl.message( - 'Connecting...', - name: 'connecting', - desc: '', - args: [], - ); + return Intl.message('Connecting…', name: 'connecting', desc: '', args: []); } /// `Are you sure you want to restart the core?` @@ -3190,16 +3885,6 @@ class AppLocalizations { ); } - /// `Force-append the system DNS to the configuration` - String get appendSystemDnsTip { - return Intl.message( - 'Force-append the system DNS to the configuration', - name: 'appendSystemDnsTip', - desc: '', - args: [], - ); - } - /// `Edit rule` String get editRule { return Intl.message('Edit rule', name: 'editRule', desc: '', args: []); @@ -3250,6 +3935,71 @@ class AppLocalizations { ); } + /// `Quick add` + String get quickAdd { + return Intl.message('Quick add', name: 'quickAdd', desc: '', args: []); + } + + /// `Block QUIC` + String get rulePresetBlockQuic { + return Intl.message( + 'Block QUIC', + name: 'rulePresetBlockQuic', + desc: '', + args: [], + ); + } + + /// `Block STUN` + String get rulePresetBlockStun { + return Intl.message( + 'Block STUN', + name: 'rulePresetBlockStun', + desc: '', + args: [], + ); + } + + /// `Block DNS over TLS` + String get rulePresetBlockDot { + return Intl.message( + 'Block DNS over TLS', + name: 'rulePresetBlockDot', + desc: '', + args: [], + ); + } + + /// `Apple and Microsoft direct` + String get rulePresetSystemServicesDirect { + return Intl.message( + 'Apple and Microsoft direct', + name: 'rulePresetSystemServicesDirect', + desc: '', + args: [], + ); + } + + /// `BitTorrent direct` + String get rulePresetBittorrentDirect { + return Intl.message( + 'BitTorrent direct', + name: 'rulePresetBittorrentDirect', + desc: '', + args: [], + ); + } + + /// `LAN direct` + String get rulePresetLanDirect { + return Intl.message( + 'LAN direct', + name: 'rulePresetLanDirect', + desc: '', + args: [], + ); + } + /// `Override script` String get overrideScript { return Intl.message( @@ -3280,16 +4030,6 @@ class AppLocalizations { ); } - /// `External fetch` - String get externalFetch { - return Intl.message( - 'External fetch', - name: 'externalFetch', - desc: '', - args: [], - ); - } - /// `Are you sure you want to force crash the core?` String get confirmForceCrashCore { return Intl.message( @@ -3310,9 +4050,9 @@ class AppLocalizations { ); } - /// `Loading...` + /// `Loading…` String get loading { - return Intl.message('Loading...', name: 'loading', desc: '', args: []); + return Intl.message('Loading…', name: 'loading', desc: '', args: []); } /// `{count, plural, =1{1 year ago} other{{count} years ago}}` @@ -3455,10 +4195,10 @@ class AppLocalizations { ); } - /// `Custom mode: fully customize proxy groups and rules` + /// `Custom mode: fully customize proxies, proxy groups and rules` String get overwriteTypeCustomDesc { return Intl.message( - 'Custom mode: fully customize proxy groups and rules', + 'Custom mode: fully customize proxies, proxy groups and rules', name: 'overwriteTypeCustomDesc', desc: '', args: [], @@ -3475,26 +4215,126 @@ class AppLocalizations { ); } - /// `Restore error` - String get restoreException { + /// `This backup comes from a newer version of the app. Update the app before restoring it` + String get backupFromNewerVersion { return Intl.message( - 'Restore error', - name: 'restoreException', + 'This backup comes from a newer version of the app. Update the app before restoring it', + name: 'backupFromNewerVersion', desc: '', args: [], ); } - /// `Network error, please check your connection and try again` - String get networkException { + /// `The request timed out. Check your network or proxy, then try again` + String get networkTimeoutError { return Intl.message( - 'Network error, please check your connection and try again', - name: 'networkException', + 'The request timed out. Check your network or proxy, then try again', + name: 'networkTimeoutError', desc: '', args: [], ); } + /// `Couldn't resolve the server address. Check that the URL is correct and DNS is working` + String get networkHostLookupError { + return Intl.message( + 'Couldn\'t resolve the server address. Check that the URL is correct and DNS is working', + name: 'networkHostLookupError', + desc: '', + args: [], + ); + } + + /// `Couldn't connect to the server. Check your network connection or proxy settings` + String get networkConnectionError { + return Intl.message( + 'Couldn\'t connect to the server. Check your network connection or proxy settings', + name: 'networkConnectionError', + desc: '', + args: [], + ); + } + + /// `Secure connection failed. The server's certificate may be invalid, or the connection is being intercepted` + String get networkTlsError { + return Intl.message( + 'Secure connection failed. The server\'s certificate may be invalid, or the connection is being intercepted', + name: 'networkTlsError', + desc: '', + args: [], + ); + } + + /// `The request was cancelled` + String get networkCancelledError { + return Intl.message( + 'The request was cancelled', + name: 'networkCancelledError', + desc: '', + args: [], + ); + } + + /// `The server denied access (HTTP {code}). The link may have expired, or the credentials are wrong` + String networkAccessDeniedError(Object code) { + return Intl.message( + 'The server denied access (HTTP $code). The link may have expired, or the credentials are wrong', + name: 'networkAccessDeniedError', + desc: '', + args: [code], + ); + } + + /// `Nothing was found at this address (HTTP {code}). Check that the URL is correct` + String networkNotFoundError(Object code) { + return Intl.message( + 'Nothing was found at this address (HTTP $code). Check that the URL is correct', + name: 'networkNotFoundError', + desc: '', + args: [code], + ); + } + + /// `Too many requests (HTTP 429). Wait a moment and try again` + String get networkRateLimitedError { + return Intl.message( + 'Too many requests (HTTP 429). Wait a moment and try again', + name: 'networkRateLimitedError', + desc: '', + args: [], + ); + } + + /// `The server ran into a problem (HTTP {code}). Try again later` + String networkServerError(Object code) { + return Intl.message( + 'The server ran into a problem (HTTP $code). Try again later', + name: 'networkServerError', + desc: '', + args: [code], + ); + } + + /// `The server rejected the request (HTTP {code})` + String networkBadResponseError(Object code) { + return Intl.message( + 'The server rejected the request (HTTP $code)', + name: 'networkBadResponseError', + desc: '', + args: [code], + ); + } + + /// `Network request failed: {detail}` + String networkRequestFailed(Object detail) { + return Intl.message( + 'Network request failed: $detail', + name: 'networkRequestFailed', + desc: '', + args: [detail], + ); + } + /// `Invalid backup file` String get invalidBackupFile { return Intl.message( @@ -3545,26 +4385,6 @@ class AppLocalizations { ); } - /// `Restore data from WebDAV` - String get restoreFromWebDAVDesc { - return Intl.message( - 'Restore data from WebDAV', - name: 'restoreFromWebDAVDesc', - desc: '', - args: [], - ); - } - - /// `Restore data from a file` - String get restoreFromFileDesc { - return Intl.message( - 'Restore data from a file', - name: 'restoreFromFileDesc', - desc: '', - args: [], - ); - } - /// `Restore profiles only` String get restoreOnlyConfig { return Intl.message( @@ -3605,16 +4425,6 @@ class AppLocalizations { ); } - /// `Proxy group name cannot be empty` - String get proxyGroupNameEmpty { - return Intl.message( - 'Proxy group name cannot be empty', - name: 'proxyGroupNameEmpty', - desc: '', - args: [], - ); - } - /// `Duplicate proxy group name` String get proxyGroupNameDuplicate { return Intl.message( @@ -3720,6 +4530,16 @@ class AppLocalizations { ); } + /// `Strategy` + String get strategy { + return Intl.message('Strategy', name: 'strategy', desc: '', args: []); + } + + /// `Tolerance` + String get tolerance { + return Intl.message('Tolerance', name: 'tolerance', desc: '', args: []); + } + /// `Select proxies` String get selectProxies { return Intl.message( @@ -3930,10 +4750,10 @@ class AppLocalizations { ); } - /// `When enabled, the imported proxy providers are overridden` + /// `When enabled, the group takes every proxy provider of this profile: the subscription's own, plus the profiles and app proxy providers any proxy group uses` String get includeAllProxyProvidersTip { return Intl.message( - 'When enabled, the imported proxy providers are overridden', + 'When enabled, the group takes every proxy provider of this profile: the subscription\'s own, plus the profiles and app proxy providers any proxy group uses', name: 'includeAllProxyProvidersTip', desc: '', args: [], @@ -4520,6 +5340,46 @@ class AppLocalizations { ); } + /// `{ruleSet} is an invalid rule set` + String invalidRuleSet(Object ruleSet) { + return Intl.message( + '$ruleSet is an invalid rule set', + name: 'invalidRuleSet', + desc: '', + args: [ruleSet], + ); + } + + /// `Only tcp or udp is supported` + String get invalidNetworkContent { + return Intl.message( + 'Only tcp or udp is supported', + name: 'invalidNetworkContent', + desc: '', + args: [], + ); + } + + /// `Enter numbers or ranges such as 80 or 8000-9000, separated by /` + String get invalidRangeContent { + return Intl.message( + 'Enter numbers or ranges such as 80 or 8000-9000, separated by /', + name: 'invalidRangeContent', + desc: '', + args: [], + ); + } + + /// `A DSCP mark cannot exceed 63` + String get invalidDscpContent { + return Intl.message( + 'A DSCP mark cannot exceed 63', + name: 'invalidDscpContent', + desc: '', + args: [], + ); + } + /// `{proxyName} is an invalid proxy` String invalidProxy(Object proxyName) { return Intl.message( @@ -4530,46 +5390,6 @@ class AppLocalizations { ); } - /// `The current proxy group is abnormal` - String get proxyGroupDetectedAbnormal { - return Intl.message( - 'The current proxy group is abnormal', - name: 'proxyGroupDetectedAbnormal', - desc: '', - args: [], - ); - } - - /// `The selected proxy providers are abnormal` - String get proxyProviderDetectedAbnormal { - return Intl.message( - 'The selected proxy providers are abnormal', - name: 'proxyProviderDetectedAbnormal', - desc: '', - args: [], - ); - } - - /// `The selected proxies are abnormal` - String get proxyDetectedAbnormal { - return Intl.message( - 'The selected proxies are abnormal', - name: 'proxyDetectedAbnormal', - desc: '', - args: [], - ); - } - - /// `Create profile` - String get createProfile { - return Intl.message( - 'Create profile', - name: 'createProfile', - desc: '', - args: [], - ); - } - /// `Location permission required` String get locationPermissionRequired { return Intl.message( @@ -4620,16 +5440,6 @@ class AppLocalizations { ); } - /// `Due to system limitations, the battery optimization status cannot be read correctly while running` - String get batteryOptimizationStatusTip { - return Intl.message( - 'Due to system limitations, the battery optimization status cannot be read correctly while running', - name: 'batteryOptimizationStatusTip', - desc: '', - args: [], - ); - } - /// `Location permission` String get locationPermission { return Intl.message( @@ -4730,9 +5540,9 @@ class AppLocalizations { ); } - /// `Suspended...` + /// `Suspended…` String get suspended { - return Intl.message('Suspended...', name: 'suspended', desc: '', args: []); + return Intl.message('Suspended…', name: 'suspended', desc: '', args: []); } /// `Geo options` @@ -4829,18 +5639,6 @@ class AppLocalizations { ); } - /// `{count, plural, =1{1 entry} other{{count} entries}}` - String entriesCount(num count) { - return Intl.plural( - count, - one: '1 entry', - other: '$count entries', - name: 'entriesCount', - desc: '', - args: [count], - ); - } - /// `{count, plural, =1{1 proxy} other{{count} proxies}}` String proxiesCount(num count) { return Intl.plural( @@ -4965,16 +5763,6 @@ class AppLocalizations { ); } - /// `Toggle labels` - String get toggleLabel { - return Intl.message( - 'Toggle labels', - name: 'toggleLabel', - desc: '', - args: [], - ); - } - /// `Flashlight` String get torch { return Intl.message('Flashlight', name: 'torch', desc: '', args: []); @@ -5055,6 +5843,16 @@ class AppLocalizations { ); } + /// `No matching results` + String get noSearchResults { + return Intl.message( + 'No matching results', + name: 'noSearchResults', + desc: '', + args: [], + ); + } + /// `Add widget` String get addWidget { return Intl.message('Add widget', name: 'addWidget', desc: '', args: []); @@ -5114,6 +5912,511 @@ class AppLocalizations { args: [], ); } + + /// `Outbound IP` + String get outboundIp { + return Intl.message('Outbound IP', name: 'outboundIp', desc: '', args: []); + } + + /// `IP address` + String get ipAddress { + return Intl.message('IP address', name: 'ipAddress', desc: '', args: []); + } + + /// `Level` + String get ipQualityLevel { + return Intl.message('Level', name: 'ipQualityLevel', desc: '', args: []); + } + + /// `Good` + String get ipQualityGood { + return Intl.message('Good', name: 'ipQualityGood', desc: '', args: []); + } + + /// `Normal` + String get ipQualityNormal { + return Intl.message('Normal', name: 'ipQualityNormal', desc: '', args: []); + } + + /// `Risky` + String get ipQualityRisky { + return Intl.message('Risky', name: 'ipQualityRisky', desc: '', args: []); + } + + /// `Type` + String get ipType { + return Intl.message('Type', name: 'ipType', desc: '', args: []); + } + + /// `Residential` + String get ipTypeResidential { + return Intl.message( + 'Residential', + name: 'ipTypeResidential', + desc: '', + args: [], + ); + } + + /// `Mobile network` + String get ipTypeMobile { + return Intl.message( + 'Mobile network', + name: 'ipTypeMobile', + desc: '', + args: [], + ); + } + + /// `Business` + String get ipTypeBusiness { + return Intl.message('Business', name: 'ipTypeBusiness', desc: '', args: []); + } + + /// `Data center` + String get ipTypeHosting { + return Intl.message( + 'Data center', + name: 'ipTypeHosting', + desc: '', + args: [], + ); + } + + /// `Flags` + String get ipFlags { + return Intl.message('Flags', name: 'ipFlags', desc: '', args: []); + } + + /// `Proxy` + String get ipFlagProxy { + return Intl.message('Proxy', name: 'ipFlagProxy', desc: '', args: []); + } + + /// `VPN` + String get ipFlagVpn { + return Intl.message('VPN', name: 'ipFlagVpn', desc: '', args: []); + } + + /// `Tor` + String get ipFlagTor { + return Intl.message('Tor', name: 'ipFlagTor', desc: '', args: []); + } + + /// `Abuse history` + String get ipFlagAbuser { + return Intl.message( + 'Abuse history', + name: 'ipFlagAbuser', + desc: '', + args: [], + ); + } + + /// `Organization` + String get ipOrganization { + return Intl.message( + 'Organization', + name: 'ipOrganization', + desc: '', + args: [], + ); + } + + /// `ASN` + String get ipAsn { + return Intl.message('ASN', name: 'ipAsn', desc: '', args: []); + } + + /// `Answered by` + String get ipQualitySource { + return Intl.message( + 'Answered by', + name: 'ipQualitySource', + desc: '', + args: [], + ); + } + + /// `Sources` + String get ipQualitySources { + return Intl.message( + 'Sources', + name: 'ipQualitySources', + desc: '', + args: [], + ); + } + + /// `Couldn't determine the IP type` + String get ipQualityFailed { + return Intl.message( + 'Couldn\'t determine the IP type', + name: 'ipQualityFailed', + desc: '', + args: [], + ); + } + + /// `Check again` + String get ipQualityRetry { + return Intl.message( + 'Check again', + name: 'ipQualityRetry', + desc: '', + args: [], + ); + } + + /// `No type` + String get ipSourceNoType { + return Intl.message('No type', name: 'ipSourceNoType', desc: '', args: []); + } + + /// `Rate limited` + String get ipSourceRateLimited { + return Intl.message( + 'Rate limited', + name: 'ipSourceRateLimited', + desc: '', + args: [], + ); + } + + /// `Different outbound IP` + String get ipSourceIpMismatch { + return Intl.message( + 'Different outbound IP', + name: 'ipSourceIpMismatch', + desc: '', + args: [], + ); + } + + /// `Hide IP` + String get hideIp { + return Intl.message('Hide IP', name: 'hideIp', desc: '', args: []); + } + + /// `Editor unavailable` + String get editorUnavailable { + return Intl.message( + 'Editor unavailable', + name: 'editorUnavailable', + desc: '', + args: [], + ); + } + + /// `Replace` + String get replace { + return Intl.message('Replace', name: 'replace', desc: '', args: []); + } + + /// `Replace all` + String get replaceAll { + return Intl.message('Replace all', name: 'replaceAll', desc: '', args: []); + } + + /// `Camera permission required` + String get cameraPermissionRequired { + return Intl.message( + 'Camera permission required', + name: 'cameraPermissionRequired', + desc: '', + args: [], + ); + } + + /// `Allow camera access in system settings to scan QR codes, or choose a QR code image from the album.` + String get cameraPermissionDesc { + return Intl.message( + 'Allow camera access in system settings to scan QR codes, or choose a QR code image from the album.', + name: 'cameraPermissionDesc', + desc: '', + args: [], + ); + } + + /// `Camera unavailable` + String get cameraUnavailable { + return Intl.message( + 'Camera unavailable', + name: 'cameraUnavailable', + desc: '', + args: [], + ); + } + + /// `Retry` + String get retry { + return Intl.message('Retry', name: 'retry', desc: '', args: []); + } + + /// `This QR code doesn't contain a profile link` + String get invalidProfileQrcode { + return Intl.message( + 'This QR code doesn\'t contain a profile link', + name: 'invalidProfileQrcode', + desc: '', + args: [], + ); + } + + /// `DNS queries` + String get dnsQueries { + return Intl.message('DNS queries', name: 'dnsQueries', desc: '', args: []); + } + + /// `Record type` + String get recordType { + return Intl.message('Record type', name: 'recordType', desc: '', args: []); + } + + /// `Answers` + String get answers { + return Intl.message('Answers', name: 'answers', desc: '', args: []); + } + + /// `Response code` + String get responseCode { + return Intl.message( + 'Response code', + name: 'responseCode', + desc: '', + args: [], + ); + } + + /// `Error` + String get error { + return Intl.message('Error', name: 'error', desc: '', args: []); + } + + /// `Initiator` + String get initiator { + return Intl.message('Initiator', name: 'initiator', desc: '', args: []); + } + + /// `Cache` + String get cache { + return Intl.message('Cache', name: 'cache', desc: '', args: []); + } + + /// `Proxy node` + String get proxyNode { + return Intl.message('Proxy node', name: 'proxyNode', desc: '', args: []); + } + + /// `Yes` + String get yes { + return Intl.message('Yes', name: 'yes', desc: '', args: []); + } + + /// `No` + String get no { + return Intl.message('No', name: 'no', desc: '', args: []); + } + + /// `This external resource is not a text file` + String get nonTextProviderFile { + return Intl.message( + 'This external resource is not a text file', + name: 'nonTextProviderFile', + desc: '', + args: [], + ); + } + + /// `Add proxy` + String get addCustomProxy { + return Intl.message( + 'Add proxy', + name: 'addCustomProxy', + desc: '', + args: [], + ); + } + + /// `Full configuration` + String get proxyDefinition { + return Intl.message( + 'Full configuration', + name: 'proxyDefinition', + desc: '', + args: [], + ); + } + + /// `The configuration must be a YAML mapping with a name and a type` + String get proxyDefinitionNotMap { + return Intl.message( + 'The configuration must be a YAML mapping with a name and a type', + name: 'proxyDefinitionNotMap', + desc: '', + args: [], + ); + } + + /// `No custom proxies, so the profile's own proxies are used` + String get customProxiesEmpty { + return Intl.message( + 'No custom proxies, so the profile\'s own proxies are used', + name: 'customProxiesEmpty', + desc: '', + args: [], + ); + } + + /// `The name is empty` + String get overwriteIssueEmptyName { + return Intl.message( + 'The name is empty', + name: 'overwriteIssueEmptyName', + desc: '', + args: [], + ); + } + + /// `{name} is a built-in policy name and cannot be used here` + String overwriteIssueReservedName(Object name) { + return Intl.message( + '$name is a built-in policy name and cannot be used here', + name: 'overwriteIssueReservedName', + desc: '', + args: [name], + ); + } + + /// `The name {name} is already used by another proxy or proxy group` + String overwriteIssueDuplicateName(Object name) { + return Intl.message( + 'The name $name is already used by another proxy or proxy group', + name: 'overwriteIssueDuplicateName', + desc: '', + args: [name], + ); + } + + /// `The core cannot parse this proxy: {message}` + String overwriteIssueCoreRejected(Object message) { + return Intl.message( + 'The core cannot parse this proxy: $message', + name: 'overwriteIssueCoreRejected', + desc: '', + args: [message], + ); + } + + /// `These proxies or policies do not exist: {names}` + String overwriteIssueMissingProxies(Object names) { + return Intl.message( + 'These proxies or policies do not exist: $names', + name: 'overwriteIssueMissingProxies', + desc: '', + args: [names], + ); + } + + /// `These proxy providers do not exist: {names}` + String overwriteIssueMissingProviders(Object names) { + return Intl.message( + 'These proxy providers do not exist: $names', + name: 'overwriteIssueMissingProviders', + desc: '', + args: [names], + ); + } + + /// `No proxies or proxy providers are selected, so the core rejects this group` + String get overwriteIssueNoProxySource { + return Intl.message( + 'No proxies or proxy providers are selected, so the core rejects this group', + name: 'overwriteIssueNoProxySource', + desc: '', + args: [], + ); + } + + /// `Proxy groups reference each other in a loop: {path}` + String overwriteIssueGroupLoop(Object path) { + return Intl.message( + 'Proxy groups reference each other in a loop: $path', + name: 'overwriteIssueGroupLoop', + desc: '', + args: [path], + ); + } + + /// `{count} items have problems, and applying this override may fail` + String overwriteIssuesSummary(Object count) { + return Intl.message( + '$count items have problems, and applying this override may fail', + name: 'overwriteIssuesSummary', + desc: '', + args: [count], + ); + } + + /// `The profile's own proxy groups name proxies that the custom proxies no longer include: {names}` + String overwriteIssueSubscriptionGroupMissingProxies(Object names) { + return Intl.message( + 'The profile\'s own proxy groups name proxies that the custom proxies no longer include: $names', + name: 'overwriteIssueSubscriptionGroupMissingProxies', + desc: '', + args: [names], + ); + } + + /// `The profile already has a provider named {name}, so the app-level one is not used. Rename it to use it` + String overwriteIssueProviderShadowed(Object name) { + return Intl.message( + 'The profile already has a provider named $name, so the app-level one is not used. Rename it to use it', + name: 'overwriteIssueProviderShadowed', + desc: '', + args: [name], + ); + } + + /// `{label} is still used by the custom proxy groups or rules of {profiles}. Remove it there first` + String providerInUse(Object label, Object profiles) { + return Intl.message( + '$label is still used by the custom proxy groups or rules of $profiles. Remove it there first', + name: 'providerInUse', + desc: '', + args: [label, profiles], + ); + } + + /// `Subscription` + String get providerSourceSubscription { + return Intl.message( + 'Subscription', + name: 'providerSourceSubscription', + desc: '', + args: [], + ); + } + + /// `The subscriptions of {profiles} already have {label}, so those profiles would switch to theirs. Choose another name` + String providerRenameShadowed(Object profiles, Object label) { + return Intl.message( + 'The subscriptions of $profiles already have $label, so those profiles would switch to theirs. Choose another name', + name: 'providerRenameShadowed', + desc: '', + args: [profiles, label], + ); + } + + /// `The app-level one of this name is not used here` + String get appProviderShadowed { + return Intl.message( + 'The app-level one of this name is not used here', + name: 'appProviderShadowed', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/models/common.dart b/lib/models/common.dart index 8e9a869b..eb121686 100644 --- a/lib/models/common.dart +++ b/lib/models/common.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:collection/collection.dart'; import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; +import 'package:fl_clash/icons/glyph.dart'; import 'package:material_ui/material_ui.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -17,7 +18,7 @@ part 'generated/common.g.dart'; @freezed abstract class NavigationItem with _$NavigationItem { const factory NavigationItem({ - required Icon icon, + required Glyph glyph, required PageLabel label, required WidgetBuilder builder, @Default(true) bool keep, @@ -42,9 +43,7 @@ abstract class Package with _$Package { } extension PackagesExt on List { - List getViewList({ - required List pinedList, - required AccessSortType sortType, + Iterable whereVisible({ required bool isFilterSystemApp, required bool isFilterNonInternetApp, }) { @@ -52,9 +51,22 @@ extension PackagesExt on List { (item) => (isFilterSystemApp ? item.system == false : true) && (isFilterNonInternetApp ? item.internet == true : true), + ); + } + + List getViewList({ + required List pinedList, + required AccessSortType sortType, + required bool isFilterSystemApp, + required bool isFilterNonInternetApp, + }) { + final pinned = pinedList.toSet(); + return whereVisible( + isFilterSystemApp: isFilterSystemApp, + isFilterNonInternetApp: isFilterNonInternetApp, ).sorted((a, b) { - final isSelectA = pinedList.contains(a.packageName); - final isSelectB = pinedList.contains(b.packageName); + final isSelectA = pinned.contains(a.packageName); + final isSelectB = pinned.contains(b.packageName); if (isSelectA != isSelectB) { return isSelectA ? -1 : 1; @@ -122,17 +134,6 @@ extension TrackerInfoExt on TrackerInfo { return metadata.destinationIP; } - String get desc { - var text = '${metadata.network}://'; - final ips = [ - metadata.host, - metadata.destinationIP, - ].where((ip) => ip.isNotEmpty); - text += ips.join('/'); - text += ':${metadata.destinationPort}'; - return text; - } - String get progressText { final process = metadata.process; final uid = metadata.uid; @@ -141,6 +142,25 @@ extension TrackerInfoExt on TrackerInfo { } return process.trim(); } + + List get searchFields => [ + metadata.network, + metadata.host, + metadata.destinationIP, + metadata.destinationPort, + metadata.sourceIP, + metadata.sourcePort, + metadata.process, + metadata.processPath, + metadata.remoteDestination, + metadata.destinationIPASN, + ...metadata.destinationGeoIP, + metadata.specialProxy, + metadata.specialRules, + rule, + rulePayload, + ...chains, + ]; } String _logDateTime(dynamic _) { @@ -172,15 +192,26 @@ abstract class LogsState with _$LogsState { }) = _LogsState; } +final _logSearchTexts = Expando(); + extension LogsStateExt on LogsState { + bool get isSearching => keywords.isNotEmpty || SearchQuery(query).isNotEmpty; + List get list { - final lowQuery = query.toLowerCase(); - return logs.where((log) { - final logLevelName = log.logLevel.name; - return {logLevelName}.containsAll(keywords) && - ((log.payload.toLowerCase().contains(lowQuery)) || - logLevelName.contains(lowQuery)); - }).toList(); + final searchQuery = SearchQuery(query); + if (keywords.isEmpty && searchQuery.isEmpty) { + return logs; + } + return logs + .where( + (log) => keywords.every((keyword) => keyword == log.logLevel.name), + ) + .whereMatches( + searchQuery, + (log) => [log.payload, log.logLevel.name], + texts: _logSearchTexts, + ) + .toList(); } } @@ -194,26 +225,101 @@ abstract class TrackerInfosState with _$TrackerInfosState { }) = _TrackerInfosState; } +final _trackerInfoSearchTexts = Expando(); + extension TrackerInfosStateExt on TrackerInfosState { + bool get isSearching => keywords.isNotEmpty || SearchQuery(query).isNotEmpty; + List get list { - final lowerQuery = query.toLowerCase().trim(); - final lowQuery = query.toLowerCase(); - return trackerInfos.where((trackerInfo) { - final chains = trackerInfo.chains; - final process = trackerInfo.metadata.process; - final networkText = trackerInfo.metadata.network.toLowerCase(); - final hostText = trackerInfo.metadata.host.toLowerCase(); - final destinationIPText = trackerInfo.metadata.destinationIP - .toLowerCase(); - final processText = trackerInfo.metadata.process.toLowerCase(); - final chainsText = chains.join('').toLowerCase(); - return {...chains, process}.containsAll(keywords) && - (networkText.contains(lowerQuery) || - hostText.contains(lowerQuery) || - destinationIPText.contains(lowQuery) || - processText.contains(lowerQuery) || - chainsText.contains(lowerQuery)); - }).toList(); + final searchQuery = SearchQuery(query); + if (keywords.isEmpty && searchQuery.isEmpty) { + return trackerInfos; + } + return trackerInfos + .where( + (trackerInfo) => keywords.every( + (keyword) => + keyword == trackerInfo.metadata.process || + trackerInfo.chains.contains(keyword), + ), + ) + .whereMatches( + searchQuery, + (trackerInfo) => trackerInfo.searchFields, + texts: _trackerInfoSearchTexts, + ) + .toList(); + } +} + +@freezed +abstract class DnsQuery with _$DnsQuery { + const factory DnsQuery({ + required String domain, + required String type, + @JsonKey(unknownEnumValue: JsonKey.nullForUndefinedEnumValue) + DnsQueryInitiator? initiator, + @Default('') String upstream, + @Default(false) bool cached, + @Default([]) List answers, + @Default('') String rcode, + @Default('') String error, + @Default(0) int delay, + required DateTime time, + }) = _DnsQuery; + + factory DnsQuery.fromJson(Map json) => + _$DnsQueryFromJson(json); +} + +extension DnsQueryExt on DnsQuery { + bool get hasFailureRcode => rcode.isNotEmpty && rcode != 'NOERROR'; + + bool get isFailed => error.isNotEmpty || hasFailureRcode; + + List get tags => [type, ...resultTags]; + + List get resultTags { + final initiator = this.initiator; + return [ + if (initiator != null) initiator.label, + if (cached) currentAppLocalizations.cache, + if (hasFailureRcode) rcode, + ]; + } + + List get searchFields => [ + domain, + ...tags, + rcode, + upstream, + error, + ...answers, + ]; +} + +@freezed +abstract class DnsQueriesState with _$DnsQueriesState { + const factory DnsQueriesState({ + @Default([]) List dnsQueries, + @Default([]) List keywords, + @Default('') String query, + @Default(true) bool autoScrollToEnd, + }) = _DnsQueriesState; +} + +extension DnsQueriesStateExt on DnsQueriesState { + bool get isSearching => keywords.isNotEmpty || SearchQuery(query).isNotEmpty; + + List get list { + final searchQuery = SearchQuery(query); + if (keywords.isEmpty && searchQuery.isEmpty) { + return dnsQueries; + } + return dnsQueries + .where((dnsQuery) => keywords.every(dnsQuery.tags.contains)) + .whereMatches(searchQuery, (dnsQuery) => dnsQuery.searchFields) + .toList(); } } @@ -343,15 +449,6 @@ extension FileInfoFileExt on File { } } -extension FileInfoExt on FileInfo { - String getDesc(BuildContext context) { - final lastModifiedDesc = - lastModified?.getLastUpdateTimeDesc(context) ?? - context.appLocalizations.unknown; - return '${size.traffic.show} · $lastModifiedDesc'; - } -} - @freezed abstract class VersionInfo with _$VersionInfo { const factory VersionInfo({ @@ -376,10 +473,6 @@ extension TrafficExt on Traffic { return '↑ ${up.traffic.show}/s ↓ ${down.traffic.show}/s'; } - String get desc { - return '${up.traffic.show} ↑ ${down.traffic.show} ↓'; - } - String get trayTitle { return '${up.shortTraffic.show}/s\n${down.shortTraffic.show}/s'; } @@ -483,7 +576,7 @@ abstract class IpInfo with _$IpInfo { }; } - static IpInfo fromIpApiCoJson(Map json) { + static IpInfo fromGeoJsJson(Map json) { return switch (json) { {'ip': final String ip, 'country_code': final String countryCode} => IpInfo(ip: ip, countryCode: countryCode), @@ -507,9 +600,9 @@ abstract class IpInfo with _$IpInfo { }; } - static IpInfo fromMyIpJson(Map json) { + static IpInfo fromCountryIsJson(Map json) { return switch (json) { - {'ip': final String ip, 'cc': final String countryCode} => IpInfo( + {'ip': final String ip, 'country': final String countryCode} => IpInfo( ip: ip, countryCode: countryCode, ), @@ -534,6 +627,34 @@ abstract class IpInfo with _$IpInfo { _ => throw const FormatException('invalid json'), }; } + + static IpInfo fromIpQueryJson(Map json) { + return switch (json) { + { + 'ip': final String ip, + 'location': {'country_code': final String countryCode}, + } => + IpInfo(ip: ip, countryCode: countryCode), + _ => throw const FormatException('invalid json'), + }; + } + + static IpInfo fromCloudflareTrace(String body) { + final fields = {}; + for (final line in const LineSplitter().convert(body)) { + final separator = line.indexOf('='); + if (separator > 0) { + fields[line.substring(0, separator)] = line.substring(separator + 1); + } + } + return switch (fields) { + {'ip': final ip, 'loc': final countryCode} => IpInfo( + ip: ip, + countryCode: countryCode, + ), + _ => throw const FormatException('invalid trace'), + }; + } } @freezed @@ -594,15 +715,18 @@ abstract class Script with _$Script { required int id, required String label, required DateTime lastUpdateTime, + String? url, + int? order, }) = _Script; factory Script.fromJson(Map json) => _$ScriptFromJson(json); - factory Script.create({required String label}) { + factory Script.create({required String label, String? url}) { return Script( id: snowflake.id, label: label, lastUpdateTime: DateTime.now(), + url: url, ); } } @@ -618,20 +742,28 @@ extension ScriptsExt on List