Compare commits

...

41 Commits
0.7.1 ... 0.7.7

Author SHA1 Message Date
Kirill Sobakin
dd5ddd1a14 Merge pull request #240 from itdoginfo/fix/long-nft-command
Import large subnet lists in chunks into nft sets
2025-10-30 16:01:14 +03:00
Andrey Petelin
cc947f9734 fix: import large subnet lists in chunks into nft sets 2025-10-30 14:07:12 +05:00
Kirill Sobakin
f8510cd828 Merge pull request #239 from itdoginfo/fix/crlf-clean
BUG: Clearing CRLF from SRS files
2025-10-29 21:15:47 +03:00
Andrey Petelin
23cbe7be4a fix: include filename in log and remove temp file on CRLF-to-LF conversion 2025-10-29 22:11:29 +05:00
Andrey Petelin
f168fb7e31 refactor: fetch remote JSON to temp files and parse ip_cidr into subnets; remove download_to_stream 2025-10-29 21:52:44 +05:00
Andrey Petelin
fe84b3154f fix: convert Windows CRLF line endings to LF for downloaded files 2025-10-29 21:36:46 +05:00
Kirill Sobakin
d09fdc0b95 Merge pull request #235 from itdoginfo/feat/urltest
feat/urltest
2025-10-27 16:07:13 +03:00
divocat
835cd85970 feat: increase timeouts for delays 2s->5s & 5s -> 10s 2025-10-27 14:56:10 +02:00
divocat
8a3b41ec9c Update fe-app-podkop/locales/podkop.ru.po
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-27 14:18:36 +02:00
divocat
10d7617739 fix: run linter 2025-10-27 14:15:19 +02:00
divocat
68010ed5f7 Update luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-27 14:13:31 +02:00
divocat
557e3666eb Update luci-app-podkop/po/ru/podkop.po
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-27 14:13:20 +02:00
Andrey Petelin
01bff8ccfb chore: refine Russian translations for 'URLTest Testing URL' and 'URLTest Tolerance' 2025-10-27 16:21:51 +05:00
divocat
675a6af89c feat: simplify sb check displaying 2025-10-27 13:16:18 +02:00
divocat
f1a6ff3469 feat: add validations & translations 2025-10-27 13:06:33 +02:00
Andrey Petelin
d4b3377d68 feat: add URLTest check interval, tolerance and testing URL options and wire them into outbound config generation 2025-10-27 15:17:20 +05:00
Kirill Sobakin
d2ef640d76 Merge pull request #233 from itdoginfo/feat/add_display_name
feat: replace outbound code with display name
2025-10-27 12:08:04 +03:00
divocat
47457f2c27 feat: replace outbound code with display name 2025-10-26 16:07:28 +02:00
Kirill Sobakin
8a29e176f2 Merge pull request #232 from itdoginfo/fix/change_json_outbound_validation
small pack of fixes
2025-10-26 16:07:47 +03:00
divocat
9653310208 fix: update locales && possible fix of incorrect outdated 2025-10-26 14:58:09 +02:00
divocat
3540610c78 fix: potential fix of structuredClone for old browsers 2025-10-26 14:52:08 +02:00
divocat
fb54d62a7f feat: actualize json outbound validation 2025-10-26 14:46:39 +02:00
Kirill Sobakin
288b8d4cc2 Merge pull request #230 from itdoginfo/feat/diagnostic-outbound-check
Add outbound check to diagnostic
2025-10-26 09:27:09 +03:00
divocat
e014396ae2 feat: extend selector checks displaying 2025-10-26 01:37:17 +03:00
divocat
694e4ca35a fix: remove extra console log 2025-10-26 01:10:33 +03:00
divocat
788c539e16 feat: add outbounds checks to diagnostics 2025-10-26 01:09:24 +03:00
Kirill Sobakin
743cba8936 Merge pull request #229 from itdoginfo/fix/show-config
Fix masked config
2025-10-25 17:38:45 +03:00
Andrey Petelin
d1d703764c fix: mask outbound_json block and DNS/domain_resolver addresses in podkop config output 2025-10-25 19:27:01 +05:00
Kirill Sobakin
2efd415305 Merge pull request #226 from itdoginfo/fix/excluded_ips
Routing Excluded IPs
2025-10-24 15:34:57 +03:00
Andrey Petelin
407b19b3ed fix: read routing_excluded_ips as non-boolean string with config_get instead of config_get_bool 2025-10-24 17:32:35 +05:00
Kirill Sobakin
c3fac995d5 Merge pull request #224 from itdoginfo/feat/fe-improvements
Some FE improvements
2025-10-23 21:12:03 +03:00
divocat
21ecfbbeca fix: correct types on ru translations 2025-10-23 20:43:46 +03:00
divocat
2918487845 feat: add custom port support to dns 2025-10-23 20:33:18 +03:00
divocat
ac258c53c0 fix: alert displaying 2025-10-23 20:05:55 +03:00
divocat
9a389c47bf fix: actualize locales 2025-10-23 20:02:49 +03:00
divocat
7cd70468c5 feat: add wiki disclaimer to diagnostics 2025-10-23 20:00:55 +03:00
divocat
13d27dab21 feat: add toast when shell exec failed 2025-10-23 19:08:27 +03:00
divocat
9f8f032dce feat: increase shell timeout to 15s 2025-10-23 19:01:06 +03:00
divocat
8301f4c271 feat: update checks displaying 2025-10-23 18:59:23 +03:00
divocat
c4078c8242 feat: update some translations 2025-10-23 18:35:34 +03:00
Kirill Sobakin
e0d149f03a fix 2025-10-23 16:39:41 +03:00
39 changed files with 1907 additions and 1108 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-21 20:02+0300\n"
"PO-Revision-Date: 2025-10-21 20:02+0300\n"
"POT-Creation-Date: 2025-10-27 11:15+0200\n"
"PO-Revision-Date: 2025-10-27 11:15+0200\n"
"Last-Translator: divocat <divocatt@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -36,23 +36,27 @@ msgstr ""
msgid "Active Connections"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:117
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:106
msgid "Additional marking rules found"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
msgid "Applicable for SOCKS and Shadowsocks proxy"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:356
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:420
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:501
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:43
msgid "Available actions"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:65
msgid "Bootsrap DNS"
msgstr ""
@@ -60,48 +64,47 @@ msgstr ""
msgid "Bootstrap DNS server"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:58
msgid "Browser is not using FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:80
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57
msgid "Browser is using FakeIP correctly"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:322
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
msgid "Cache File Path"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
msgid "Cache file path cannot be empty"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:26
msgid "Cannot receive DNS checks result"
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
msgid "Cannot receive checks result"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:27
msgid "Cannot receive nftables checks result"
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
msgid "Checking, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:24
msgid "Cannot receive Sing-box checks result"
#: src/podkop/tabs/diagnostic/helpers/getCheckTitle.ts:2
msgid "checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:14
msgid "Checking dns, please wait"
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:26
msgid "Checks failed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:14
msgid "Checking FakeIP, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:12
msgid "Checking nftables, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:12
msgid "Checking sing-box, please wait"
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:13
msgid "Checks passed"
msgstr ""
#: src/validators/validateSubnet.ts:33
@@ -112,11 +115,11 @@ msgstr ""
msgid "Close"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:275
msgid "Community Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:309
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
msgid "Config File Path"
msgstr ""
@@ -152,15 +155,15 @@ msgstr ""
msgid "Dashboard currently unavailable"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:215
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222
msgid "Delay in milliseconds before reloading podkop after interface UP"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:229
msgid "Delay value cannot be empty"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:89
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:82
msgid "DHCP has DNS server"
msgstr ""
@@ -172,42 +175,34 @@ msgstr ""
msgid "Disable autostart"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:239
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
msgid "Disable QUIC"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:240
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:302
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:382
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:366
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:446
msgid "Disabled"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:14
msgid "DNS checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:64
msgid "DNS checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:84
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:77
msgid "DNS on router"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:243
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
msgid "DNS over HTTPS (DoH)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:180
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:244
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
msgid "DNS over TLS (DoT)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:240
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
msgid "DNS Protocol Type"
msgstr ""
@@ -216,7 +211,7 @@ msgstr ""
msgid "DNS Rewrite TTL"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:189
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:253
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
msgid "DNS Server"
msgstr ""
@@ -225,11 +220,15 @@ msgstr ""
msgid "DNS server address cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:26
msgid "Do not panic, everything can be fixed, just..."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:230
msgid "Domain Resolver"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:300
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
msgid "Dont Touch My DHCP!"
msgstr ""
@@ -242,24 +241,21 @@ msgstr ""
msgid "Download"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:262
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
msgid "Download Lists via Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:271
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
msgid "Download Lists via specific proxy section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:263
msgid "Downloading all lists via main Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:272
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
msgid "Downloading all lists via specific Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:303
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:383
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:367
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:447
msgid "Dynamic List"
msgstr ""
@@ -267,11 +263,11 @@ msgstr ""
msgid "Enable autostart"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:231
msgid "Enable built-in DNS resolver for domains handled by this section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:575
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:639
msgid "Enable Mixed Proxy"
msgstr ""
@@ -279,11 +275,11 @@ msgstr ""
msgid "Enable Output Network Interface"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:640
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:230
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:237
msgid "Enable YACD"
msgstr ""
@@ -291,23 +287,39 @@ msgstr ""
msgid "Enter complete outbound configuration in JSON format"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:402
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:376
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:456
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:358
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:114
msgid "Every 1 minute"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:115
msgid "Every 3 minutes"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:113
msgid "Every 30 seconds"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:116
msgid "Every 5 minutes"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
msgid "Exclude NTP"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:359
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
msgstr ""
@@ -315,27 +327,21 @@ msgstr ""
msgid "Failed to copy!"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:29
msgid "FakeIP checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57
msgid "FakeIP checks failed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51
msgid "FakeIP checks partially passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:44
msgid "FakeIP checks passed"
#: src/podkop/tabs/diagnostic/initController.ts:227
#: src/podkop/tabs/diagnostic/initController.ts:231
#: src/podkop/tabs/diagnostic/initController.ts:261
#: src/podkop/tabs/diagnostic/initController.ts:265
#: src/podkop/tabs/diagnostic/initController.ts:299
#: src/podkop/tabs/diagnostic/initController.ts:303
msgid "Failed to execute!"
msgstr ""
#: src/podkop/methods/custom/getDashboardSections.ts:117
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
msgid "Fastest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:614
msgid "Fully Routed IPs"
msgstr ""
@@ -343,7 +349,7 @@ msgstr ""
msgid "Get global check"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:218
#: src/podkop/tabs/diagnostic/initController.ts:222
msgid "Global check"
msgstr ""
@@ -351,19 +357,19 @@ msgstr ""
msgid "HTTP error"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:182
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:189
msgid "Interface Monitoring"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:214
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:221
msgid "Interface Monitoring Delay"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:183
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:190
msgid "Interface monitoring for Bad WAN"
msgstr ""
#: src/validators/validateDns.ts:20
#: src/validators/validateDns.ts:23
msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH"
msgstr ""
@@ -380,7 +386,7 @@ msgstr ""
msgid "Invalid IP address"
msgstr ""
#: src/validators/validateOutboundJson.ts:19
#: src/validators/validateOutboundJson.ts:9
msgid "Invalid JSON format"
msgstr ""
@@ -476,11 +482,12 @@ msgstr ""
msgid "Invalid Trojan URL: parsing failed"
msgstr ""
#: src/validators/validateUrl.ts:18
#: src/validators/validateUrl.ts:8
#: src/validators/validateUrl.ts:31
msgid "Invalid URL format"
msgstr ""
#: src/validators/validateVlessUrl.ts:109
#: src/validators/validateVlessUrl.ts:110
msgid "Invalid VLESS URL: parsing failed"
msgstr ""
@@ -488,23 +495,27 @@ msgstr ""
msgid "IP address 0.0.0.0 is not allowed"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:404
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:20
msgid "Issues detected"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:453
msgid "Latest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:250
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
msgid "List Update Frequency"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:522
msgid "Local Domain Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:545
msgid "Local Subnet Lists"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:79
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
msgid "Main DNS"
msgstr ""
@@ -512,31 +523,23 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:586
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:650
msgid "Mixed Proxy Port"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:191
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:198
msgid "Monitored Interfaces"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:140
msgid "Must be a number in the range of 50 - 1000"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:184
msgid "Network Interface"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:24
msgid "Nftables checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:75
msgid "Nftables checks partially passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74
msgid "Nftables checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:116
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105
msgid "No other marking rules found"
msgstr ""
@@ -544,10 +547,17 @@ msgstr ""
msgid "Not implement yet"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:75
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:100
msgid "Not responding"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87
msgid "Not running"
msgstr ""
@@ -563,11 +573,7 @@ msgstr ""
msgid "Outbound Configuration"
msgstr ""
#: src/validators/validateOutboundJson.ts:11
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:394
#: src/podkop/tabs/diagnostic/initController.ts:443
msgid "Outdated"
msgstr ""
@@ -579,18 +585,26 @@ msgstr ""
msgid "Path cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:340
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
msgid "Path must be absolute (start with /)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
msgid "Path must contain at least one directory (like /tmp/cache.db)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:344
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
msgid "Path must end with cache.db"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135
msgid "Pending"
msgstr ""
#: src/podkop/tabs/dashboard/initController.ts:340
msgid "Podkop"
msgstr ""
@@ -599,7 +613,7 @@ msgstr ""
msgid "Podkop Settings"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:301
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
msgid "Podkop will not modify your DHCP configuration"
msgstr ""
@@ -607,30 +621,23 @@ msgstr ""
msgid "Proxy Configuration URL"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:89
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:66
msgid "Proxy traffic is not routed via FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:88
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:65
msgid "Proxy traffic is routed via FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
msgid "Queued"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:309
msgid "Regional options cannot be used together"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:568
msgid "Remote Domain Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:591
msgid "Remote Subnet Lists"
msgstr ""
@@ -638,39 +645,39 @@ msgstr ""
msgid "Restart podkop"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:74
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51
msgid "Router DNS is not routed through sing-box"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:73
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:50
msgid "Router DNS is routed through sing-box"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:369
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
msgid "Routing Excluded IPs"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:90
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:79
msgid "Rules mangle counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:85
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74
msgid "Rules mangle exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:100
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:89
msgid "Rules mangle output counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:95
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:84
msgid "Rules mangle output exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:110
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:99
msgid "Rules proxy counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:94
msgid "Rules proxy exist"
msgstr ""
@@ -678,7 +685,7 @@ msgstr ""
msgid "Run Diagnostic"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:328
msgid "Russia inside restrictions"
msgstr ""
@@ -686,7 +693,7 @@ msgstr ""
msgid "Sections"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:276
msgid "Select a predefined list for routing"
msgstr ""
@@ -698,7 +705,7 @@ msgstr ""
msgid "Select DNS protocol to use"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:251
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
msgid "Select how often the domain or subnet lists are updated automatically"
msgstr ""
@@ -706,32 +713,32 @@ msgstr ""
msgid "Select how to configure the proxy"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:185
msgid "Select network interface for VPN connection"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:254
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
msgid "Select or enter DNS server address"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:323
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:310
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:241
msgid "Select the DNS protocol type for the domain resolver"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:364
msgid "Select the list type for adding custom domains"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:444
msgid "Select the list type for adding custom subnets"
msgstr ""
@@ -743,7 +750,7 @@ msgstr ""
msgid "Select the network interface to which the traffic will originate"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:192
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:199
msgid "Select the WAN interfaces to be monitored"
msgstr ""
@@ -755,7 +762,7 @@ msgstr ""
msgid "Settings"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:278
#: src/podkop/tabs/diagnostic/initController.ts:290
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
msgid "Show sing-box config"
msgstr ""
@@ -764,60 +771,52 @@ msgstr ""
msgid "Sing-box"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:86
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:77
msgid "Sing-box autostart disabled"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:19
msgid "Sing-box checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:66
msgid "Sing-box checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:71
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:62
msgid "Sing-box installed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:96
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:87
msgid "Sing-box listening ports"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:91
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:82
msgid "Sing-box process running"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:72
msgid "Sing-box service exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:76
msgid "Sing-box version >= 1.12.4"
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
msgid "Sing-box version is compatible (newer than 1.12.4)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
msgid "Source Network Interface"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
msgid "Specify a local IP address to be excluded from routing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:615
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:569
msgid "Specify remote URLs to download and use domain lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:592
msgid "Specify remote URLs to download and use subnet lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:459
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:482
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:523
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:546
msgid "Specify the path to the list file located on the router filesystem"
msgstr ""
@@ -837,7 +836,11 @@ msgstr ""
msgid "System info"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:80
#: src/podkop/tabs/diagnostic/partials/renderSystemInfo.ts:21
msgid "System information"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:69
msgid "Table exist"
msgstr ""
@@ -845,11 +848,11 @@ msgstr ""
msgid "Test latency"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:368
msgid "Text List"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:448
msgid "Text List (comma/space/newline separated)"
msgstr ""
@@ -857,6 +860,18 @@ msgstr ""
msgid "The DNS server used to look up the IP address of an upstream DNS server"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
msgid "The interval between connectivity tests"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:124
msgid "The maximum difference in response times (ms) allowed when comparing servers"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:147
msgid "The URL used to test server connectivity"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
msgid "Time in seconds for DNS record caching (default: 60)"
msgstr ""
@@ -869,6 +884,10 @@ msgstr ""
msgid "Traffic Total"
msgstr ""
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:25
msgid "Troubleshooting"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:80
msgid "TTL must be a positive number"
msgstr ""
@@ -877,22 +896,22 @@ msgstr ""
msgid "TTL value cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
msgid "UDP (Unprotected DNS)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:174
msgid "UDP over TCP"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:34
#: src/podkop/tabs/diagnostic/initController.ts:35
#: src/podkop/tabs/diagnostic/initController.ts:36
#: src/podkop/tabs/diagnostic/initController.ts:37
#: src/podkop/tabs/diagnostic/initController.ts:38
#: src/podkop/tabs/diagnostic/initController.ts:39
#: src/podkop/tabs/diagnostic/initController.ts:373
#: src/podkop/tabs/diagnostic/initController.ts:40
#: src/podkop/tabs/diagnostic/initController.ts:41
#: src/podkop/tabs/diagnostic/initController.ts:42
#: src/podkop/tabs/diagnostic/initController.ts:43
#: src/podkop/tabs/diagnostic/initController.ts:417
msgid "unknown"
msgstr ""
@@ -905,11 +924,11 @@ msgstr ""
msgid "Uplink"
msgstr ""
#: src/validators/validateProxyUrl.ts:27
#: src/validators/validateProxyUrl.ts:29
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
msgstr ""
#: src/validators/validateUrl.ts:13
#: src/validators/validateUrl.ts:17
msgid "URL must use one of the following protocols:"
msgstr ""
@@ -917,65 +936,81 @@ msgstr ""
msgid "URLTest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
msgid "URLTest Check Interval"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:87
msgid "URLTest Proxy Links"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:146
msgid "URLTest Testing URL"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:123
msgid "URLTest Tolerance"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:363
msgid "User Domain List Type"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:375
msgid "User Domains"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:337
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:401
msgid "User Domains List"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:443
msgid "User Subnet List Type"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:455
msgid "User Subnets"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:417
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
msgid "User Subnets List"
msgstr ""
#: src/validators/validateDns.ts:11
#: src/validators/validateDns.ts:15
#: src/validators/validateDns.ts:14
#: src/validators/validateDns.ts:18
#: src/validators/validateDomain.ts:13
#: src/validators/validateDomain.ts:30
#: src/validators/validateIp.ts:8
#: src/validators/validateOutboundJson.ts:17
#: src/validators/validateOutboundJson.ts:7
#: src/validators/validatePath.ts:16
#: src/validators/validateShadowsocksUrl.ts:95
#: src/validators/validateSocksUrl.ts:80
#: src/validators/validateSubnet.ts:38
#: src/validators/validateTrojanUrl.ts:59
#: src/validators/validateUrl.ts:16
#: src/validators/validateVlessUrl.ts:107
#: src/validators/validateUrl.ts:28
#: src/validators/validateVlessUrl.ts:108
msgid "Valid"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:370
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:449
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:434
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:513
msgid "Validation errors:"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:248
#: src/podkop/tabs/diagnostic/initController.ts:256
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
msgid "View logs"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:31
msgid "Visit Wiki"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:330
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
msgstr ""

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-21 23:02+0300\n"
"PO-Revision-Date: 2025-10-21 23:02+0300\n"
"POT-Creation-Date: 2025-10-27 13:15+0200\n"
"PO-Revision-Date: 2025-10-27 13:15+0200\n"
"Last-Translator: divocat\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -44,6 +44,9 @@ msgstr "Необходимо указать хотя бы один действ
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
msgstr "Необходимо указать хотя бы одну действительную подсеть или IP. Только комментарии недопустимы."
msgid "Available actions"
msgstr "Доступные действия"
msgid "Bootsrap DNS"
msgstr "Bootstrap DNS"
@@ -62,26 +65,20 @@ msgstr "Путь к файлу кэша"
msgid "Cache file path cannot be empty"
msgstr "Путь к файлу кэша не может быть пустым"
msgid "Cannot receive DNS checks result"
msgstr "Не удалось получить результаты проверки DNS"
msgid "Cannot receive checks result"
msgstr "Не удалось получить результаты проверки"
msgid "Cannot receive nftables checks result"
msgstr "Не удалось получить результаты проверки nftables"
msgid "Checking, please wait"
msgstr "Проверяем, пожалуйста подождите"
msgid "Cannot receive Sing-box checks result"
msgstr "Не удалось получить результаты проверки Sing-box"
msgid "checks"
msgstr "проверки"
msgid "Checking dns, please wait"
msgstr "Проверка dns, пожалуйста подождите"
msgid "Checks failed"
msgstr "Проверки не выполнены"
msgid "Checking FakeIP, please wait"
msgstr "Проверка FakeIP, пожалуйста подождите"
msgid "Checking nftables, please wait"
msgstr "Проверка nftables, пожалуйста подождите"
msgid "Checking sing-box, please wait"
msgstr "Проверка sing-box, пожалуйста подождите"
msgid "Checks passed"
msgstr "Проверки пройдены"
msgid "CIDR must be between 0 and 32"
msgstr "CIDR должен быть между 0 и 32"
@@ -143,12 +140,6 @@ msgstr "Отключить QUIC протокол для улучшения со
msgid "Disabled"
msgstr "Отключено"
msgid "DNS checks"
msgstr "DNS проверки"
msgid "DNS checks passed"
msgstr "DNS проверки успешно завершены"
msgid "DNS on router"
msgstr "DNS на роутере"
@@ -170,6 +161,9 @@ msgstr "DNS-сервер"
msgid "DNS server address cannot be empty"
msgstr "Адрес DNS-сервера не может быть пустым"
msgid "Do not panic, everything can be fixed, just..."
msgstr "Не паникуйте, всё можно исправить, просто..."
msgid "Domain Resolver"
msgstr "Резолвер доменов"
@@ -188,9 +182,6 @@ msgstr "Скачивать списки через Proxy/VPN"
msgid "Download Lists via specific proxy section"
msgstr "Скачивать списки через выбранную секцию"
msgid "Downloading all lists via main Proxy/VPN"
msgstr "Загрузка всех списков через основной прокси/VPN"
msgid "Downloading all lists via specific Proxy/VPN"
msgstr "Загрузка всех списков через указанный прокси/VPN"
@@ -227,6 +218,18 @@ msgstr "Введите доменные имена без протоколов,
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
msgid "Every 1 minute"
msgstr "Каждую минуту"
msgid "Every 3 minutes"
msgstr "Каждые 3 минуты"
msgid "Every 30 seconds"
msgstr "Каждые 30 секунд"
msgid "Every 5 minutes"
msgstr "Каждые 5 минут"
msgid "Exclude NTP"
msgstr "Исключить NTP"
@@ -236,17 +239,8 @@ msgstr "Исключите трафик протокола NTP из туннел
msgid "Failed to copy!"
msgstr "Не удалось скопировать!"
msgid "FakeIP checks"
msgstr "Проверка FakeIP"
msgid "FakeIP checks failed"
msgstr "Проверки FakeIP не пройдены"
msgid "FakeIP checks partially passed"
msgstr "Проверка FakeIP частично пройдена"
msgid "FakeIP checks passed"
msgstr "Проверки FakeIP пройдены"
msgid "Failed to execute!"
msgstr "Не удалось выполнить!"
msgid "Fastest"
msgstr "Самый быстрый"
@@ -365,6 +359,9 @@ msgstr "Неверный URL VLESS: ошибка разбора"
msgid "IP address 0.0.0.0 is not allowed"
msgstr "IP-адрес 0.0.0.0 не допускается"
msgid "Issues detected"
msgstr "Обнаружены проблемы"
msgid "Latest"
msgstr "Последняя"
@@ -389,24 +386,21 @@ msgstr "Порт смешанного прокси"
msgid "Monitored Interfaces"
msgstr "Наблюдаемые интерфейсы"
msgid "Must be a number in the range of 50 - 1000"
msgstr "Должно быть числом от 50 до 1000"
msgid "Network Interface"
msgstr "Сетевой интерфейс"
msgid "Nftables checks"
msgstr "Проверки Nftables"
msgid "Nftables checks partially passed"
msgstr "Проверки Nftables частично пройдена"
msgid "Nftables checks passed"
msgstr "Nftables проверки успешно завершены"
msgid "No other marking rules found"
msgstr "Другие правила маркировки не найдены"
msgid "Not implement yet"
msgstr "Ещё не реализовано"
msgid "Not responding"
msgstr "Не отвечает"
msgid "Not running"
msgstr "Не запущено"
@@ -419,9 +413,6 @@ msgstr "Конфигурация Outbound"
msgid "Outbound Configuration"
msgstr "Конфигурация исходящего соединения"
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
msgid "Outdated"
msgstr "Устаревшая"
@@ -440,6 +431,9 @@ msgstr "Путь должен содержать хотя бы одну дире
msgid "Path must end with cache.db"
msgstr "Путь должен заканчиваться на cache.db"
msgid "Pending"
msgstr "Ожидает запуска"
msgid "Podkop"
msgstr "Podkop"
@@ -458,17 +452,14 @@ msgstr "Прокси-трафик не маршрутизируется чере
msgid "Proxy traffic is routed via FakeIP"
msgstr "Прокси-трафик направляется через FakeIP"
msgid "Queued"
msgstr "В очереди"
msgid "Regional options cannot be used together"
msgstr "Нельзя использовать несколько региональных опций одновременно"
msgid "Remote Domain Lists"
msgstr "Удалённые списки доменов"
msgstr "Внешние списки доменов"
msgid "Remote Subnet Lists"
msgstr "Удалённые списки подсетей"
msgstr "Внешние списки подсетей"
msgid "Restart podkop"
msgstr "Перезапустить Podkop"
@@ -569,12 +560,6 @@ msgstr "Sing-box"
msgid "Sing-box autostart disabled"
msgstr "Автостарт sing-box отключен"
msgid "Sing-box checks"
msgstr "Sing-box проверки"
msgid "Sing-box checks passed"
msgstr "Sing-box проверки успешно завершены"
msgid "Sing-box installed"
msgstr "Sing-box установлен"
@@ -587,8 +572,8 @@ msgstr "Процесс sing-box запущен"
msgid "Sing-box service exist"
msgstr "Сервис sing-box существует"
msgid "Sing-box version >= 1.12.4"
msgstr "Версия sing-box >= 1.12.4"
msgid "Sing-box version is compatible (newer than 1.12.4)"
msgstr "Версия Sing-box совместима (новее 1.12.4)"
msgid "Source Network Interface"
msgstr "Сетевой интерфейс источника"
@@ -600,10 +585,10 @@ msgid "Specify local IP addresses or subnets whose traffic will always be routed
msgstr "Укажите локальные IP-адреса или подсети, трафик которых всегда будет направляться через настроенный маршрут."
msgid "Specify remote URLs to download and use domain lists"
msgstr "Укажите удаленные URL-адреса для загрузки и использования списков доменов."
msgstr "Укажите URL-адреса для загрузки и использования списков доменов."
msgid "Specify remote URLs to download and use subnet lists"
msgstr "Укажите удаленные URL-адреса для загрузки и использования списков подсетей."
msgstr "Укажите URL-адреса для загрузки и использования списков подсетей."
msgid "Specify the path to the list file located on the router filesystem"
msgstr "Укажите путь к файлу списка, расположенному в файловой системе маршрутизатора."
@@ -620,11 +605,14 @@ msgstr "Успешно скопировано!"
msgid "System info"
msgstr "Системная информация"
msgid "System information"
msgstr "Системная информация"
msgid "Table exist"
msgstr "Таблица существует"
msgid "Test latency"
msgstr "Измерить задержки"
msgstr "Тестирование задержки"
msgid "Text List"
msgstr "Текстовый список"
@@ -635,6 +623,15 @@ msgstr "Текстовый список (через запятую, пробел
msgid "The DNS server used to look up the IP address of an upstream DNS server"
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
msgid "The interval between connectivity tests"
msgstr "Интервал между тестами подключения"
msgid "The maximum difference in response times (ms) allowed when comparing servers"
msgstr "Максимально допустимая разница во времени отклика (мс) при сравнении серверов"
msgid "The URL used to test server connectivity"
msgstr "URL-адрес, используемый для проверки подключения к серверу"
msgid "Time in seconds for DNS record caching (default: 60)"
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
@@ -644,6 +641,9 @@ msgstr "Трафик"
msgid "Traffic Total"
msgstr "Всего трафика"
msgid "Troubleshooting"
msgstr "Устранение неполадок"
msgid "TTL must be a positive number"
msgstr "TTL должно быть положительным числом"
@@ -674,9 +674,18 @@ msgstr "URL должен использовать один из следующи
msgid "URLTest"
msgstr "URLTest"
msgid "URLTest Check Interval"
msgstr "Интервал проверки URLTest"
msgid "URLTest Proxy Links"
msgstr "Ссылки прокси для URLTest"
msgid "URLTest Testing URL"
msgstr "URLTest ссылка для проверки"
msgid "URLTest Tolerance"
msgstr "URLTest допустимое отклонение"
msgid "User Domain List Type"
msgstr "Тип пользовательского списка доменов"
@@ -704,6 +713,9 @@ msgstr "Ошибки валидации:"
msgid "View logs"
msgstr "Посмотреть логи"
msgid "Visit Wiki"
msgstr "Перейти в wiki"
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."

View File

@@ -15,3 +15,4 @@ export * from './renderCircleCheckBigIcon24';
export * from './renderSquareChartGanttIcon24';
export * from './renderCogIcon24';
export * from './renderSearchIcon24';
export * from './renderBookOpenTextIcon24';

View File

@@ -0,0 +1,28 @@
import { svgEl } from '../helpers';
export function renderBookOpenTextIcon24() {
const NS = 'http://www.w3.org/2000/svg';
return svgEl(
'svg',
{
xmlns: NS,
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
'stroke-width': '2',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
class: 'lucide lucide-book-open-text-icon lucide-book-open-text',
},
[
svgEl('path', { d: 'M12 7v14' }),
svgEl('path', { d: 'M16 12h2' }),
svgEl('path', { d: 'M16 8h2' }),
svgEl('path', {
d: 'M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z',
}),
svgEl('path', { d: 'M6 12h2' }),
svgEl('path', { d: 'M6 8h2' }),
],
);
}

View File

@@ -4,6 +4,9 @@
'require uci';
'require ui';
if (typeof structuredClone !== 'function')
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
export * from './validators';
export * from './helpers';
export * from './podkop';

View File

@@ -9,7 +9,7 @@ export async function callBaseMethod<T>(
const response = await executeShellCommand({
command,
args: [method as string, ...args],
timeout: 10000,
timeout: 15000,
});
if (response.stdout) {

View File

@@ -29,15 +29,15 @@ export const PodkopShellMethods = {
Podkop.AvailableClashAPIMethods.GET_PROXIES,
]),
getClashApiProxyLatency: async (tag: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY,
tag,
]),
callBaseMethod<Podkop.GetClashApiProxyLatency>(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, '5000'],
),
getClashApiGroupLatency: async (tag: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY,
tag,
]),
callBaseMethod<Podkop.GetClashApiGroupLatency>(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, '10000'],
),
setClashApiGroupProxy: async (group: string, proxy: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,

View File

@@ -1,8 +1,11 @@
import { getCheckTitle } from '../helpers/getCheckTitle';
export enum DIAGNOSTICS_CHECKS {
DNS = 'DNS',
SINGBOX = 'SINGBOX',
NFT = 'NFT',
FAKEIP = 'FAKEIP',
OUTBOUNDS = 'OUTBOUNDS',
}
export const DIAGNOSTICS_CHECKS_MAP: Record<
@@ -11,22 +14,27 @@ export const DIAGNOSTICS_CHECKS_MAP: Record<
> = {
[DIAGNOSTICS_CHECKS.DNS]: {
order: 1,
title: _('DNS checks'),
title: getCheckTitle('DNS'),
code: DIAGNOSTICS_CHECKS.DNS,
},
[DIAGNOSTICS_CHECKS.SINGBOX]: {
order: 2,
title: _('Sing-box checks'),
title: getCheckTitle('Sing-box'),
code: DIAGNOSTICS_CHECKS.SINGBOX,
},
[DIAGNOSTICS_CHECKS.NFT]: {
order: 3,
title: _('Nftables checks'),
title: getCheckTitle('Nftables'),
code: DIAGNOSTICS_CHECKS.NFT,
},
[DIAGNOSTICS_CHECKS.FAKEIP]: {
[DIAGNOSTICS_CHECKS.OUTBOUNDS]: {
order: 4,
title: _('FakeIP checks'),
title: getCheckTitle('Outbounds'),
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
},
[DIAGNOSTICS_CHECKS.FAKEIP]: {
order: 5,
title: getCheckTitle('FakeIP'),
code: DIAGNOSTICS_CHECKS.FAKEIP,
},
};

View File

@@ -3,6 +3,7 @@ import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods } from '../../../methods';
import { IDiagnosticsChecksItem } from '../../../services';
import { updateCheckStore } from './updateCheckStore';
import { getMeta } from '../helpers/getMeta';
export async function runDnsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS;
@@ -11,7 +12,7 @@ export async function runDnsCheck() {
order,
code,
title,
description: _('Checking dns, please wait'),
description: _('Checking, please wait'),
state: 'loading',
items: [],
});
@@ -23,7 +24,7 @@ export async function runDnsCheck() {
order,
code,
title,
description: _('Cannot receive DNS checks result'),
description: _('Cannot receive checks result'),
state: 'error',
items: [],
});
@@ -45,27 +46,19 @@ export async function runDnsCheck() {
Boolean(data.bootstrap_dns_status) ||
Boolean(data.dns_status);
function getStatus() {
if (allGood) {
return 'success';
}
if (atLeastOneGood) {
return 'warning';
}
return 'error';
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: _('DNS checks passed'),
state: getStatus(),
description,
state,
items: [
...insertIf<IDiagnosticsChecksItem>(
data.dns_type === 'doh' || data.dns_type === 'dot',
data.dns_type === 'doh' ||
data.dns_type === 'dot' ||
!data.bootstrap_dns_status,
[
{
state: data.bootstrap_dns_status ? 'success' : 'error',

View File

@@ -3,6 +3,7 @@ import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods, RemoteFakeIPMethods } from '../../../methods';
import { IDiagnosticsChecksItem } from '../../../services';
import { updateCheckStore } from './updateCheckStore';
import { getMeta } from '../helpers/getMeta';
export async function runFakeIPCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.FAKEIP;
@@ -11,7 +12,7 @@ export async function runFakeIPCheck() {
order,
code,
title,
description: _('Checking FakeIP, please wait'),
description: _('Checking, please wait'),
state: 'loading',
items: [],
});
@@ -34,31 +35,7 @@ export async function runFakeIPCheck() {
const atLeastOneGood =
checks.router && checks.browserFakeIP && checks.differentIP;
function getMeta(): {
description: string;
state: 'loading' | 'warning' | 'success' | 'error' | 'skipped';
} {
if (allGood) {
return {
state: 'success',
description: _('FakeIP checks passed'),
};
}
if (atLeastOneGood) {
return {
state: 'warning',
description: _('FakeIP checks partially passed'),
};
}
return {
state: 'error',
description: _('FakeIP checks failed'),
};
}
const { state, description } = getMeta();
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,

View File

@@ -1,6 +1,7 @@
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { RemoteFakeIPMethods, PodkopShellMethods } from '../../../methods';
import { updateCheckStore } from './updateCheckStore';
import { getMeta } from '../helpers/getMeta';
export async function runNftCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.NFT;
@@ -9,7 +10,7 @@ export async function runNftCheck() {
order,
code,
title,
description: _('Checking nftables, please wait'),
description: _('Checking, please wait'),
state: 'loading',
items: [],
});
@@ -24,7 +25,7 @@ export async function runNftCheck() {
order,
code,
title,
description: _('Cannot receive nftables checks result'),
description: _('Cannot receive checks result'),
state: 'error',
items: [],
});
@@ -54,26 +55,14 @@ export async function runNftCheck() {
Boolean(data.rules_proxy_counters) ||
!data.rules_other_mark_exist;
function getStatus() {
if (allGood) {
return 'success';
}
if (atLeastOneGood) {
return 'warning';
}
return 'error';
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: allGood
? _('Nftables checks passed')
: _('Nftables checks partially passed'),
state: getStatus(),
description,
state,
items: [
{
state: data.table_exist ? 'success' : 'error',

View File

@@ -0,0 +1,132 @@
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods } from '../../../methods';
import { updateCheckStore } from './updateCheckStore';
import { getMeta } from '../helpers/getMeta';
import { getDashboardSections } from '../../../methods/custom/getDashboardSections';
import { IDiagnosticsChecksItem } from '../../../services';
export async function runSectionsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS;
updateCheckStore({
order,
code,
title,
description: _('Checking, please wait'),
state: 'loading',
items: [],
});
const sections = await getDashboardSections();
if (!sections.success) {
updateCheckStore({
order,
code,
title,
description: _('Cannot receive checks result'),
state: 'error',
items: [],
});
throw new Error('Sections checks failed');
}
const items = (await Promise.all(
sections.data.map(async (section) => {
async function getLatency() {
if (section.withTagSelect) {
const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency(
section.code,
);
const selectedOutbound = section.outbounds.find(
(item) => item.selected,
);
const isUrlTest = selectedOutbound?.type === 'URLTest';
const success = latencyGroup.success && !latencyGroup.data.message;
if (success) {
if (isUrlTest) {
const latency = Object.values(latencyGroup.data)
.map((item) => (item ? `${item}ms` : 'n/a'))
.join(' / ');
return {
success: true,
latency: `[${_('Fastest')}] ${latency}`,
};
}
const selectedProxyDelay =
latencyGroup.data?.[selectedOutbound?.code ?? ''];
if (selectedProxyDelay) {
return {
success: true,
latency: `[${selectedOutbound?.displayName ?? ''}] ${selectedProxyDelay}ms`,
};
}
return {
success: false,
latency: `[${selectedOutbound?.displayName ?? ''}] ${_('Not responding')}`,
};
}
return {
success: false,
latency: _('Not responding'),
};
}
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
section.code,
);
const success = latencyProxy.success && !latencyProxy.data.message;
if (success) {
return {
success: true,
latency: `${latencyProxy.data.delay} ms`,
};
}
return {
success: false,
latency: _('Not responding'),
};
}
const { latency, success } = await getLatency();
return {
state: success ? 'success' : 'error',
key: section.displayName,
value: latency,
};
}),
)) as Array<IDiagnosticsChecksItem>;
const allGood = items.every((item) => item.state === 'success');
const atLeastOneGood = items.some((item) => item.state === 'success');
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description,
state,
items,
});
if (!atLeastOneGood) {
throw new Error('Sections checks failed');
}
}

View File

@@ -1,6 +1,7 @@
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods } from '../../../methods';
import { updateCheckStore } from './updateCheckStore';
import { getMeta } from '../helpers/getMeta';
export async function runSingBoxCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.SINGBOX;
@@ -9,7 +10,7 @@ export async function runSingBoxCheck() {
order,
code,
title,
description: _('Checking sing-box, please wait'),
description: _('Checking, please wait'),
state: 'loading',
items: [],
});
@@ -21,7 +22,7 @@ export async function runSingBoxCheck() {
order,
code,
title,
description: _('Cannot receive Sing-box checks result'),
description: _('Cannot receive checks result'),
state: 'error',
items: [],
});
@@ -47,24 +48,14 @@ export async function runSingBoxCheck() {
Boolean(data.sing_box_process_running) ||
Boolean(data.sing_box_ports_listening);
function getStatus() {
if (allGood) {
return 'success';
}
if (atLeastOneGood) {
return 'warning';
}
return 'error';
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: _('Sing-box checks passed'),
state: getStatus(),
description,
state,
items: [
{
state: data.sing_box_installed ? 'success' : 'error',
@@ -73,7 +64,7 @@ export async function runSingBoxCheck() {
},
{
state: data.sing_box_version_ok ? 'success' : 'error',
key: _('Sing-box version >= 1.12.4'),
key: _('Sing-box version is compatible (newer than 1.12.4)'),
value: '',
},
{

View File

@@ -72,6 +72,14 @@ export const initialDiagnosticStore: Pick<
items: [],
state: 'skipped',
},
{
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
description: _('Not running'),
items: [],
state: 'skipped',
},
{
code: DIAGNOSTICS_CHECKS.FAKEIP,
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
@@ -92,7 +100,7 @@ export const loadingDiagnosticsChecksStore: Pick<
code: DIAGNOSTICS_CHECKS.DNS,
title: DIAGNOSTICS_CHECKS_MAP.DNS.title,
order: DIAGNOSTICS_CHECKS_MAP.DNS.order,
description: _('Queued'),
description: _('Pending'),
items: [],
state: 'skipped',
},
@@ -100,7 +108,7 @@ export const loadingDiagnosticsChecksStore: Pick<
code: DIAGNOSTICS_CHECKS.SINGBOX,
title: DIAGNOSTICS_CHECKS_MAP.SINGBOX.title,
order: DIAGNOSTICS_CHECKS_MAP.SINGBOX.order,
description: _('Queued'),
description: _('Pending'),
items: [],
state: 'skipped',
},
@@ -108,7 +116,15 @@ export const loadingDiagnosticsChecksStore: Pick<
code: DIAGNOSTICS_CHECKS.NFT,
title: DIAGNOSTICS_CHECKS_MAP.NFT.title,
order: DIAGNOSTICS_CHECKS_MAP.NFT.order,
description: _('Queued'),
description: _('Pending'),
items: [],
state: 'skipped',
},
{
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
description: _('Pending'),
items: [],
state: 'skipped',
},
@@ -116,7 +132,7 @@ export const loadingDiagnosticsChecksStore: Pick<
code: DIAGNOSTICS_CHECKS.FAKEIP,
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
order: DIAGNOSTICS_CHECKS_MAP.FAKEIP.order,
description: _('Queued'),
description: _('Pending'),
items: [],
state: 'skipped',
},

View File

@@ -0,0 +1,3 @@
export function getCheckTitle(name: string) {
return `${name} ${_('checks')}`;
}

View File

@@ -0,0 +1,28 @@
interface IGetMetaProps {
allGood: boolean;
atLeastOneGood: boolean;
}
export function getMeta({ allGood, atLeastOneGood }: IGetMetaProps): {
description: string;
state: 'loading' | 'warning' | 'success' | 'error' | 'skipped';
} {
if (allGood) {
return {
state: 'success',
description: _('Checks passed'),
};
}
if (atLeastOneGood) {
return {
state: 'warning',
description: _('Issues detected'),
};
}
return {
state: 'error',
description: _('Checks failed'),
};
}

View File

@@ -16,6 +16,10 @@ import { PodkopShellMethods } from '../../methods';
import { fetchServicesInfo } from '../../fetchers';
import { normalizeCompiledVersion } from '../../../helpers/normalizeCompiledVersion';
import { renderModal } from '../../../partials';
import { PODKOP_LUCI_APP_VERSION } from '../../../constants';
import { showToast } from '../../../helpers/showToast';
import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer';
import { runSectionsCheck } from './checks/runSectionsCheck';
async function fetchSystemInfo() {
const systemInfo = await PodkopShellMethods.getSystemInfo();
@@ -218,9 +222,13 @@ async function handleShowGlobalCheck() {
_('Global check'),
renderModal(globalCheck.data as string, 'global_check'),
);
} else {
logger.error('[DIAGNOSTIC]', 'handleShowGlobalCheck - e', globalCheck);
showToast(_('Failed to execute!'), 'error');
}
} catch (e) {
logger.error('[DIAGNOSTIC]', 'handleShowGlobalCheck - e', e);
showToast(_('Failed to execute!'), 'error');
} finally {
store.set({
diagnosticsActions: {
@@ -248,9 +256,13 @@ async function handleViewLogs() {
_('View logs'),
renderModal(viewLogs.data as string, 'view_logs'),
);
} else {
logger.error('[DIAGNOSTIC]', 'handleViewLogs - e', viewLogs);
showToast(_('Failed to execute!'), 'error');
}
} catch (e) {
logger.error('[DIAGNOSTIC]', 'handleViewLogs - e', e);
showToast(_('Failed to execute!'), 'error');
} finally {
store.set({
diagnosticsActions: {
@@ -278,9 +290,17 @@ async function handleShowSingBoxConfig() {
_('Show sing-box config'),
renderModal(showSingBoxConfig.data as string, 'show_sing_box_config'),
);
} else {
logger.error(
'[DIAGNOSTIC]',
'handleShowSingBoxConfig - e',
showSingBoxConfig,
);
showToast(_('Failed to execute!'), 'error');
}
} catch (e) {
logger.error('[DIAGNOSTIC]', 'handleShowSingBoxConfig - e', e);
showToast(_('Failed to execute!'), 'error');
} finally {
store.set({
diagnosticsActions: {
@@ -291,6 +311,30 @@ async function handleShowSingBoxConfig() {
}
}
function renderWikiDisclaimerWidget() {
const diagnosticsChecks = store.get().diagnosticsChecks;
function getWikiKind() {
const allResults = diagnosticsChecks.map((check) => check.state);
if (allResults.includes('error')) {
return 'error';
}
if (allResults.includes('warning')) {
return 'warning';
}
return 'default';
}
const container = document.getElementById('pdk_diagnostic-page-wiki');
return preserveScrollForPage(() => {
container!.replaceChildren(renderWikiDisclaimer(getWikiKind()));
});
}
function renderDiagnosticAvailableActionsWidget() {
const diagnosticsActions = store.get().diagnosticsActions;
const servicesInfoWidget = store.get().servicesInfoWidget;
@@ -371,9 +415,9 @@ function renderDiagnosticSystemInfoWidget() {
function getPodkopVersionRow(): IRenderSystemInfoRow {
const loading = diagnosticsSystemInfo.loading;
const unknown = diagnosticsSystemInfo.podkop_version === _('unknown');
const hasActualVersion = Boolean(
diagnosticsSystemInfo.podkop_latest_version,
);
const hasActualVersion =
Boolean(diagnosticsSystemInfo.podkop_latest_version) &&
diagnosticsSystemInfo.podkop_latest_version !== 'unknown';
const version = normalizeCompiledVersion(
diagnosticsSystemInfo.podkop_version,
);
@@ -387,6 +431,11 @@ function renderDiagnosticSystemInfoWidget() {
}
if (version !== `v${diagnosticsSystemInfo.podkop_latest_version}`) {
logger.debug(
'[DIAGNOSTIC]',
'diagnosticsSystemInfo',
diagnosticsSystemInfo,
);
return {
key: 'Podkop',
value: version,
@@ -412,7 +461,7 @@ function renderDiagnosticSystemInfoWidget() {
getPodkopVersionRow(),
{
key: 'Luci App',
value: normalizeCompiledVersion(diagnosticsSystemInfo.luci_app_version),
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION),
},
{
key: 'Sing-box',
@@ -441,6 +490,7 @@ async function onStoreUpdate(
) {
if (diff.diagnosticsChecks) {
renderDiagnosticsChecks();
renderWikiDisclaimerWidget();
}
if (diff.diagnosticsRunAction) {
@@ -469,6 +519,8 @@ async function runChecks() {
await runNftCheck();
await runSectionsCheck();
await runFakeIPCheck();
} catch (e) {
logger.error('[DIAGNOSTIC]', 'runChecks - e', e);
@@ -496,6 +548,9 @@ function onPageMount() {
// Initial system info render
renderDiagnosticSystemInfoWidget();
// Initial Wiki disclaimer render
renderWikiDisclaimerWidget();
// Initial services info fetch
fetchServicesInfo();

View File

@@ -40,7 +40,7 @@ export function renderAvailableActions({
showSingBoxConfig,
}: IRenderAvailableActionsProps) {
return E('div', { class: 'pdk_diagnostic-page__right-bar__actions' }, [
E('b', {}, 'Available actions'),
E('b', {}, _('Available actions')),
...insertIf(restart.visible, [
renderButton({
classNames: ['cbi-button-apply'],

View File

@@ -18,7 +18,7 @@ export function renderSystemInfo({ items }: IRenderSystemInfoProps) {
E(
'b',
{ class: 'pdk_diagnostic-page__right-bar__system-info__title' },
'System information',
_('System information'),
),
...items.map((item) => {
const tagClass = [

View File

@@ -0,0 +1,40 @@
import { renderBookOpenTextIcon24 } from '../../../../icons';
import { renderButton } from '../../../../partials';
import { insertIf } from '../../../../helpers';
export function renderWikiDisclaimer(kind: 'default' | 'error' | 'warning') {
const iconWrap = E('span', {
class: 'pdk_diagnostic-page__right-bar__wiki__icon',
});
iconWrap.appendChild(renderBookOpenTextIcon24());
const className = [
'pdk_diagnostic-page__right-bar__wiki',
...insertIf(kind === 'error', [
'pdk_diagnostic-page__right-bar__wiki--error',
]),
...insertIf(kind === 'warning', [
'pdk_diagnostic-page__right-bar__wiki--warning',
]),
].join(' ');
return E('div', { class: className }, [
E('div', { class: 'pdk_diagnostic-page__right-bar__wiki__content' }, [
iconWrap,
E('div', { class: 'pdk_diagnostic-page__right-bar__wiki__texts' }, [
E('b', {}, _('Troubleshooting')),
E('div', {}, _('Do not panic, everything can be fixed, just...')),
]),
]),
renderButton({
classNames: ['cbi-button-save'],
text: _('Visit Wiki'),
onClick: () =>
window.open(
'https://podkop.net/docs/troubleshooting/?utm_source=podkop',
'_blank',
'noopener,noreferrer',
),
}),
]);
}

View File

@@ -8,6 +8,7 @@ export function render() {
}),
]),
E('div', { class: 'pdk_diagnostic-page__right-bar' }, [
E('div', { id: 'pdk_diagnostic-page-wiki' }),
E('div', { id: 'pdk_diagnostic-page-actions' }),
E('div', { id: 'pdk_diagnostic-page-system-info' }),
]),

View File

@@ -28,6 +28,31 @@ export const styles = `
grid-row-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki {
border: 2px var(--background-color-low, lightgray) solid;
border-radius: 4px;
padding: 10px;
display: grid;
grid-template-columns: auto;
grid-row-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki--warning {
border: 2px var(--warn-color-medium, orange) solid;
}
.pdk_diagnostic-page__right-bar__wiki--error {
border: 2px var(--error-color-medium, red) solid;
}
.pdk_diagnostic-page__right-bar__wiki__content {
display: grid;
grid-template-columns: 1fr 5fr;
grid-column-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki__texts {}
.pdk_diagnostic-page__right-bar__actions {
border: 2px var(--background-color-low, lightgray) solid;
border-radius: 4px;

View File

@@ -196,4 +196,11 @@ export namespace Podkop {
openwrt_version: string;
device_model: string;
}
export interface GetClashApiProxyLatency {
delay: number;
message?: string;
}
export type GetClashApiGroupLatency = Record<string, number>;
}

View File

@@ -3,7 +3,18 @@ import { validateDNS } from '../validateDns.js';
import { invalidIPs, validIPs } from './validateIp.test';
import { invalidDomains, validDomains } from './validateDomain.test';
const validDns = [...validIPs, ...validDomains];
export const additionalValidDns = [
['Google DNS (port 53)', '8.8.8.8:53'],
['Google DNS (port 5353)', '8.8.8.8:5353'],
['Cloudflare DNS (port 853)', '1.1.1.1:853'],
['Cloudflare domain (port 853)', 'cloudflare-dns.com:853'],
['DoH IP', '1.1.1.1/dns-query'],
['DoH IP with port 443', '1.1.1.1:443/dns-query'],
['DoH domain', 'cloudflare-dns.com/dns-query'],
['DoH domain with port 443', 'cloudflare-dns.com:443/dns-query'],
];
const validDns = [...validIPs, ...validDomains, ...additionalValidDns];
const invalidDns = [...invalidIPs, ...invalidDomains];

View File

@@ -16,6 +16,7 @@ const invalidUrls = [
['Unsupported protocol (ftp)', 'ftp://example.com'],
['Unsupported protocol (ws)', 'ws://example.com'],
['Empty string', ''],
['Without tld', 'https://google'],
];
describe('validateUrl', () => {

View File

@@ -7,11 +7,14 @@ export function validateDNS(value: string): ValidationResult {
return { valid: false, message: _('DNS server address cannot be empty') };
}
if (validateIPV4(value).valid) {
const cleanedValueWithoutPort = value.replace(/:(\d+)(?=\/|$)/, '');
const cleanedIpWithoutPath = cleanedValueWithoutPort.split('/')[0];
if (validateIPV4(cleanedIpWithoutPath).valid) {
return { valid: true, message: _('Valid') };
}
if (validateDomain(value).valid) {
if (validateDomain(cleanedValueWithoutPort).valid) {
return { valid: true, message: _('Valid') };
}

View File

@@ -1,18 +1,8 @@
import { ValidationResult } from './types';
// TODO refactor current validation and add tests
export function validateOutboundJson(value: string): ValidationResult {
try {
const parsed = JSON.parse(value);
if (!parsed.type || !parsed.server || !parsed.server_port) {
return {
valid: false,
message: _(
'Outbound JSON must contain at least "type", "server" and "server_port" fields',
),
};
}
JSON.parse(value);
return { valid: true, message: _('Valid') };
} catch {

View File

@@ -6,20 +6,22 @@ import { validateSocksUrl } from './validateSocksUrl';
// TODO refactor current validation and add tests
export function validateProxyUrl(url: string): ValidationResult {
if (url.startsWith('ss://')) {
return validateShadowsocksUrl(url);
const trimmedUrl = url.trim();
if (trimmedUrl.startsWith('ss://')) {
return validateShadowsocksUrl(trimmedUrl);
}
if (url.startsWith('vless://')) {
return validateVlessUrl(url);
if (trimmedUrl.startsWith('vless://')) {
return validateVlessUrl(trimmedUrl);
}
if (url.startsWith('trojan://')) {
return validateTrojanUrl(url);
if (trimmedUrl.startsWith('trojan://')) {
return validateTrojanUrl(trimmedUrl);
}
if (/^socks(4|4a|5):\/\//.test(url)) {
return validateSocksUrl(url);
if (/^socks(4|4a|5):\/\//.test(trimmedUrl)) {
return validateSocksUrl(trimmedUrl);
}
return {

View File

@@ -2,19 +2,31 @@ import { ValidationResult } from './types';
export function validateUrl(
url: string,
protocols: string[] = ['http:', 'https:'],
protocols = ['http:', 'https:'],
): ValidationResult {
try {
const parsedUrl = new URL(url);
if (!protocols.includes(parsedUrl.protocol)) {
return {
valid: false,
message: `${_('URL must use one of the following protocols:')} ${protocols.join(', ')}`,
};
}
return { valid: true, message: _('Valid') };
} catch (_e) {
if (!url.length) {
return { valid: false, message: _('Invalid URL format') };
}
const hasValidProtocol = protocols.some((p) => url.indexOf(p + '//') === 0);
if (!hasValidProtocol)
return {
valid: false,
message:
_('URL must use one of the following protocols:') +
' ' +
protocols.join(', '),
};
const regex = new RegExp(
`^(?:${protocols.map((p) => p.replace(':', '')).join('|')})://` +
`(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`,
);
if (regex.test(url)) {
return { valid: true, message: _('Valid') };
}
return { valid: false, message: _('Invalid URL format') };
}

View File

@@ -43,7 +43,8 @@ export function validateVlessUrl(url: string): ValidationResult {
if (!port)
return { valid: false, message: 'Invalid VLESS URL: missing port' };
const portNum = Number(port);
const cleanedPort = port.replace('/', '');
const portNum = Number(cleanedPort);
if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535)
return {
valid: false,

View File

@@ -90,6 +90,7 @@ update_config() {
mv /etc/config/podkop /etc/config/podkop-070
wget -O /etc/config/podkop https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/podkop/files/etc/config/podkop
msg "Podkop config has been reset to default. Your old config saved in /etc/config/podkop-070"
break
;;
*)
msg "Exit"

View File

@@ -40,10 +40,12 @@ function validateDNS(value) {
if (!value) {
return { valid: false, message: _("DNS server address cannot be empty") };
}
if (validateIPV4(value).valid) {
const cleanedValueWithoutPort = value.replace(/:(\d+)(?=\/|$)/, "");
const cleanedIpWithoutPath = cleanedValueWithoutPort.split("/")[0];
if (validateIPV4(cleanedIpWithoutPath).valid) {
return { valid: true, message: _("Valid") };
}
if (validateDomain(value).valid) {
if (validateDomain(cleanedValueWithoutPort).valid) {
return { valid: true, message: _("Valid") };
}
return {
@@ -56,18 +58,22 @@ function validateDNS(value) {
// src/validators/validateUrl.ts
function validateUrl(url, protocols = ["http:", "https:"]) {
try {
const parsedUrl = new URL(url);
if (!protocols.includes(parsedUrl.protocol)) {
return {
valid: false,
message: `${_("URL must use one of the following protocols:")} ${protocols.join(", ")}`
};
}
return { valid: true, message: _("Valid") };
} catch (_e) {
if (!url.length) {
return { valid: false, message: _("Invalid URL format") };
}
const hasValidProtocol = protocols.some((p) => url.indexOf(p + "//") === 0);
if (!hasValidProtocol)
return {
valid: false,
message: _("URL must use one of the following protocols:") + " " + protocols.join(", ")
};
const regex = new RegExp(
`^(?:${protocols.map((p) => p.replace(":", "")).join("|")})://(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`
);
if (regex.test(url)) {
return { valid: true, message: _("Valid") };
}
return { valid: false, message: _("Invalid URL format") };
}
// src/validators/validatePath.ts
@@ -259,7 +265,8 @@ function validateVlessUrl(url) {
return { valid: false, message: "Invalid VLESS URL: missing hostname" };
if (!port)
return { valid: false, message: "Invalid VLESS URL: missing port" };
const portNum = Number(port);
const cleanedPort = port.replace("/", "");
const portNum = Number(cleanedPort);
if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535)
return {
valid: false,
@@ -320,15 +327,7 @@ function validateVlessUrl(url) {
// src/validators/validateOutboundJson.ts
function validateOutboundJson(value) {
try {
const parsed = JSON.parse(value);
if (!parsed.type || !parsed.server || !parsed.server_port) {
return {
valid: false,
message: _(
'Outbound JSON must contain at least "type", "server" and "server_port" fields'
)
};
}
JSON.parse(value);
return { valid: true, message: _("Valid") };
} catch {
return { valid: false, message: _("Invalid JSON format") };
@@ -451,17 +450,18 @@ function validateSocksUrl(url) {
// src/validators/validateProxyUrl.ts
function validateProxyUrl(url) {
if (url.startsWith("ss://")) {
return validateShadowsocksUrl(url);
const trimmedUrl = url.trim();
if (trimmedUrl.startsWith("ss://")) {
return validateShadowsocksUrl(trimmedUrl);
}
if (url.startsWith("vless://")) {
return validateVlessUrl(url);
if (trimmedUrl.startsWith("vless://")) {
return validateVlessUrl(trimmedUrl);
}
if (url.startsWith("trojan://")) {
return validateTrojanUrl(url);
if (trimmedUrl.startsWith("trojan://")) {
return validateTrojanUrl(trimmedUrl);
}
if (/^socks(4|4a|5):\/\//.test(url)) {
return validateSocksUrl(url);
if (/^socks(4|4a|5):\/\//.test(trimmedUrl)) {
return validateSocksUrl(trimmedUrl);
}
return {
valid: false,
@@ -486,7 +486,7 @@ async function callBaseMethod(method, args = [], command = "/usr/bin/podkop") {
const response = await executeShellCommand({
command,
args: [method, ...args],
timeout: 1e4
timeout: 15e3
});
if (response.stdout) {
try {
@@ -559,14 +559,14 @@ var PodkopShellMethods = {
getClashApiProxies: async () => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_PROXIES
]),
getClashApiProxyLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY,
tag
]),
getClashApiGroupLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY,
tag
]),
getClashApiProxyLatency: async (tag) => callBaseMethod(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag, "5000"]
),
getClashApiGroupLatency: async (tag) => callBaseMethod(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag, "10000"]
),
setClashApiGroupProxy: async (group, proxy) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,
group,
@@ -978,26 +978,36 @@ var TabService = class _TabService {
};
var TabServiceInstance = TabService.getInstance();
// src/podkop/tabs/diagnostic/helpers/getCheckTitle.ts
function getCheckTitle(name) {
return `${name} ${_("checks")}`;
}
// src/podkop/tabs/diagnostic/checks/contstants.ts
var DIAGNOSTICS_CHECKS_MAP = {
["DNS" /* DNS */]: {
order: 1,
title: _("DNS checks"),
title: getCheckTitle("DNS"),
code: "DNS" /* DNS */
},
["SINGBOX" /* SINGBOX */]: {
order: 2,
title: _("Sing-box checks"),
title: getCheckTitle("Sing-box"),
code: "SINGBOX" /* SINGBOX */
},
["NFT" /* NFT */]: {
order: 3,
title: _("Nftables checks"),
title: getCheckTitle("Nftables"),
code: "NFT" /* NFT */
},
["FAKEIP" /* FAKEIP */]: {
["OUTBOUNDS" /* OUTBOUNDS */]: {
order: 4,
title: _("FakeIP checks"),
title: getCheckTitle("Outbounds"),
code: "OUTBOUNDS" /* OUTBOUNDS */
},
["FAKEIP" /* FAKEIP */]: {
order: 5,
title: getCheckTitle("FakeIP"),
code: "FAKEIP" /* FAKEIP */
}
};
@@ -1065,6 +1075,14 @@ var initialDiagnosticStore = {
items: [],
state: "skipped"
},
{
code: "OUTBOUNDS" /* OUTBOUNDS */,
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
description: _("Not running"),
items: [],
state: "skipped"
},
{
code: "FAKEIP" /* FAKEIP */,
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
@@ -1081,7 +1099,7 @@ var loadingDiagnosticsChecksStore = {
code: "DNS" /* DNS */,
title: DIAGNOSTICS_CHECKS_MAP.DNS.title,
order: DIAGNOSTICS_CHECKS_MAP.DNS.order,
description: _("Queued"),
description: _("Pending"),
items: [],
state: "skipped"
},
@@ -1089,7 +1107,7 @@ var loadingDiagnosticsChecksStore = {
code: "SINGBOX" /* SINGBOX */,
title: DIAGNOSTICS_CHECKS_MAP.SINGBOX.title,
order: DIAGNOSTICS_CHECKS_MAP.SINGBOX.order,
description: _("Queued"),
description: _("Pending"),
items: [],
state: "skipped"
},
@@ -1097,7 +1115,15 @@ var loadingDiagnosticsChecksStore = {
code: "NFT" /* NFT */,
title: DIAGNOSTICS_CHECKS_MAP.NFT.title,
order: DIAGNOSTICS_CHECKS_MAP.NFT.order,
description: _("Queued"),
description: _("Pending"),
items: [],
state: "skipped"
},
{
code: "OUTBOUNDS" /* OUTBOUNDS */,
title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title,
order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order,
description: _("Pending"),
items: [],
state: "skipped"
},
@@ -1105,7 +1131,7 @@ var loadingDiagnosticsChecksStore = {
code: "FAKEIP" /* FAKEIP */,
title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title,
order: DIAGNOSTICS_CHECKS_MAP.FAKEIP.order,
description: _("Queued"),
description: _("Pending"),
items: [],
state: "skipped"
}
@@ -2335,6 +2361,7 @@ function render2() {
})
]),
E("div", { class: "pdk_diagnostic-page__right-bar" }, [
E("div", { id: "pdk_diagnostic-page-wiki" }),
E("div", { id: "pdk_diagnostic-page-actions" }),
E("div", { id: "pdk_diagnostic-page-system-info" })
])
@@ -2355,6 +2382,26 @@ function updateCheckStore(check, minified) {
});
}
// src/podkop/tabs/diagnostic/helpers/getMeta.ts
function getMeta({ allGood, atLeastOneGood }) {
if (allGood) {
return {
state: "success",
description: _("Checks passed")
};
}
if (atLeastOneGood) {
return {
state: "warning",
description: _("Issues detected")
};
}
return {
state: "error",
description: _("Checks failed")
};
}
// src/podkop/tabs/diagnostic/checks/runDnsCheck.ts
async function runDnsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS;
@@ -2362,7 +2409,7 @@ async function runDnsCheck() {
order,
code,
title,
description: _("Checking dns, please wait"),
description: _("Checking, please wait"),
state: "loading",
items: []
});
@@ -2372,7 +2419,7 @@ async function runDnsCheck() {
order,
code,
title,
description: _("Cannot receive DNS checks result"),
description: _("Cannot receive checks result"),
state: "error",
items: []
});
@@ -2381,24 +2428,16 @@ async function runDnsCheck() {
const data = dnsChecks.data;
const allGood = Boolean(data.dns_on_router) && Boolean(data.dhcp_config_status) && Boolean(data.bootstrap_dns_status) && Boolean(data.dns_status);
const atLeastOneGood = Boolean(data.dns_on_router) || Boolean(data.dhcp_config_status) || Boolean(data.bootstrap_dns_status) || Boolean(data.dns_status);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: _("DNS checks passed"),
state: getStatus(),
description,
state,
items: [
...insertIf(
data.dns_type === "doh" || data.dns_type === "dot",
data.dns_type === "doh" || data.dns_type === "dot" || !data.bootstrap_dns_status,
[
{
state: data.bootstrap_dns_status ? "success" : "error",
@@ -2436,7 +2475,7 @@ async function runSingBoxCheck() {
order,
code,
title,
description: _("Checking sing-box, please wait"),
description: _("Checking, please wait"),
state: "loading",
items: []
});
@@ -2446,7 +2485,7 @@ async function runSingBoxCheck() {
order,
code,
title,
description: _("Cannot receive Sing-box checks result"),
description: _("Cannot receive checks result"),
state: "error",
items: []
});
@@ -2455,21 +2494,13 @@ async function runSingBoxCheck() {
const data = singBoxChecks.data;
const allGood = Boolean(data.sing_box_installed) && Boolean(data.sing_box_version_ok) && Boolean(data.sing_box_service_exist) && Boolean(data.sing_box_autostart_disabled) && Boolean(data.sing_box_process_running) && Boolean(data.sing_box_ports_listening);
const atLeastOneGood = Boolean(data.sing_box_installed) || Boolean(data.sing_box_version_ok) || Boolean(data.sing_box_service_exist) || Boolean(data.sing_box_autostart_disabled) || Boolean(data.sing_box_process_running) || Boolean(data.sing_box_ports_listening);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: _("Sing-box checks passed"),
state: getStatus(),
description,
state,
items: [
{
state: data.sing_box_installed ? "success" : "error",
@@ -2478,7 +2509,7 @@ async function runSingBoxCheck() {
},
{
state: data.sing_box_version_ok ? "success" : "error",
key: _("Sing-box version >= 1.12.4"),
key: _("Sing-box version is compatible (newer than 1.12.4)"),
value: ""
},
{
@@ -2515,7 +2546,7 @@ async function runNftCheck() {
order,
code,
title,
description: _("Checking nftables, please wait"),
description: _("Checking, please wait"),
state: "loading",
items: []
});
@@ -2527,7 +2558,7 @@ async function runNftCheck() {
order,
code,
title,
description: _("Cannot receive nftables checks result"),
description: _("Cannot receive checks result"),
state: "error",
items: []
});
@@ -2536,21 +2567,13 @@ async function runNftCheck() {
const data = nftablesChecks.data;
const allGood = Boolean(data.table_exist) && Boolean(data.rules_mangle_exist) && Boolean(data.rules_mangle_counters) && Boolean(data.rules_mangle_output_exist) && Boolean(data.rules_mangle_output_counters) && Boolean(data.rules_proxy_exist) && Boolean(data.rules_proxy_counters) && !data.rules_other_mark_exist;
const atLeastOneGood = Boolean(data.table_exist) || Boolean(data.rules_mangle_exist) || Boolean(data.rules_mangle_counters) || Boolean(data.rules_mangle_output_exist) || Boolean(data.rules_mangle_output_counters) || Boolean(data.rules_proxy_exist) || Boolean(data.rules_proxy_counters) || !data.rules_other_mark_exist;
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description: allGood ? _("Nftables checks passed") : _("Nftables checks partially passed"),
state: getStatus(),
description,
state,
items: [
{
state: data.table_exist ? "success" : "error",
@@ -2606,7 +2629,7 @@ async function runFakeIPCheck() {
order,
code,
title,
description: _("Checking FakeIP, please wait"),
description: _("Checking, please wait"),
state: "loading",
items: []
});
@@ -2620,25 +2643,7 @@ async function runFakeIPCheck() {
};
const allGood = checks.router || checks.browserFakeIP || checks.differentIP;
const atLeastOneGood = checks.router && checks.browserFakeIP && checks.differentIP;
function getMeta() {
if (allGood) {
return {
state: "success",
description: _("FakeIP checks passed")
};
}
if (atLeastOneGood) {
return {
state: "warning",
description: _("FakeIP checks partially passed")
};
}
return {
state: "error",
description: _("FakeIP checks failed")
};
}
const { state, description } = getMeta();
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
@@ -3211,6 +3216,34 @@ function renderSearchIcon24() {
);
}
// src/icons/renderBookOpenTextIcon24.ts
function renderBookOpenTextIcon24() {
const NS = "http://www.w3.org/2000/svg";
return svgEl(
"svg",
{
xmlns: NS,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
class: "lucide lucide-book-open-text-icon lucide-book-open-text"
},
[
svgEl("path", { d: "M12 7v14" }),
svgEl("path", { d: "M16 12h2" }),
svgEl("path", { d: "M16 8h2" }),
svgEl("path", {
d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"
}),
svgEl("path", { d: "M6 12h2" }),
svgEl("path", { d: "M6 8h2" })
]
);
}
// src/partials/button/renderButton.ts
function renderButton({
classNames = [],
@@ -3341,7 +3374,7 @@ function renderAvailableActions({
showSingBoxConfig
}) {
return E("div", { class: "pdk_diagnostic-page__right-bar__actions" }, [
E("b", {}, "Available actions"),
E("b", {}, _("Available actions")),
...insertIf(restart.visible, [
renderButton({
classNames: ["cbi-button-apply"],
@@ -3599,7 +3632,7 @@ function renderSystemInfo({ items }) {
E(
"b",
{ class: "pdk_diagnostic-page__right-bar__system-info__title" },
"System information"
_("System information")
),
...items.map((item) => {
const tagClass = [
@@ -3634,6 +3667,140 @@ function normalizeCompiledVersion(version) {
return version;
}
// src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts
function renderWikiDisclaimer(kind) {
const iconWrap = E("span", {
class: "pdk_diagnostic-page__right-bar__wiki__icon"
});
iconWrap.appendChild(renderBookOpenTextIcon24());
const className = [
"pdk_diagnostic-page__right-bar__wiki",
...insertIf(kind === "error", [
"pdk_diagnostic-page__right-bar__wiki--error"
]),
...insertIf(kind === "warning", [
"pdk_diagnostic-page__right-bar__wiki--warning"
])
].join(" ");
return E("div", { class: className }, [
E("div", { class: "pdk_diagnostic-page__right-bar__wiki__content" }, [
iconWrap,
E("div", { class: "pdk_diagnostic-page__right-bar__wiki__texts" }, [
E("b", {}, _("Troubleshooting")),
E("div", {}, _("Do not panic, everything can be fixed, just..."))
])
]),
renderButton({
classNames: ["cbi-button-save"],
text: _("Visit Wiki"),
onClick: () => window.open(
"https://podkop.net/docs/troubleshooting/?utm_source=podkop",
"_blank",
"noopener,noreferrer"
)
})
]);
}
// src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts
async function runSectionsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS;
updateCheckStore({
order,
code,
title,
description: _("Checking, please wait"),
state: "loading",
items: []
});
const sections = await getDashboardSections();
if (!sections.success) {
updateCheckStore({
order,
code,
title,
description: _("Cannot receive checks result"),
state: "error",
items: []
});
throw new Error("Sections checks failed");
}
const items = await Promise.all(
sections.data.map(async (section) => {
async function getLatency() {
if (section.withTagSelect) {
const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency(
section.code
);
const selectedOutbound = section.outbounds.find(
(item) => item.selected
);
const isUrlTest = selectedOutbound?.type === "URLTest";
const success3 = latencyGroup.success && !latencyGroup.data.message;
if (success3) {
if (isUrlTest) {
const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / ");
return {
success: true,
latency: `[${_("Fastest")}] ${latency2}`
};
}
const selectedProxyDelay = latencyGroup.data?.[selectedOutbound?.code ?? ""];
if (selectedProxyDelay) {
return {
success: true,
latency: `[${selectedOutbound?.displayName ?? ""}] ${selectedProxyDelay}ms`
};
}
return {
success: false,
latency: `[${selectedOutbound?.displayName ?? ""}] ${_("Not responding")}`
};
}
return {
success: false,
latency: _("Not responding")
};
}
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
section.code
);
const success2 = latencyProxy.success && !latencyProxy.data.message;
if (success2) {
return {
success: true,
latency: `${latencyProxy.data.delay} ms`
};
}
return {
success: false,
latency: _("Not responding")
};
}
const { latency, success } = await getLatency();
return {
state: success ? "success" : "error",
key: section.displayName,
value: latency
};
})
);
const allGood = items.every((item) => item.state === "success");
const atLeastOneGood = items.some((item) => item.state === "success");
const { state, description } = getMeta({ atLeastOneGood, allGood });
updateCheckStore({
order,
code,
title,
description,
state,
items
});
if (!atLeastOneGood) {
throw new Error("Sections checks failed");
}
}
// src/podkop/tabs/diagnostic/initController.ts
async function fetchSystemInfo() {
const systemInfo = await PodkopShellMethods.getSystemInfo();
@@ -3813,9 +3980,13 @@ async function handleShowGlobalCheck() {
_("Global check"),
renderModal(globalCheck.data, "global_check")
);
} else {
logger.error("[DIAGNOSTIC]", "handleShowGlobalCheck - e", globalCheck);
showToast(_("Failed to execute!"), "error");
}
} catch (e) {
logger.error("[DIAGNOSTIC]", "handleShowGlobalCheck - e", e);
showToast(_("Failed to execute!"), "error");
} finally {
store.set({
diagnosticsActions: {
@@ -3840,9 +4011,13 @@ async function handleViewLogs() {
_("View logs"),
renderModal(viewLogs.data, "view_logs")
);
} else {
logger.error("[DIAGNOSTIC]", "handleViewLogs - e", viewLogs);
showToast(_("Failed to execute!"), "error");
}
} catch (e) {
logger.error("[DIAGNOSTIC]", "handleViewLogs - e", e);
showToast(_("Failed to execute!"), "error");
} finally {
store.set({
diagnosticsActions: {
@@ -3867,9 +4042,17 @@ async function handleShowSingBoxConfig() {
_("Show sing-box config"),
renderModal(showSingBoxConfig.data, "show_sing_box_config")
);
} else {
logger.error(
"[DIAGNOSTIC]",
"handleShowSingBoxConfig - e",
showSingBoxConfig
);
showToast(_("Failed to execute!"), "error");
}
} catch (e) {
logger.error("[DIAGNOSTIC]", "handleShowSingBoxConfig - e", e);
showToast(_("Failed to execute!"), "error");
} finally {
store.set({
diagnosticsActions: {
@@ -3879,6 +4062,23 @@ async function handleShowSingBoxConfig() {
});
}
}
function renderWikiDisclaimerWidget() {
const diagnosticsChecks = store.get().diagnosticsChecks;
function getWikiKind() {
const allResults = diagnosticsChecks.map((check) => check.state);
if (allResults.includes("error")) {
return "error";
}
if (allResults.includes("warning")) {
return "warning";
}
return "default";
}
const container = document.getElementById("pdk_diagnostic-page-wiki");
return preserveScrollForPage(() => {
container.replaceChildren(renderWikiDisclaimer(getWikiKind()));
});
}
function renderDiagnosticAvailableActionsWidget() {
const diagnosticsActions = store.get().diagnosticsActions;
const servicesInfoWidget = store.get().servicesInfoWidget;
@@ -3948,9 +4148,7 @@ function renderDiagnosticSystemInfoWidget() {
function getPodkopVersionRow() {
const loading = diagnosticsSystemInfo.loading;
const unknown = diagnosticsSystemInfo.podkop_version === _("unknown");
const hasActualVersion = Boolean(
diagnosticsSystemInfo.podkop_latest_version
);
const hasActualVersion = Boolean(diagnosticsSystemInfo.podkop_latest_version) && diagnosticsSystemInfo.podkop_latest_version !== "unknown";
const version = normalizeCompiledVersion(
diagnosticsSystemInfo.podkop_version
);
@@ -3962,6 +4160,11 @@ function renderDiagnosticSystemInfoWidget() {
};
}
if (version !== `v${diagnosticsSystemInfo.podkop_latest_version}`) {
logger.debug(
"[DIAGNOSTIC]",
"diagnosticsSystemInfo",
diagnosticsSystemInfo
);
return {
key: "Podkop",
value: version,
@@ -3985,7 +4188,7 @@ function renderDiagnosticSystemInfoWidget() {
getPodkopVersionRow(),
{
key: "Luci App",
value: normalizeCompiledVersion(diagnosticsSystemInfo.luci_app_version)
value: normalizeCompiledVersion(PODKOP_LUCI_APP_VERSION)
},
{
key: "Sing-box",
@@ -4008,6 +4211,7 @@ function renderDiagnosticSystemInfoWidget() {
async function onStoreUpdate2(next, prev, diff) {
if (diff.diagnosticsChecks) {
renderDiagnosticsChecks();
renderWikiDisclaimerWidget();
}
if (diff.diagnosticsRunAction) {
renderDiagnosticRunActionWidget();
@@ -4028,6 +4232,7 @@ async function runChecks() {
await runDnsCheck();
await runSingBoxCheck();
await runNftCheck();
await runSectionsCheck();
await runFakeIPCheck();
} catch (e) {
logger.error("[DIAGNOSTIC]", "runChecks - e", e);
@@ -4042,6 +4247,7 @@ function onPageMount2() {
renderDiagnosticRunActionWidget();
renderDiagnosticAvailableActionsWidget();
renderDiagnosticSystemInfoWidget();
renderWikiDisclaimerWidget();
fetchServicesInfo();
fetchSystemInfo();
}
@@ -4120,6 +4326,31 @@ var styles4 = `
grid-row-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki {
border: 2px var(--background-color-low, lightgray) solid;
border-radius: 4px;
padding: 10px;
display: grid;
grid-template-columns: auto;
grid-row-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki--warning {
border: 2px var(--warn-color-medium, orange) solid;
}
.pdk_diagnostic-page__right-bar__wiki--error {
border: 2px var(--error-color-medium, red) solid;
}
.pdk_diagnostic-page__right-bar__wiki__content {
display: grid;
grid-template-columns: 1fr 5fr;
grid-column-gap: 10px;
}
.pdk_diagnostic-page__right-bar__wiki__texts {}
.pdk_diagnostic-page__right-bar__actions {
border: 2px var(--background-color-low, lightgray) solid;
border-radius: 4px;
@@ -4508,6 +4739,10 @@ function insertIf(condition, elements) {
function insertIfObj(condition, object) {
return condition ? object : {};
}
// src/main.ts
if (typeof structuredClone !== "function")
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
return baseclass.extend({
ALLOWED_WITH_RUSSIA_INSIDE,
BOOTSTRAP_DNS_SERVER_OPTIONS,

View File

@@ -104,6 +104,70 @@ function createSectionContent(section) {
return validation.message;
};
o = section.option(
form.ListValue,
"urltest_check_interval",
_("URLTest Check Interval"),
_("The interval between connectivity tests")
);
o.value("30s", _("Every 30 seconds"));
o.value("1m", _("Every 1 minute"));
o.value("3m", _("Every 3 minutes"));
o.value("5m", _("Every 5 minutes"));
o.default = "3m";
o.depends("proxy_config_type", "urltest");
o = section.option(
form.Value,
"urltest_tolerance",
_("URLTest Tolerance"),
_("The maximum difference in response times (ms) allowed when comparing servers")
);
o.default = "50";
o.rmempty = false;
o.depends("proxy_config_type", "urltest");
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
const parsed = parseFloat(value);
if (/^[0-9]+$/.test(value) && !isNaN(parsed) && isFinite(parsed) && parsed >= 50 && parsed <= 1000) {
return true;
}
return _('Must be a number in the range of 50 - 1000');
};
o = section.option(
form.Value,
"urltest_testing_url",
_("URLTest Testing URL"),
_("The URL used to test server connectivity")
);
o.value("https://www.gstatic.com/generate_204", "https://www.gstatic.com/generate_204 (Google)");
o.value("https://cp.cloudflare.com/generate_204", "https://cp.cloudflare.com/generate_204 (Cloudflare)");
o.value("https://captive.apple.com", "https://captive.apple.com (Apple)");
o.value("https://connectivity-check.ubuntu.com", "https://connectivity-check.ubuntu.com (Ubuntu)")
o.default = "https://www.gstatic.com/generate_204";
o.rmempty = false;
o.depends("proxy_config_type", "urltest");
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
const validation = main.validateUrl(value);
if (validation.valid) {
return true;
}
return validation.message;
};
o = section.option(
form.Flag,
"enable_udp_over_tcp",
@@ -241,7 +305,7 @@ function createSectionContent(section) {
(v) => v === lastSelected || !main.REGIONAL_OPTIONS.includes(v),
);
notifications.push(
E("p", { class: "alert-message warning" }, [
E("p", {}, [
E("strong", {}, _("Regional options cannot be used together")),
E("br"),
_(

View File

@@ -267,7 +267,7 @@ function createSettingsContent(section) {
form.Flag,
"download_lists_via_proxy",
_("Download Lists via Proxy/VPN"),
_("Downloading all lists via main Proxy/VPN"),
_("Downloading all lists via specific Proxy/VPN"),
);
o.default = "0";
o.rmempty = false;

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-21 23:02+0300\n"
"PO-Revision-Date: 2025-10-21 23:02+0300\n"
"POT-Creation-Date: 2025-10-27 13:15+0200\n"
"PO-Revision-Date: 2025-10-27 13:15+0200\n"
"Last-Translator: divocat\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -44,6 +44,9 @@ msgstr "Необходимо указать хотя бы один действ
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
msgstr "Необходимо указать хотя бы одну действительную подсеть или IP. Только комментарии недопустимы."
msgid "Available actions"
msgstr "Доступные действия"
msgid "Bootsrap DNS"
msgstr "Bootstrap DNS"
@@ -62,26 +65,20 @@ msgstr "Путь к файлу кэша"
msgid "Cache file path cannot be empty"
msgstr "Путь к файлу кэша не может быть пустым"
msgid "Cannot receive DNS checks result"
msgstr "Не удалось получить результаты проверки DNS"
msgid "Cannot receive checks result"
msgstr "Не удалось получить результаты проверки"
msgid "Cannot receive nftables checks result"
msgstr "Не удалось получить результаты проверки nftables"
msgid "Checking, please wait"
msgstr "Проверяем, пожалуйста подождите"
msgid "Cannot receive Sing-box checks result"
msgstr "Не удалось получить результаты проверки Sing-box"
msgid "checks"
msgstr "проверки"
msgid "Checking dns, please wait"
msgstr "Проверка dns, пожалуйста подождите"
msgid "Checks failed"
msgstr "Проверки не выполнены"
msgid "Checking FakeIP, please wait"
msgstr "Проверка FakeIP, пожалуйста подождите"
msgid "Checking nftables, please wait"
msgstr "Проверка nftables, пожалуйста подождите"
msgid "Checking sing-box, please wait"
msgstr "Проверка sing-box, пожалуйста подождите"
msgid "Checks passed"
msgstr "Проверки пройдены"
msgid "CIDR must be between 0 and 32"
msgstr "CIDR должен быть между 0 и 32"
@@ -143,12 +140,6 @@ msgstr "Отключить QUIC протокол для улучшения со
msgid "Disabled"
msgstr "Отключено"
msgid "DNS checks"
msgstr "DNS проверки"
msgid "DNS checks passed"
msgstr "DNS проверки успешно завершены"
msgid "DNS on router"
msgstr "DNS на роутере"
@@ -170,6 +161,9 @@ msgstr "DNS-сервер"
msgid "DNS server address cannot be empty"
msgstr "Адрес DNS-сервера не может быть пустым"
msgid "Do not panic, everything can be fixed, just..."
msgstr "Не паникуйте, всё можно исправить, просто..."
msgid "Domain Resolver"
msgstr "Резолвер доменов"
@@ -188,9 +182,6 @@ msgstr "Скачивать списки через Proxy/VPN"
msgid "Download Lists via specific proxy section"
msgstr "Скачивать списки через выбранную секцию"
msgid "Downloading all lists via main Proxy/VPN"
msgstr "Загрузка всех списков через основной прокси/VPN"
msgid "Downloading all lists via specific Proxy/VPN"
msgstr "Загрузка всех списков через указанный прокси/VPN"
@@ -227,6 +218,18 @@ msgstr "Введите доменные имена без протоколов,
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
msgstr "Введите подсети в нотации CIDR (например, 103.21.244.0/22) или отдельные IP-адреса"
msgid "Every 1 minute"
msgstr "Каждую минуту"
msgid "Every 3 minutes"
msgstr "Каждые 3 минуты"
msgid "Every 30 seconds"
msgstr "Каждые 30 секунд"
msgid "Every 5 minutes"
msgstr "Каждые 5 минут"
msgid "Exclude NTP"
msgstr "Исключить NTP"
@@ -236,17 +239,8 @@ msgstr "Исключите трафик протокола NTP из туннел
msgid "Failed to copy!"
msgstr "Не удалось скопировать!"
msgid "FakeIP checks"
msgstr "Проверка FakeIP"
msgid "FakeIP checks failed"
msgstr "Проверки FakeIP не пройдены"
msgid "FakeIP checks partially passed"
msgstr "Проверка FakeIP частично пройдена"
msgid "FakeIP checks passed"
msgstr "Проверки FakeIP пройдены"
msgid "Failed to execute!"
msgstr "Не удалось выполнить!"
msgid "Fastest"
msgstr "Самый быстрый"
@@ -365,6 +359,9 @@ msgstr "Неверный URL VLESS: ошибка разбора"
msgid "IP address 0.0.0.0 is not allowed"
msgstr "IP-адрес 0.0.0.0 не допускается"
msgid "Issues detected"
msgstr "Обнаружены проблемы"
msgid "Latest"
msgstr "Последняя"
@@ -389,24 +386,21 @@ msgstr "Порт смешанного прокси"
msgid "Monitored Interfaces"
msgstr "Наблюдаемые интерфейсы"
msgid "Must be a number in the range of 50 - 1000"
msgstr "Должно быть числом от 50 до 1000"
msgid "Network Interface"
msgstr "Сетевой интерфейс"
msgid "Nftables checks"
msgstr "Проверки Nftables"
msgid "Nftables checks partially passed"
msgstr "Проверки Nftables частично пройдена"
msgid "Nftables checks passed"
msgstr "Nftables проверки успешно завершены"
msgid "No other marking rules found"
msgstr "Другие правила маркировки не найдены"
msgid "Not implement yet"
msgstr "Ещё не реализовано"
msgid "Not responding"
msgstr "Не отвечает"
msgid "Not running"
msgstr "Не запущено"
@@ -419,9 +413,6 @@ msgstr "Конфигурация Outbound"
msgid "Outbound Configuration"
msgstr "Конфигурация исходящего соединения"
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
msgid "Outdated"
msgstr "Устаревшая"
@@ -440,6 +431,9 @@ msgstr "Путь должен содержать хотя бы одну дире
msgid "Path must end with cache.db"
msgstr "Путь должен заканчиваться на cache.db"
msgid "Pending"
msgstr "Ожидает запуска"
msgid "Podkop"
msgstr "Podkop"
@@ -458,17 +452,14 @@ msgstr "Прокси-трафик не маршрутизируется чере
msgid "Proxy traffic is routed via FakeIP"
msgstr "Прокси-трафик направляется через FakeIP"
msgid "Queued"
msgstr "В очереди"
msgid "Regional options cannot be used together"
msgstr "Нельзя использовать несколько региональных опций одновременно"
msgid "Remote Domain Lists"
msgstr "Удалённые списки доменов"
msgstr "Внешние списки доменов"
msgid "Remote Subnet Lists"
msgstr "Удалённые списки подсетей"
msgstr "Внешние списки подсетей"
msgid "Restart podkop"
msgstr "Перезапустить Podkop"
@@ -569,12 +560,6 @@ msgstr "Sing-box"
msgid "Sing-box autostart disabled"
msgstr "Автостарт sing-box отключен"
msgid "Sing-box checks"
msgstr "Sing-box проверки"
msgid "Sing-box checks passed"
msgstr "Sing-box проверки успешно завершены"
msgid "Sing-box installed"
msgstr "Sing-box установлен"
@@ -587,8 +572,8 @@ msgstr "Процесс sing-box запущен"
msgid "Sing-box service exist"
msgstr "Сервис sing-box существует"
msgid "Sing-box version >= 1.12.4"
msgstr "Версия sing-box >= 1.12.4"
msgid "Sing-box version is compatible (newer than 1.12.4)"
msgstr "Версия Sing-box совместима (новее 1.12.4)"
msgid "Source Network Interface"
msgstr "Сетевой интерфейс источника"
@@ -600,10 +585,10 @@ msgid "Specify local IP addresses or subnets whose traffic will always be routed
msgstr "Укажите локальные IP-адреса или подсети, трафик которых всегда будет направляться через настроенный маршрут."
msgid "Specify remote URLs to download and use domain lists"
msgstr "Укажите удаленные URL-адреса для загрузки и использования списков доменов."
msgstr "Укажите URL-адреса для загрузки и использования списков доменов."
msgid "Specify remote URLs to download and use subnet lists"
msgstr "Укажите удаленные URL-адреса для загрузки и использования списков подсетей."
msgstr "Укажите URL-адреса для загрузки и использования списков подсетей."
msgid "Specify the path to the list file located on the router filesystem"
msgstr "Укажите путь к файлу списка, расположенному в файловой системе маршрутизатора."
@@ -620,11 +605,14 @@ msgstr "Успешно скопировано!"
msgid "System info"
msgstr "Системная информация"
msgid "System information"
msgstr "Системная информация"
msgid "Table exist"
msgstr "Таблица существует"
msgid "Test latency"
msgstr "Измерить задержки"
msgstr "Тестирование задержки"
msgid "Text List"
msgstr "Текстовый список"
@@ -635,6 +623,15 @@ msgstr "Текстовый список (через запятую, пробел
msgid "The DNS server used to look up the IP address of an upstream DNS server"
msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера"
msgid "The interval between connectivity tests"
msgstr "Интервал между тестами подключения"
msgid "The maximum difference in response times (ms) allowed when comparing servers"
msgstr "Максимально допустимая разница во времени отклика (мс) при сравнении серверов"
msgid "The URL used to test server connectivity"
msgstr "URL-адрес, используемый для проверки подключения к серверу"
msgid "Time in seconds for DNS record caching (default: 60)"
msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)"
@@ -644,6 +641,9 @@ msgstr "Трафик"
msgid "Traffic Total"
msgstr "Всего трафика"
msgid "Troubleshooting"
msgstr "Устранение неполадок"
msgid "TTL must be a positive number"
msgstr "TTL должно быть положительным числом"
@@ -674,9 +674,18 @@ msgstr "URL должен использовать один из следующи
msgid "URLTest"
msgstr "URLTest"
msgid "URLTest Check Interval"
msgstr "Интервал проверки URLTest"
msgid "URLTest Proxy Links"
msgstr "Ссылки прокси для URLTest"
msgid "URLTest Testing URL"
msgstr "URL для тестирования URLTest"
msgid "URLTest Tolerance"
msgstr "Порог переключения URLTest"
msgid "User Domain List Type"
msgstr "Тип пользовательского списка доменов"
@@ -704,6 +713,9 @@ msgstr "Ошибки валидации:"
msgid "View logs"
msgstr "Посмотреть логи"
msgid "Visit Wiki"
msgstr "Перейти в wiki"
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены."

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PODKOP\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-21 20:02+0300\n"
"PO-Revision-Date: 2025-10-21 20:02+0300\n"
"POT-Creation-Date: 2025-10-27 11:15+0200\n"
"PO-Revision-Date: 2025-10-27 11:15+0200\n"
"Last-Translator: divocat <divocatt@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -36,23 +36,27 @@ msgstr ""
msgid "Active Connections"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:117
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:106
msgid "Additional marking rules found"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
msgid "Applicable for SOCKS and Shadowsocks proxy"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:356
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:420
msgid "At least one valid domain must be specified. Comments-only content is not allowed."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:501
msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed."
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:43
msgid "Available actions"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:65
msgid "Bootsrap DNS"
msgstr ""
@@ -60,48 +64,47 @@ msgstr ""
msgid "Bootstrap DNS server"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:58
msgid "Browser is not using FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:80
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57
msgid "Browser is using FakeIP correctly"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:322
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
msgid "Cache File Path"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
msgid "Cache file path cannot be empty"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:26
msgid "Cannot receive DNS checks result"
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25
msgid "Cannot receive checks result"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:27
msgid "Cannot receive nftables checks result"
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13
msgid "Checking, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:24
msgid "Cannot receive Sing-box checks result"
#: src/podkop/tabs/diagnostic/helpers/getCheckTitle.ts:2
msgid "checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:14
msgid "Checking dns, please wait"
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:26
msgid "Checks failed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:14
msgid "Checking FakeIP, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:12
msgid "Checking nftables, please wait"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:12
msgid "Checking sing-box, please wait"
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:13
msgid "Checks passed"
msgstr ""
#: src/validators/validateSubnet.ts:33
@@ -112,11 +115,11 @@ msgstr ""
msgid "Close"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:275
msgid "Community Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:309
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
msgid "Config File Path"
msgstr ""
@@ -152,15 +155,15 @@ msgstr ""
msgid "Dashboard currently unavailable"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:215
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222
msgid "Delay in milliseconds before reloading podkop after interface UP"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:229
msgid "Delay value cannot be empty"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:89
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:82
msgid "DHCP has DNS server"
msgstr ""
@@ -172,42 +175,34 @@ msgstr ""
msgid "Disable autostart"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:239
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
msgid "Disable QUIC"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:240
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:302
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:382
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:366
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:446
msgid "Disabled"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:14
msgid "DNS checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:64
msgid "DNS checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:84
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:77
msgid "DNS on router"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:243
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15
msgid "DNS over HTTPS (DoH)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:180
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:244
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16
msgid "DNS over TLS (DoT)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:240
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12
msgid "DNS Protocol Type"
msgstr ""
@@ -216,7 +211,7 @@ msgstr ""
msgid "DNS Rewrite TTL"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:189
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:253
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24
msgid "DNS Server"
msgstr ""
@@ -225,11 +220,15 @@ msgstr ""
msgid "DNS server address cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:26
msgid "Do not panic, everything can be fixed, just..."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:230
msgid "Domain Resolver"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:300
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
msgid "Dont Touch My DHCP!"
msgstr ""
@@ -242,24 +241,21 @@ msgstr ""
msgid "Download"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:262
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
msgid "Download Lists via Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:271
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
msgid "Download Lists via specific proxy section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:263
msgid "Downloading all lists via main Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:272
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
msgid "Downloading all lists via specific Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:303
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:383
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:367
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:447
msgid "Dynamic List"
msgstr ""
@@ -267,11 +263,11 @@ msgstr ""
msgid "Enable autostart"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:231
msgid "Enable built-in DNS resolver for domains handled by this section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:575
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:639
msgid "Enable Mixed Proxy"
msgstr ""
@@ -279,11 +275,11 @@ msgstr ""
msgid "Enable Output Network Interface"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:640
msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:230
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:237
msgid "Enable YACD"
msgstr ""
@@ -291,23 +287,39 @@ msgstr ""
msgid "Enter complete outbound configuration in JSON format"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:402
msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:376
msgid "Enter domain names without protocols, e.g. example.com or sub.example.com"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:456
msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:358
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:114
msgid "Every 1 minute"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:115
msgid "Every 3 minutes"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:113
msgid "Every 30 seconds"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:116
msgid "Every 5 minutes"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
msgid "Exclude NTP"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:359
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
msgstr ""
@@ -315,27 +327,21 @@ msgstr ""
msgid "Failed to copy!"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:29
msgid "FakeIP checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57
msgid "FakeIP checks failed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51
msgid "FakeIP checks partially passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:44
msgid "FakeIP checks passed"
#: src/podkop/tabs/diagnostic/initController.ts:227
#: src/podkop/tabs/diagnostic/initController.ts:231
#: src/podkop/tabs/diagnostic/initController.ts:261
#: src/podkop/tabs/diagnostic/initController.ts:265
#: src/podkop/tabs/diagnostic/initController.ts:299
#: src/podkop/tabs/diagnostic/initController.ts:303
msgid "Failed to execute!"
msgstr ""
#: src/podkop/methods/custom/getDashboardSections.ts:117
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
msgid "Fastest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:614
msgid "Fully Routed IPs"
msgstr ""
@@ -343,7 +349,7 @@ msgstr ""
msgid "Get global check"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:218
#: src/podkop/tabs/diagnostic/initController.ts:222
msgid "Global check"
msgstr ""
@@ -351,19 +357,19 @@ msgstr ""
msgid "HTTP error"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:182
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:189
msgid "Interface Monitoring"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:214
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:221
msgid "Interface Monitoring Delay"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:183
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:190
msgid "Interface monitoring for Bad WAN"
msgstr ""
#: src/validators/validateDns.ts:20
#: src/validators/validateDns.ts:23
msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH"
msgstr ""
@@ -380,7 +386,7 @@ msgstr ""
msgid "Invalid IP address"
msgstr ""
#: src/validators/validateOutboundJson.ts:19
#: src/validators/validateOutboundJson.ts:9
msgid "Invalid JSON format"
msgstr ""
@@ -476,11 +482,12 @@ msgstr ""
msgid "Invalid Trojan URL: parsing failed"
msgstr ""
#: src/validators/validateUrl.ts:18
#: src/validators/validateUrl.ts:8
#: src/validators/validateUrl.ts:31
msgid "Invalid URL format"
msgstr ""
#: src/validators/validateVlessUrl.ts:109
#: src/validators/validateVlessUrl.ts:110
msgid "Invalid VLESS URL: parsing failed"
msgstr ""
@@ -488,23 +495,27 @@ msgstr ""
msgid "IP address 0.0.0.0 is not allowed"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:404
#: src/podkop/tabs/diagnostic/helpers/getMeta.ts:20
msgid "Issues detected"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:453
msgid "Latest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:250
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
msgid "List Update Frequency"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:522
msgid "Local Domain Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:545
msgid "Local Subnet Lists"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:79
#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72
msgid "Main DNS"
msgstr ""
@@ -512,31 +523,23 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:586
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:650
msgid "Mixed Proxy Port"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:191
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:198
msgid "Monitored Interfaces"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:140
msgid "Must be a number in the range of 50 - 1000"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:184
msgid "Network Interface"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:24
msgid "Nftables checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:75
msgid "Nftables checks partially passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74
msgid "Nftables checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:116
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105
msgid "No other marking rules found"
msgstr ""
@@ -544,10 +547,17 @@ msgstr ""
msgid "Not implement yet"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:75
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:100
msgid "Not responding"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:55
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:63
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:71
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:79
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87
msgid "Not running"
msgstr ""
@@ -563,11 +573,7 @@ msgstr ""
msgid "Outbound Configuration"
msgstr ""
#: src/validators/validateOutboundJson.ts:11
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:394
#: src/podkop/tabs/diagnostic/initController.ts:443
msgid "Outdated"
msgstr ""
@@ -579,18 +585,26 @@ msgstr ""
msgid "Path cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:340
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
msgid "Path must be absolute (start with /)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
msgid "Path must contain at least one directory (like /tmp/cache.db)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:344
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
msgid "Path must end with cache.db"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135
msgid "Pending"
msgstr ""
#: src/podkop/tabs/dashboard/initController.ts:340
msgid "Podkop"
msgstr ""
@@ -599,7 +613,7 @@ msgstr ""
msgid "Podkop Settings"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:301
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
msgid "Podkop will not modify your DHCP configuration"
msgstr ""
@@ -607,30 +621,23 @@ msgstr ""
msgid "Proxy Configuration URL"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:89
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:66
msgid "Proxy traffic is not routed via FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:88
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:65
msgid "Proxy traffic is routed via FakeIP"
msgstr ""
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:103
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:111
#: src/podkop/tabs/diagnostic/diagnostic.store.ts:119
msgid "Queued"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:309
msgid "Regional options cannot be used together"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:568
msgid "Remote Domain Lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:591
msgid "Remote Subnet Lists"
msgstr ""
@@ -638,39 +645,39 @@ msgstr ""
msgid "Restart podkop"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:74
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51
msgid "Router DNS is not routed through sing-box"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:73
#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:50
msgid "Router DNS is routed through sing-box"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:369
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
msgid "Routing Excluded IPs"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:90
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:79
msgid "Rules mangle counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:85
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74
msgid "Rules mangle exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:100
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:89
msgid "Rules mangle output counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:95
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:84
msgid "Rules mangle output exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:110
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:99
msgid "Rules proxy counters"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:94
msgid "Rules proxy exist"
msgstr ""
@@ -678,7 +685,7 @@ msgstr ""
msgid "Run Diagnostic"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:328
msgid "Russia inside restrictions"
msgstr ""
@@ -686,7 +693,7 @@ msgstr ""
msgid "Sections"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:276
msgid "Select a predefined list for routing"
msgstr ""
@@ -698,7 +705,7 @@ msgstr ""
msgid "Select DNS protocol to use"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:251
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
msgid "Select how often the domain or subnet lists are updated automatically"
msgstr ""
@@ -706,32 +713,32 @@ msgstr ""
msgid "Select how to configure the proxy"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:185
msgid "Select network interface for VPN connection"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:254
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25
msgid "Select or enter DNS server address"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:323
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:310
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:241
msgid "Select the DNS protocol type for the domain resolver"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:364
msgid "Select the list type for adding custom domains"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:444
msgid "Select the list type for adding custom subnets"
msgstr ""
@@ -743,7 +750,7 @@ msgstr ""
msgid "Select the network interface to which the traffic will originate"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:192
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:199
msgid "Select the WAN interfaces to be monitored"
msgstr ""
@@ -755,7 +762,7 @@ msgstr ""
msgid "Settings"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:278
#: src/podkop/tabs/diagnostic/initController.ts:290
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116
msgid "Show sing-box config"
msgstr ""
@@ -764,60 +771,52 @@ msgstr ""
msgid "Sing-box"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:86
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:77
msgid "Sing-box autostart disabled"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/contstants.ts:19
msgid "Sing-box checks"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:66
msgid "Sing-box checks passed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:71
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:62
msgid "Sing-box installed"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:96
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:87
msgid "Sing-box listening ports"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:91
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:82
msgid "Sing-box process running"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:81
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:72
msgid "Sing-box service exist"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:76
msgid "Sing-box version >= 1.12.4"
#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:67
msgid "Sing-box version is compatible (newer than 1.12.4)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89
msgid "Source Network Interface"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
msgid "Specify a local IP address to be excluded from routing"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:615
msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:569
msgid "Specify remote URLs to download and use domain lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:592
msgid "Specify remote URLs to download and use subnet lists"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:459
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:482
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:523
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:546
msgid "Specify the path to the list file located on the router filesystem"
msgstr ""
@@ -837,7 +836,11 @@ msgstr ""
msgid "System info"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:80
#: src/podkop/tabs/diagnostic/partials/renderSystemInfo.ts:21
msgid "System information"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:69
msgid "Table exist"
msgstr ""
@@ -845,11 +848,11 @@ msgstr ""
msgid "Test latency"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:368
msgid "Text List"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:448
msgid "Text List (comma/space/newline separated)"
msgstr ""
@@ -857,6 +860,18 @@ msgstr ""
msgid "The DNS server used to look up the IP address of an upstream DNS server"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111
msgid "The interval between connectivity tests"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:124
msgid "The maximum difference in response times (ms) allowed when comparing servers"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:147
msgid "The URL used to test server connectivity"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69
msgid "Time in seconds for DNS record caching (default: 60)"
msgstr ""
@@ -869,6 +884,10 @@ msgstr ""
msgid "Traffic Total"
msgstr ""
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:25
msgid "Troubleshooting"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:80
msgid "TTL must be a positive number"
msgstr ""
@@ -877,22 +896,22 @@ msgstr ""
msgid "TTL value cannot be empty"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17
msgid "UDP (Unprotected DNS)"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:174
msgid "UDP over TCP"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:34
#: src/podkop/tabs/diagnostic/initController.ts:35
#: src/podkop/tabs/diagnostic/initController.ts:36
#: src/podkop/tabs/diagnostic/initController.ts:37
#: src/podkop/tabs/diagnostic/initController.ts:38
#: src/podkop/tabs/diagnostic/initController.ts:39
#: src/podkop/tabs/diagnostic/initController.ts:373
#: src/podkop/tabs/diagnostic/initController.ts:40
#: src/podkop/tabs/diagnostic/initController.ts:41
#: src/podkop/tabs/diagnostic/initController.ts:42
#: src/podkop/tabs/diagnostic/initController.ts:43
#: src/podkop/tabs/diagnostic/initController.ts:417
msgid "unknown"
msgstr ""
@@ -905,11 +924,11 @@ msgstr ""
msgid "Uplink"
msgstr ""
#: src/validators/validateProxyUrl.ts:27
#: src/validators/validateProxyUrl.ts:29
msgid "URL must start with vless://, ss://, trojan://, or socks4/5://"
msgstr ""
#: src/validators/validateUrl.ts:13
#: src/validators/validateUrl.ts:17
msgid "URL must use one of the following protocols:"
msgstr ""
@@ -917,65 +936,81 @@ msgstr ""
msgid "URLTest"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110
msgid "URLTest Check Interval"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:87
msgid "URLTest Proxy Links"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:146
msgid "URLTest Testing URL"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:123
msgid "URLTest Tolerance"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:363
msgid "User Domain List Type"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:375
msgid "User Domains"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:337
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:401
msgid "User Domains List"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:443
msgid "User Subnet List Type"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:455
msgid "User Subnets"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:417
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481
msgid "User Subnets List"
msgstr ""
#: src/validators/validateDns.ts:11
#: src/validators/validateDns.ts:15
#: src/validators/validateDns.ts:14
#: src/validators/validateDns.ts:18
#: src/validators/validateDomain.ts:13
#: src/validators/validateDomain.ts:30
#: src/validators/validateIp.ts:8
#: src/validators/validateOutboundJson.ts:17
#: src/validators/validateOutboundJson.ts:7
#: src/validators/validatePath.ts:16
#: src/validators/validateShadowsocksUrl.ts:95
#: src/validators/validateSocksUrl.ts:80
#: src/validators/validateSubnet.ts:38
#: src/validators/validateTrojanUrl.ts:59
#: src/validators/validateUrl.ts:16
#: src/validators/validateVlessUrl.ts:107
#: src/validators/validateUrl.ts:28
#: src/validators/validateVlessUrl.ts:108
msgid "Valid"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:370
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:449
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:434
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:513
msgid "Validation errors:"
msgstr ""
#: src/podkop/tabs/diagnostic/initController.ts:248
#: src/podkop/tabs/diagnostic/initController.ts:256
#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107
msgid "View logs"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247
#: src/podkop/tabs/diagnostic/partials/renderWikiDisclaimer.ts:31
msgid "Visit Wiki"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:330
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
msgstr ""

View File

@@ -627,9 +627,12 @@ configure_outbound_handler() {
urltest)
log "Detected proxy configuration type: urltest" "debug"
local urltest_proxy_links udp_over_tcp i urltest_tag selector_tag outbound_tag outbound_tags \
urltest_outbounds selector_outbounds
urltest_outbounds selector_outbounds urltest_check_interval urltest_tolerance urltest_testing_url
config_get urltest_proxy_links "$section" "urltest_proxy_links"
config_get udp_over_tcp "$section" "enable_udp_over_tcp"
config_get urltest_check_interval "$section" "urltest_check_interval" "3m"
config_get urltest_tolerance "$section" "urltest_tolerance" 50
config_get urltest_testing_url "$section" "urltest_testing_url" "https://www.gstatic.com/generate_204"
if [ -z "$urltest_proxy_links" ]; then
log "URLTest proxy links is not set. Aborted." "fatal"
@@ -652,7 +655,8 @@ configure_outbound_handler() {
selector_tag="$(get_outbound_tag_by_section "$section")"
urltest_outbounds="$(comma_string_to_json_array "$outbound_tags")"
selector_outbounds="$(comma_string_to_json_array "$outbound_tags,$urltest_tag")"
config="$(sing_box_cm_add_urltest_outbound "$config" "$urltest_tag" "$urltest_outbounds")"
config="$(sing_box_cm_add_urltest_outbound "$config" "$urltest_tag" "$urltest_outbounds" \
"$urltest_testing_url" "$urltest_check_interval" "$urltest_tolerance")"
config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds" "$urltest_tag")"
;;
*)
@@ -767,7 +771,7 @@ sing_box_configure_route() {
configure_common_reject_route_rule
local routing_excluded_ips
config_get_bool routing_excluded_ips "settings" "routing_excluded_ips"
config_get routing_excluded_ips "settings" "routing_excluded_ips"
if [ -n "$routing_excluded_ips" ]; then
rule_tag="$(gen_id)"
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$SB_TPROXY_INBOUND_TAG" "$SB_DIRECT_OUTBOUND_TAG")
@@ -1028,7 +1032,7 @@ import_local_domain_or_subnet_list() {
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array" ;;
subnets)
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$items"
nft_add_set_elements_from_file_chunked "$filepath" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
;;
esac
}
@@ -1209,7 +1213,7 @@ import_community_service_subnet_list_handler() {
*) return 0 ;;
esac
local tmpfile http_proxy_address subnets
local tmpfile http_proxy_address
tmpfile=$(mktemp)
http_proxy_address="$(get_service_proxy_address)"
@@ -1220,14 +1224,13 @@ import_community_service_subnet_list_handler() {
return 1
fi
subnets="$(parse_domain_or_subnet_file_to_comma_string "$tmpfile" "subnets")"
rm -f "$tmpfile"
if [ "$service" = "discord" ]; then
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_DISCORD_SET_NAME" "$subnets"
nft_add_set_elements_from_file_chunked "$tmpfile" "$NFT_TABLE_NAME" "$NFT_DISCORD_SET_NAME"
else
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$subnets"
nft_add_set_elements_from_file_chunked "$tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
fi
rm -f "$tmpfile"
}
import_domains_from_remote_domain_lists() {
@@ -1309,8 +1312,8 @@ import_domains_or_subnets_from_remote_file() {
return 1
fi
convert_crlf_to_lf "$tmpfile"
items="$(parse_domain_or_subnet_file_to_comma_string "$tmpfile" "$type")"
rm -f "$tmpfile"
if [ -z "$items" ]; then
log "No valid $type found in $url" "warn"
@@ -1325,33 +1328,36 @@ import_domains_or_subnets_from_remote_file() {
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array" ;;
subnets)
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$items"
nft_add_set_elements_from_file_chunked "$tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
;;
esac
rm -f "$tmpfile"
}
import_subnets_from_remote_json_file() {
local url="$1"
local tmpfile subnets http_proxy_address
tmpfile="$(mktemp)"
local json_tmpfile subnets_tmpfile http_proxy_address
json_tmpfile="$(mktemp)"
subnets_tmpfile="$(mktemp)"
http_proxy_address="$(get_service_proxy_address)"
download_to_stream "$url" "$http_proxy_address" | jq -r '.rules[].ip_cidr[]?' > "$tmpfile"
download_to_file "$url" "$json_tmpfile" "$http_proxy_address"
if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
if [ $? -ne 0 ] || [ ! -s "$json_tmpfile" ]; then
log "Download $url list failed" "error"
return 1
fi
subnets="$(parse_domain_or_subnet_file_to_comma_string "$tmpfile" "subnets")"
rm -f "$tmpfile"
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$subnets"
extract_ip_cidr_from_json_ruleset_to_file "$json_tmpfile" "$subnets_tmpfile"
nft_add_set_elements_from_file_chunked "$subnets_tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
rm -f "$json_tmpfile" "$subnets_tmpfile"
}
import_subnets_from_remote_srs_file() {
local url="$1"
local binary_tmpfile json_tmpfile subnets_tmpfile subnets http_proxy_address
local binary_tmpfile json_tmpfile subnets_tmpfile http_proxy_address
binary_tmpfile="$(mktemp)"
json_tmpfile="$(mktemp)"
subnets_tmpfile="$(mktemp)"
@@ -1369,10 +1375,9 @@ import_subnets_from_remote_srs_file() {
return 1
fi
jq -r '.rules[].ip_cidr[]' "$json_tmpfile" > "$subnets_tmpfile"
subnets="$(parse_domain_or_subnet_file_to_comma_string "$subnets_tmpfile" "subnets")"
extract_ip_cidr_from_json_ruleset_to_file "$json_tmpfile" "$subnets_tmpfile"
nft_add_set_elements_from_file_chunked "$subnets_tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
rm -f "$binary_tmpfile" "$json_tmpfile" "$subnets_tmpfile"
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$subnets"
}
## Support functions
@@ -1466,6 +1471,46 @@ nft_list_all_traffic_from_ip() {
fi
}
nft_add_set_elements_from_file_chunked() {
local filepath="$1"
local nft_table_name="$2"
local nft_set_name="$3"
local chunk_size="${4:-5000}"
local array count
count=0
while IFS= read -r line; do
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -z "$line" ] && continue
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
continue
fi
if [ -z "$array" ]; then
array="$line"
else
array="$array,$line"
fi
count=$((count + 1))
if [ "$count" = "$chunk_size" ]; then
log "Adding $count elements to nft set $nft_set_name" "debug"
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
array=""
count=0
fi
done < "$filepath"
if [ -n "$array" ]; then
log "Adding $count elements to nft set $nft_set_name" "debug"
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
fi
}
# Diagnotics
check_proxy() {
local sing_box_config_path
@@ -1684,16 +1729,10 @@ show_config() {
tmp_config=$(mktemp)
sed -e 's/\(option proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(vless:\/\/[^@]*@\)/vless:\/\/MASKED@/g' \
-e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \
-e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \
-e 's/\(sid=[^&]*\)/sid=MASKED/g' \
-e 's/\(option dns_server '\''[^'\'']*\.dns\.nextdns\.io'\''\)/option dns_server '\''MASKED.dns.nextdns.io'\''/g' \
-e "s|\(option dns_server 'dns\.nextdns\.io\)/[^']*|\1/MASKED|" \
-e '/option outbound_json/,/^}/c\ option outbound_json '\''MASKED'\''' \
-e 's/\(list urltest_proxy_links\).*/\1 '\''MASKED'\''/g' \
-e "s@\\(option dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
-e "s@\\(option domain_resolver_dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
"$PODKOP_CONFIG" > "$tmp_config"
cat "$tmp_config"
@@ -2279,9 +2318,9 @@ global_check() {
fi
if [ "$sing_box_version_ok" -eq 1 ]; then
print_global "✅ Sing-box version >= 1.12.4"
print_global "✅ Sing-box version is compatible (newer than 1.12.4)"
else
print_global "❌ Sing-box version >= 1.12.4"
print_global "❌ Sing-box version is not compatible (older than 1.12.4)"
fi
if [ "$sing_box_service_exist" -eq 1 ]; then

View File

@@ -268,25 +268,6 @@ migration_rename_config_key() {
fi
}
# Download URL content directly
download_to_stream() {
local url="$1"
local http_proxy_address="$2"
local retries="${3:-3}"
local wait="${4:-2}"
for attempt in $(seq 1 "$retries"); do
if [ -n "$http_proxy_address" ]; then
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" wget -qO- "$url" | sed 's/\r$//' && break
else
wget -qO- "$url" | sed 's/\r$//' && break
fi
log "Attempt $attempt/$retries to download $url failed" "warn"
sleep "$wait"
done
}
# Download URL to file
download_to_file() {
local url="$1"
@@ -305,10 +286,17 @@ download_to_file() {
log "Attempt $attempt/$retries to download $url failed" "warn"
sleep "$wait"
done
}
# Converts Windows-style line endings (CRLF) to Unix-style (LF)
convert_crlf_to_lf() {
local filepath="$1"
if grep -q $'\r' "$filepath"; then
log "Downloaded file has Windows line endings (CRLF). Converting to Unix (LF)"
sed -i 's/\r$//' "$filepath"
log "File '$filepath' contains CRLF line endings. Converting to LF..." "debug"
local tmpfile
tmpfile=$(mktemp)
tr -d '\r' < "$filepath" > "$tmpfile" && mv "$tmpfile" "$filepath" || rm -f "$tmpfile"
fi
}
@@ -400,3 +388,17 @@ parse_domain_or_subnet_file_to_comma_string() {
echo "$result"
}
# Extracts all ip_cidr entries from a JSON ruleset file and writes them to an output file.
extract_ip_cidr_from_json_ruleset_to_file() {
local json_file="$1"
local output_file="$2"
if [ ! -f "$json_file" ]; then
log "JSON file not found: $json_file" "error"
return 1
fi
log "Extracting ip_cidr entries from $json_file to $output_file" "debug"
jq -r '.rules[].ip_cidr[]' "$json_file" > "$output_file"
}