diff --git a/fe-app-podkop/distribute-locales.js b/fe-app-podkop/distribute-locales.js new file mode 100644 index 0000000..0bc27b2 --- /dev/null +++ b/fe-app-podkop/distribute-locales.js @@ -0,0 +1,38 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const sourceDir = path.resolve(__dirname, 'locales'); +const targetRoot = path.resolve(__dirname, '../luci-app-podkop/po'); + +async function main() { + const files = await fs.readdir(sourceDir); + + for (const file of files) { + const filePath = path.join(sourceDir, file); + + if (file === 'podkop.pot') { + const potTarget = path.join(targetRoot, 'templates', 'podkop.pot'); + await fs.mkdir(path.dirname(potTarget), { recursive: true }); + await fs.copyFile(filePath, potTarget); + console.log(`✅ Copied POT: ${filePath} → ${potTarget}`); + } + + const match = file.match(/^podkop\.([a-zA-Z_]+)\.po$/); + if (match) { + const lang = match[1]; + const poTarget = path.join(targetRoot, lang, 'podkop.po'); + await fs.mkdir(path.dirname(poTarget), { recursive: true }); + await fs.copyFile(filePath, poTarget); + console.log(`✅ Copied ${lang.toUpperCase()}: ${filePath} → ${poTarget}`); + } + } +} + +main().catch((err) => { + console.error('❌ Ошибка при распространении переводов:', err); + process.exit(1); +}); diff --git a/fe-app-podkop/extract-calls.js b/fe-app-podkop/extract-calls.js new file mode 100644 index 0000000..4bc88d1 --- /dev/null +++ b/fe-app-podkop/extract-calls.js @@ -0,0 +1,93 @@ +import fg from 'fast-glob'; +import fs from 'fs/promises'; +import path from 'path'; + +const outputFile = 'locales/calls.json'; + +const tsSearchGlob = 'src/**/*.ts'; +const jsSearchGlob = '../luci-app-podkop/htdocs/luci-static/resources/view/podkop/**/*.js'; + +function extractAllUnderscoreCallsFromContent(content) { + const results = []; + let index = 0; + + while (index < content.length) { + const start = content.indexOf('_(', index); + if (start === -1) break; + + let i = start + 2; + let depth = 1; + + while (i < content.length && depth > 0) { + if (content[i] === '(') depth++; + else if (content[i] === ')') depth--; + i++; + } + + const raw = content.slice(start, i); + results.push({ raw, index: start }); + index = i; + } + + return results; +} + +function getLineNumber(content, charIndex) { + return content.slice(0, charIndex).split('\n').length; +} + +function extractKey(call) { + const match = call.match(/^_\(\s*(['"`])((?:\\\1|.)*?)\1\s*\)$/); + return match ? match[2].trim() : null; +} + +function normalizeCall(call) { + return call + .replace(/\s*\n\s*/g, ' ') + .replace(/\s+/g, ' ') + .replace(/\(\s+/g, '(') + .replace(/\s+\)/g, ')') + .replace(/,\s*\)$/, ')') + .trim(); +} + +async function extractAllUnderscoreCallsWithLocations() { + const files = [ + ...(await fg(tsSearchGlob, { ignore: ['**/*test.ts'], absolute: true })), + ...(await fg(jsSearchGlob, { ignore: ['**/main.js'], absolute: true })), + ]; + + const callMap = new Map(); + + for (const file of files) { + const content = await fs.readFile(file, 'utf8'); + const relativePath = path.relative(process.cwd(), file); + const extracted = extractAllUnderscoreCallsFromContent(content); + + for (const { raw, index } of extracted) { + const line = getLineNumber(content, index); + const location = `${relativePath}:${line}`; + + const normalized = normalizeCall(raw); + const key = extractKey(normalized); + + if (!callMap.has(normalized)) { + callMap.set(normalized, { + call: normalized, + key: key ?? '', + places: [], + }); + } + + callMap.get(normalized).places.push(location); + } + } + + const result = [...callMap.values()]; + await fs.mkdir(path.dirname(outputFile), { recursive: true }); + await fs.writeFile(outputFile, JSON.stringify(result, null, 2), 'utf8'); + + console.log(`✅ Найдено ${result.length} уникальных вызовов _(...). Сохранено в ${outputFile}`); +} + +extractAllUnderscoreCallsWithLocations().catch(console.error); diff --git a/fe-app-podkop/generate-po.js b/fe-app-podkop/generate-po.js new file mode 100644 index 0000000..234d6b8 --- /dev/null +++ b/fe-app-podkop/generate-po.js @@ -0,0 +1,113 @@ +import fs from 'fs/promises'; +import { execSync } from 'child_process'; + +const lang = process.argv[2]; +if (!lang) { + console.error('❌ Укажи язык, например: node generate-po.js ru'); + process.exit(1); +} + +const callsPath = 'locales/calls.json'; +const poPath = `locales/podkop.${lang}.po`; + +function getGitUser() { + try { + return execSync('git config user.name').toString().trim(); + } catch { + return 'Automatically generated'; + } +} + +function getHeader(lang) { + const now = new Date(); + const date = now.toISOString().split('T')[0]; + const time = now.toTimeString().split(' ')[0].slice(0, 5); + const tzOffset = (() => { + const offset = -now.getTimezoneOffset(); + const sign = offset >= 0 ? '+' : '-'; + const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0'); + const minutes = String(Math.abs(offset) % 60).padStart(2, '0'); + return `${sign}${hours}${minutes}`; + })(); + + const translator = getGitUser(); + const pluralForms = lang === 'ru' + ? 'nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);' + : 'nplurals=2; plural=(n != 1);'; + + return [ + `# ${lang.toUpperCase()} translations for PODKOP package.`, + `# Copyright (C) ${now.getFullYear()} THE PODKOP'S COPYRIGHT HOLDER`, + `# This file is distributed under the same license as the PODKOP package.`, + `# ${translator}, ${now.getFullYear()}.`, + '#', + 'msgid ""', + 'msgstr ""', + `"Project-Id-Version: PODKOP\\n"`, + `"Report-Msgid-Bugs-To: \\n"`, + `"POT-Creation-Date: ${date} ${time}${tzOffset}\\n"`, + `"PO-Revision-Date: ${date} ${time}${tzOffset}\\n"`, + `"Last-Translator: ${translator}\\n"`, + `"Language-Team: none\\n"`, + `"Language: ${lang}\\n"`, + `"MIME-Version: 1.0\\n"`, + `"Content-Type: text/plain; charset=UTF-8\\n"`, + `"Content-Transfer-Encoding: 8bit\\n"`, + `"Plural-Forms: ${pluralForms}\\n"`, + '', + ]; +} + +function parsePo(content) { + const lines = content.split('\n'); + const translations = new Map(); + let msgid = null; + let msgstr = null; + for (const line of lines) { + if (line.startsWith('msgid ')) { + msgid = JSON.parse(line.slice(6)); + } else if (line.startsWith('msgstr ') && msgid !== null) { + msgstr = JSON.parse(line.slice(7)); + translations.set(msgid, msgstr); + msgid = null; + msgstr = null; + } + } + return translations; +} + +function escapePoString(str) { + return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +} + +async function generatePo() { + const [callsRaw, oldPoRaw] = await Promise.all([ + fs.readFile(callsPath, 'utf8'), + fs.readFile(poPath, 'utf8').catch(() => ''), + ]); + + const calls = JSON.parse(callsRaw); + const oldTranslations = parsePo(oldPoRaw); + const header = getHeader(lang); + + const body = calls + .map(({ key }) => { + const msgid = key; + const msgstr = oldTranslations.get(msgid) || ''; + return [ + `msgid "${escapePoString(msgid)}"`, + `msgstr "${escapePoString(msgstr)}"`, + '' + ].join('\n'); + }) + .join('\n'); + + const finalPo = header.join('\n') + '\n' + body; + + await fs.writeFile(poPath, finalPo, 'utf8'); + console.log(`✅ Файл ${poPath} успешно сгенерирован. Переведено ${[...oldTranslations.keys()].length}/${calls.length}`); +} + +generatePo().catch((err) => { + console.error('Ошибка генерации PO файла:', err); +}); diff --git a/fe-app-podkop/generate-pot.js b/fe-app-podkop/generate-pot.js new file mode 100644 index 0000000..b739044 --- /dev/null +++ b/fe-app-podkop/generate-pot.js @@ -0,0 +1,73 @@ +import fs from 'fs/promises'; +import { execSync } from 'child_process'; + +const inputFile = 'locales/calls.json'; +const outputFile = 'locales/podkop.pot'; +const projectId = 'PODKOP'; + +function getGitUser() { + const name = execSync('git config user.name').toString().trim(); + const email = execSync('git config user.email').toString().trim(); + return { name, email }; +} + +function getPotHeader({ name, email }) { + const now = new Date(); + const date = now.toISOString().replace('T', ' ').slice(0, 16); + const offset = -now.getTimezoneOffset(); + const sign = offset >= 0 ? '+' : '-'; + const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0'); + const minutes = String(Math.abs(offset) % 60).padStart(2, '0'); + const timezone = `${sign}${hours}${minutes}`; + + return [ + '# SOME DESCRIPTIVE TITLE.', + `# Copyright (C) ${now.getFullYear()} THE PACKAGE'S COPYRIGHT HOLDER`, + `# This file is distributed under the same license as the ${projectId} package.`, + `# ${name} <${email}>, ${now.getFullYear()}.`, + '#, fuzzy', + 'msgid ""', + 'msgstr ""', + `"Project-Id-Version: ${projectId}\\n"`, + `"Report-Msgid-Bugs-To: \\n"`, + `"POT-Creation-Date: ${date}${timezone}\\n"`, + `"PO-Revision-Date: ${date}${timezone}\\n"`, + `"Last-Translator: ${name} <${email}>\\n"`, + `"Language-Team: LANGUAGE \\n"`, + `"Language: \\n"`, + `"MIME-Version: 1.0\\n"`, + `"Content-Type: text/plain; charset=UTF-8\\n"`, + `"Content-Transfer-Encoding: 8bit\\n"`, + '', + ].join('\n'); +} + +function escapePoString(str) { + return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +} + +function generateEntry(item) { + const locations = item.places.map(loc => `#: ${loc}`).join('\n'); + const msgid = escapePoString(item.key); + return [ + locations, + `msgid "${msgid}"`, + `msgstr ""`, + '' + ].join('\n'); +} + +async function generatePot() { + const gitUser = getGitUser(); + const raw = await fs.readFile(inputFile, 'utf8'); + const entries = JSON.parse(raw); + + const header = getPotHeader(gitUser); + const body = entries.map(generateEntry).join('\n'); + + await fs.writeFile(outputFile, `${header}\n${body}`, 'utf8'); + + console.log(`✅ POT-файл успешно создан: ${outputFile}`); +} + +generatePot().catch(console.error); diff --git a/fe-app-podkop/locales/calls.json b/fe-app-podkop/locales/calls.json new file mode 100644 index 0000000..9f4c445 --- /dev/null +++ b/fe-app-podkop/locales/calls.json @@ -0,0 +1,2570 @@ +[ + { + "call": "_('Successfully copied!')", + "key": "Successfully copied!", + "places": [ + "src/helpers/copyToClipboard.ts:10" + ] + }, + { + "call": "_('Failed to copy!')", + "key": "Failed to copy!", + "places": [ + "src/helpers/copyToClipboard.ts:12" + ] + }, + { + "call": "_('Operation timed out')", + "key": "Operation timed out", + "places": [ + "src/helpers/withTimeout.ts:7" + ] + }, + { + "call": "_('HTTP error')", + "key": "HTTP error", + "places": [ + "src/podkop/api.ts:27" + ] + }, + { + "call": "_('Unknown error')", + "key": "Unknown error", + "places": [ + "src/podkop/api.ts:40" + ] + }, + { + "call": "_('DNS server address cannot be empty')", + "key": "DNS server address cannot be empty", + "places": [ + "src/validators/validateDns.ts:7" + ] + }, + { + "call": "_('Valid')", + "key": "Valid", + "places": [ + "src/validators/validateDns.ts:11", + "src/validators/validateDns.ts:15", + "src/validators/validateDomain.ts:13", + "src/validators/validateDomain.ts:30", + "src/validators/validateIp.ts:8", + "src/validators/validateOutboundJson.ts:17", + "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" + ] + }, + { + "call": "_('Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH')", + "key": "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH", + "places": [ + "src/validators/validateDns.ts:20" + ] + }, + { + "call": "_('Invalid domain address')", + "key": "Invalid domain address", + "places": [ + "src/validators/validateDomain.ts:18", + "src/validators/validateDomain.ts:27" + ] + }, + { + "call": "_('Invalid IP address')", + "key": "Invalid IP address", + "places": [ + "src/validators/validateIp.ts:11" + ] + }, + { + "call": "_('Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields')", + "key": "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields", + "places": [ + "src/validators/validateOutboundJson.ts:11", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:327" + ] + }, + { + "call": "_('Invalid JSON format')", + "key": "Invalid JSON format", + "places": [ + "src/validators/validateOutboundJson.ts:19" + ] + }, + { + "call": "_('Path cannot be empty')", + "key": "Path cannot be empty", + "places": [ + "src/validators/validatePath.ts:7" + ] + }, + { + "call": "_('Invalid path format. Path must start with \"/\" and contain valid characters')", + "key": "Invalid path format. Path must start with \"/\" and contain valid characters", + "places": [ + "src/validators/validatePath.ts:22", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:90" + ] + }, + { + "call": "_('URL must start with vless://, ss://, trojan://, or socks4/5://')", + "key": "URL must start with vless://, ss://, trojan://, or socks4/5://", + "places": [ + "src/validators/validateProxyUrl.ts:27" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: must start with ss://')", + "key": "Invalid Shadowsocks URL: must start with ss://", + "places": [ + "src/validators/validateShadowsocksUrl.ts:8" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: must not contain spaces')", + "key": "Invalid Shadowsocks URL: must not contain spaces", + "places": [ + "src/validators/validateShadowsocksUrl.ts:16" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: missing credentials')", + "key": "Invalid Shadowsocks URL: missing credentials", + "places": [ + "src/validators/validateShadowsocksUrl.ts:27" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: decoded credentials must contain method:password')", + "key": "Invalid Shadowsocks URL: decoded credentials must contain method:password", + "places": [ + "src/validators/validateShadowsocksUrl.ts:37" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: missing method and password separator \":\"')", + "key": "Invalid Shadowsocks URL: missing method and password separator \":\"", + "places": [ + "src/validators/validateShadowsocksUrl.ts:46", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:171" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: missing server address')", + "key": "Invalid Shadowsocks URL: missing server address", + "places": [ + "src/validators/validateShadowsocksUrl.ts:58" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: missing server')", + "key": "Invalid Shadowsocks URL: missing server", + "places": [ + "src/validators/validateShadowsocksUrl.ts:67" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: missing port')", + "key": "Invalid Shadowsocks URL: missing port", + "places": [ + "src/validators/validateShadowsocksUrl.ts:76" + ] + }, + { + "call": "_('Invalid port number. Must be between 1 and 65535')", + "key": "Invalid port number. Must be between 1 and 65535", + "places": [ + "src/validators/validateShadowsocksUrl.ts:85" + ] + }, + { + "call": "_('Invalid Shadowsocks URL: parsing failed')", + "key": "Invalid Shadowsocks URL: parsing failed", + "places": [ + "src/validators/validateShadowsocksUrl.ts:91" + ] + }, + { + "call": "_('Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://')", + "key": "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://", + "places": [ + "src/validators/validateSocksUrl.ts:10" + ] + }, + { + "call": "_('Invalid SOCKS URL: must not contain spaces')", + "key": "Invalid SOCKS URL: must not contain spaces", + "places": [ + "src/validators/validateSocksUrl.ts:19" + ] + }, + { + "call": "_('Invalid SOCKS URL: missing username')", + "key": "Invalid SOCKS URL: missing username", + "places": [ + "src/validators/validateSocksUrl.ts:34" + ] + }, + { + "call": "_('Invalid SOCKS URL: missing host and port')", + "key": "Invalid SOCKS URL: missing host and port", + "places": [ + "src/validators/validateSocksUrl.ts:42" + ] + }, + { + "call": "_('Invalid SOCKS URL: missing hostname or IP')", + "key": "Invalid SOCKS URL: missing hostname or IP", + "places": [ + "src/validators/validateSocksUrl.ts:51" + ] + }, + { + "call": "_('Invalid SOCKS URL: missing port')", + "key": "Invalid SOCKS URL: missing port", + "places": [ + "src/validators/validateSocksUrl.ts:56" + ] + }, + { + "call": "_('Invalid SOCKS URL: invalid port number')", + "key": "Invalid SOCKS URL: invalid port number", + "places": [ + "src/validators/validateSocksUrl.ts:63" + ] + }, + { + "call": "_('Invalid SOCKS URL: invalid host format')", + "key": "Invalid SOCKS URL: invalid host format", + "places": [ + "src/validators/validateSocksUrl.ts:73" + ] + }, + { + "call": "_('Invalid SOCKS URL: parsing failed')", + "key": "Invalid SOCKS URL: parsing failed", + "places": [ + "src/validators/validateSocksUrl.ts:77" + ] + }, + { + "call": "_('Invalid format. Use X.X.X.X or X.X.X.X/Y')", + "key": "Invalid format. Use X.X.X.X or X.X.X.X/Y", + "places": [ + "src/validators/validateSubnet.ts:11" + ] + }, + { + "call": "_('IP address 0.0.0.0 is not allowed')", + "key": "IP address 0.0.0.0 is not allowed", + "places": [ + "src/validators/validateSubnet.ts:18" + ] + }, + { + "call": "_('CIDR must be between 0 and 32')", + "key": "CIDR must be between 0 and 32", + "places": [ + "src/validators/validateSubnet.ts:33" + ] + }, + { + "call": "_('Invalid Trojan URL: must start with trojan://')", + "key": "Invalid Trojan URL: must start with trojan://", + "places": [ + "src/validators/validateTrojanUrl.ts:8" + ] + }, + { + "call": "_('Invalid Trojan URL: must not contain spaces')", + "key": "Invalid Trojan URL: must not contain spaces", + "places": [ + "src/validators/validateTrojanUrl.ts:15" + ] + }, + { + "call": "_('Invalid Trojan URL: parsing failed')", + "key": "Invalid Trojan URL: parsing failed", + "places": [ + "src/validators/validateTrojanUrl.ts:56" + ] + }, + { + "call": "_('URL must use one of the following protocols:')", + "key": "URL must use one of the following protocols:", + "places": [ + "src/validators/validateUrl.ts:13" + ] + }, + { + "call": "_('Invalid URL format')", + "key": "Invalid URL format", + "places": [ + "src/validators/validateUrl.ts:18" + ] + }, + { + "call": "_('Invalid VLESS URL: parsing failed')", + "key": "Invalid VLESS URL: parsing failed", + "places": [ + "src/validators/validateVlessUrl.ts:109" + ] + }, + { + "call": "_('Download')", + "key": "Download", + "places": [ + "src/partials/modal/renderModal.ts:15" + ] + }, + { + "call": "_('Copy')", + "key": "Copy", + "places": [ + "src/partials/modal/renderModal.ts:20" + ] + }, + { + "call": "_('Close')", + "key": "Close", + "places": [ + "src/partials/modal/renderModal.ts:26" + ] + }, + { + "call": "_('Fastest')", + "key": "Fastest", + "places": [ + "src/podkop/methods/custom/getDashboardSections.ts:117" + ] + }, + { + "call": "_('Traffic')", + "key": "Traffic", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:235" + ] + }, + { + "call": "_('Uplink')", + "key": "Uplink", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:237", + "src/podkop/tabs/dashboard/initController.ts:268" + ] + }, + { + "call": "_('Downlink')", + "key": "Downlink", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:238", + "src/podkop/tabs/dashboard/initController.ts:272" + ] + }, + { + "call": "_('Traffic Total')", + "key": "Traffic Total", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:265" + ] + }, + { + "call": "_('System info')", + "key": "System info", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:301" + ] + }, + { + "call": "_('Active Connections')", + "key": "Active Connections", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:304" + ] + }, + { + "call": "_('Memory Usage')", + "key": "Memory Usage", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:308" + ] + }, + { + "call": "_('Services info')", + "key": "Services info", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:337" + ] + }, + { + "call": "_('Podkop')", + "key": "Podkop", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:340" + ] + }, + { + "call": "_('✔ Enabled')", + "key": "✔ Enabled", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:342" + ] + }, + { + "call": "_('✘ Disabled')", + "key": "✘ Disabled", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:343" + ] + }, + { + "call": "_('Sing-box')", + "key": "Sing-box", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:351" + ] + }, + { + "call": "_('✔ Running')", + "key": "✔ Running", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:353" + ] + }, + { + "call": "_('✘ Stopped')", + "key": "✘ Stopped", + "places": [ + "src/podkop/tabs/dashboard/initController.ts:354" + ] + }, + { + "call": "_('Not running')", + "key": "Not running", + "places": [ + "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" + ] + }, + { + "call": "_('Queued')", + "key": "Queued", + "places": [ + "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" + ] + }, + { + "call": "_('unknown')", + "key": "unknown", + "places": [ + "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" + ] + }, + { + "call": "_('Global check')", + "key": "Global check", + "places": [ + "src/podkop/tabs/diagnostic/initController.ts:218" + ] + }, + { + "call": "_('View logs')", + "key": "View logs", + "places": [ + "src/podkop/tabs/diagnostic/initController.ts:248", + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107" + ] + }, + { + "call": "_('Show sing-box config')", + "key": "Show sing-box config", + "places": [ + "src/podkop/tabs/diagnostic/initController.ts:278", + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116" + ] + }, + { + "call": "_('Outdated')", + "key": "Outdated", + "places": [ + "src/podkop/tabs/diagnostic/initController.ts:394" + ] + }, + { + "call": "_('Latest')", + "key": "Latest", + "places": [ + "src/podkop/tabs/diagnostic/initController.ts:404" + ] + }, + { + "call": "_('Dashboard currently unavailable')", + "key": "Dashboard currently unavailable", + "places": [ + "src/podkop/tabs/dashboard/partials/renderSections.ts:19" + ] + }, + { + "call": "_('Test latency')", + "key": "Test latency", + "places": [ + "src/podkop/tabs/dashboard/partials/renderSections.ts:108" + ] + }, + { + "call": "_('Currently unavailable')", + "key": "Currently unavailable", + "places": [ + "src/podkop/tabs/dashboard/partials/renderWidget.ts:22" + ] + }, + { + "call": "_('DNS checks')", + "key": "DNS checks", + "places": [ + "src/podkop/tabs/diagnostic/checks/contstants.ts:14" + ] + }, + { + "call": "_('Sing-box checks')", + "key": "Sing-box checks", + "places": [ + "src/podkop/tabs/diagnostic/checks/contstants.ts:19" + ] + }, + { + "call": "_('Nftables checks')", + "key": "Nftables checks", + "places": [ + "src/podkop/tabs/diagnostic/checks/contstants.ts:24" + ] + }, + { + "call": "_('FakeIP checks')", + "key": "FakeIP checks", + "places": [ + "src/podkop/tabs/diagnostic/checks/contstants.ts:29" + ] + }, + { + "call": "_('Checking dns, please wait')", + "key": "Checking dns, please wait", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:14" + ] + }, + { + "call": "_('Cannot receive DNS checks result')", + "key": "Cannot receive DNS checks result", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:26" + ] + }, + { + "call": "_('DNS checks passed')", + "key": "DNS checks passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:64" + ] + }, + { + "call": "_('Bootsrap DNS')", + "key": "Bootsrap DNS", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72" + ] + }, + { + "call": "_('Main DNS')", + "key": "Main DNS", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:79" + ] + }, + { + "call": "_('DNS on router')", + "key": "DNS on router", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:84" + ] + }, + { + "call": "_('DHCP has DNS server')", + "key": "DHCP has DNS server", + "places": [ + "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:89" + ] + }, + { + "call": "_('Checking FakeIP, please wait')", + "key": "Checking FakeIP, please wait", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:14" + ] + }, + { + "call": "_('FakeIP checks passed')", + "key": "FakeIP checks passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:44" + ] + }, + { + "call": "_('FakeIP checks partially passed')", + "key": "FakeIP checks partially passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51" + ] + }, + { + "call": "_('FakeIP checks failed')", + "key": "FakeIP checks failed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57" + ] + }, + { + "call": "_('Router DNS is routed through sing-box')", + "key": "Router DNS is routed through sing-box", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:73" + ] + }, + { + "call": "_('Router DNS is not routed through sing-box')", + "key": "Router DNS is not routed through sing-box", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:74" + ] + }, + { + "call": "_('Browser is using FakeIP correctly')", + "key": "Browser is using FakeIP correctly", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:80" + ] + }, + { + "call": "_('Browser is not using FakeIP')", + "key": "Browser is not using FakeIP", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:81" + ] + }, + { + "call": "_('Proxy traffic is routed via FakeIP')", + "key": "Proxy traffic is routed via FakeIP", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:88" + ] + }, + { + "call": "_('Proxy traffic is not routed via FakeIP')", + "key": "Proxy traffic is not routed via FakeIP", + "places": [ + "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:89" + ] + }, + { + "call": "_('Checking nftables, please wait')", + "key": "Checking nftables, please wait", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:12" + ] + }, + { + "call": "_('Cannot receive nftables checks result')", + "key": "Cannot receive nftables checks result", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:27" + ] + }, + { + "call": "_('Nftables checks passed')", + "key": "Nftables checks passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74" + ] + }, + { + "call": "_('Nftables checks partially passed')", + "key": "Nftables checks partially passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:75" + ] + }, + { + "call": "_('Table exist')", + "key": "Table exist", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:80" + ] + }, + { + "call": "_('Rules mangle exist')", + "key": "Rules mangle exist", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:85" + ] + }, + { + "call": "_('Rules mangle counters')", + "key": "Rules mangle counters", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:90" + ] + }, + { + "call": "_('Rules mangle output exist')", + "key": "Rules mangle output exist", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:95" + ] + }, + { + "call": "_('Rules mangle output counters')", + "key": "Rules mangle output counters", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:100" + ] + }, + { + "call": "_('Rules proxy exist')", + "key": "Rules proxy exist", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105" + ] + }, + { + "call": "_('Rules proxy counters')", + "key": "Rules proxy counters", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:110" + ] + }, + { + "call": "_('No other marking rules found')", + "key": "No other marking rules found", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:116" + ] + }, + { + "call": "_('Additional marking rules found')", + "key": "Additional marking rules found", + "places": [ + "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:117" + ] + }, + { + "call": "_('Checking sing-box, please wait')", + "key": "Checking sing-box, please wait", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:12" + ] + }, + { + "call": "_('Cannot receive Sing-box checks result')", + "key": "Cannot receive Sing-box checks result", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:24" + ] + }, + { + "call": "_('Sing-box checks passed')", + "key": "Sing-box checks passed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:66" + ] + }, + { + "call": "_('Sing-box installed')", + "key": "Sing-box installed", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:71" + ] + }, + { + "call": "_('Sing-box version >= 1.12.4')", + "key": "Sing-box version >= 1.12.4", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:76" + ] + }, + { + "call": "_('Sing-box service exist')", + "key": "Sing-box service exist", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:81" + ] + }, + { + "call": "_('Sing-box autostart disabled')", + "key": "Sing-box autostart disabled", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:86" + ] + }, + { + "call": "_('Sing-box process running')", + "key": "Sing-box process running", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:91" + ] + }, + { + "call": "_('Sing-box listening ports')", + "key": "Sing-box listening ports", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:96" + ] + }, + { + "call": "_('Restart podkop')", + "key": "Restart podkop", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49" + ] + }, + { + "call": "_('Stop podkop')", + "key": "Stop podkop", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:59" + ] + }, + { + "call": "_('Start podkop')", + "key": "Start podkop", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:69" + ] + }, + { + "call": "_('Disable autostart')", + "key": "Disable autostart", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:79" + ] + }, + { + "call": "_('Enable autostart')", + "key": "Enable autostart", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:89" + ] + }, + { + "call": "_('Get global check')", + "key": "Get global check", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:98" + ] + }, + { + "call": "_('Not implement yet')", + "key": "Not implement yet", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderCheckSection.ts:189" + ] + }, + { + "call": "_('Run Diagnostic')", + "key": "Run Diagnostic", + "places": [ + "src/podkop/tabs/diagnostic/partials/renderRunAction.ts:15" + ] + }, + { + "call": "_(\"Valid\")", + "key": "Valid", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:12", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:23", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:35", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:44", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:47", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:67", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:85", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:122", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:211", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:314", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:332", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:383", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:449" + ] + }, + { + "call": "_(\"Invalid IP address\")", + "key": "Invalid IP address", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:14" + ] + }, + { + "call": "_(\"Invalid domain address\")", + "key": "Invalid domain address", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:27", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:33" + ] + }, + { + "call": "_(\"DNS server address cannot be empty\")", + "key": "DNS server address cannot be empty", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:41" + ] + }, + { + "call": "_(\"Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH\")", + "key": "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:51" + ] + }, + { + "call": "_(\"URL must use one of the following protocols:\")", + "key": "URL must use one of the following protocols:", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:64" + ] + }, + { + "call": "_(\"Invalid URL format\")", + "key": "Invalid URL format", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:69" + ] + }, + { + "call": "_(\"Path cannot be empty\")", + "key": "Path cannot be empty", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:78" + ] + }, + { + "call": "_(\"Invalid format. Use X.X.X.X or X.X.X.X/Y\")", + "key": "Invalid format. Use X.X.X.X or X.X.X.X/Y", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:102" + ] + }, + { + "call": "_(\"IP address 0.0.0.0 is not allowed\")", + "key": "IP address 0.0.0.0 is not allowed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:107" + ] + }, + { + "call": "_(\"CIDR must be between 0 and 32\")", + "key": "CIDR must be between 0 and 32", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:118" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: must start with ss://\")", + "key": "Invalid Shadowsocks URL: must start with ss://", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:139" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: must not contain spaces\")", + "key": "Invalid Shadowsocks URL: must not contain spaces", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:146" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: missing credentials\")", + "key": "Invalid Shadowsocks URL: missing credentials", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:154" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: decoded credentials must contain method:password\")", + "key": "Invalid Shadowsocks URL: decoded credentials must contain method:password", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:162" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: missing server address\")", + "key": "Invalid Shadowsocks URL: missing server address", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:181" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: missing server\")", + "key": "Invalid Shadowsocks URL: missing server", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:188" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: missing port\")", + "key": "Invalid Shadowsocks URL: missing port", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:195" + ] + }, + { + "call": "_(\"Invalid port number. Must be between 1 and 65535\")", + "key": "Invalid port number. Must be between 1 and 65535", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:202" + ] + }, + { + "call": "_(\"Invalid Shadowsocks URL: parsing failed\")", + "key": "Invalid Shadowsocks URL: parsing failed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:208" + ] + }, + { + "call": "_(\"Invalid VLESS URL: parsing failed\")", + "key": "Invalid VLESS URL: parsing failed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:316" + ] + }, + { + "call": "_(\"Invalid JSON format\")", + "key": "Invalid JSON format", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:334" + ] + }, + { + "call": "_(\"Invalid Trojan URL: must start with trojan://\")", + "key": "Invalid Trojan URL: must start with trojan://", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:344" + ] + }, + { + "call": "_(\"Invalid Trojan URL: must not contain spaces\")", + "key": "Invalid Trojan URL: must not contain spaces", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:350" + ] + }, + { + "call": "_(\"Invalid Trojan URL: parsing failed\")", + "key": "Invalid Trojan URL: parsing failed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:381" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://\")", + "key": "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:392" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: must not contain spaces\")", + "key": "Invalid SOCKS URL: must not contain spaces", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:400" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: missing username\")", + "key": "Invalid SOCKS URL: missing username", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:411" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: missing host and port\")", + "key": "Invalid SOCKS URL: missing host and port", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:418" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: missing hostname or IP\")", + "key": "Invalid SOCKS URL: missing hostname or IP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:425" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: missing port\")", + "key": "Invalid SOCKS URL: missing port", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:429" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: invalid port number\")", + "key": "Invalid SOCKS URL: invalid port number", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:435" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: invalid host format\")", + "key": "Invalid SOCKS URL: invalid host format", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:443" + ] + }, + { + "call": "_(\"Invalid SOCKS URL: parsing failed\")", + "key": "Invalid SOCKS URL: parsing failed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:447" + ] + }, + { + "call": "_(\"URL must start with vless://, ss://, trojan://, or socks4/5://\")", + "key": "URL must start with vless://, ss://, trojan://, or socks4/5://", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:468" + ] + }, + { + "call": "_(\"Fastest\")", + "key": "Fastest", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:692" + ] + }, + { + "call": "_(\"HTTP error\")", + "key": "HTTP error", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:864" + ] + }, + { + "call": "_(\"Unknown error\")", + "key": "Unknown error", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:875" + ] + }, + { + "call": "_(\"DNS checks\")", + "key": "DNS checks", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:985" + ] + }, + { + "call": "_(\"Sing-box checks\")", + "key": "Sing-box checks", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:990" + ] + }, + { + "call": "_(\"Nftables checks\")", + "key": "Nftables checks", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:995" + ] + }, + { + "call": "_(\"FakeIP checks\")", + "key": "FakeIP checks", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1000" + ] + }, + { + "call": "_(\"Not running\")", + "key": "Not running", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1048", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1056", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1064", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1072" + ] + }, + { + "call": "_(\"Queued\")", + "key": "Queued", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1084", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1092", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1100", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1108" + ] + }, + { + "call": "_(\"Dashboard currently unavailable\")", + "key": "Dashboard currently unavailable", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1578" + ] + }, + { + "call": "_(\"Test latency\")", + "key": "Test latency", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1654" + ] + }, + { + "call": "_(\"Currently unavailable\")", + "key": "Currently unavailable", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1683" + ] + }, + { + "call": "_(\"Traffic\")", + "key": "Traffic", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2024" + ] + }, + { + "call": "_(\"Uplink\")", + "key": "Uplink", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2026", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2051" + ] + }, + { + "call": "_(\"Downlink\")", + "key": "Downlink", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2027", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2055" + ] + }, + { + "call": "_(\"Traffic Total\")", + "key": "Traffic Total", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2048" + ] + }, + { + "call": "_(\"System info\")", + "key": "System info", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2078" + ] + }, + { + "call": "_(\"Active Connections\")", + "key": "Active Connections", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2081" + ] + }, + { + "call": "_(\"Memory Usage\")", + "key": "Memory Usage", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2085" + ] + }, + { + "call": "_(\"Services info\")", + "key": "Services info", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2108" + ] + }, + { + "call": "_(\"Podkop\")", + "key": "Podkop", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2111" + ] + }, + { + "call": "_(\"\\u2714 Enabled\")", + "key": "\\u2714 Enabled", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112" + ] + }, + { + "call": "_(\"\\u2718 Disabled\")", + "key": "\\u2718 Disabled", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112" + ] + }, + { + "call": "_(\"Sing-box\")", + "key": "Sing-box", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2118" + ] + }, + { + "call": "_(\"\\u2714 Running\")", + "key": "\\u2714 Running", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119" + ] + }, + { + "call": "_(\"\\u2718 Stopped\")", + "key": "\\u2718 Stopped", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119" + ] + }, + { + "call": "_(\"Checking dns, please wait\")", + "key": "Checking dns, please wait", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2365" + ] + }, + { + "call": "_(\"Cannot receive DNS checks result\")", + "key": "Cannot receive DNS checks result", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2375" + ] + }, + { + "call": "_(\"DNS checks passed\")", + "key": "DNS checks passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2397" + ] + }, + { + "call": "_(\"Bootsrap DNS\")", + "key": "Bootsrap DNS", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2405" + ] + }, + { + "call": "_(\"Main DNS\")", + "key": "Main DNS", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2412" + ] + }, + { + "call": "_(\"DNS on router\")", + "key": "DNS on router", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2417" + ] + }, + { + "call": "_(\"DHCP has DNS server\")", + "key": "DHCP has DNS server", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2422" + ] + }, + { + "call": "_(\"Checking sing-box, please wait\")", + "key": "Checking sing-box, please wait", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2439" + ] + }, + { + "call": "_(\"Cannot receive Sing-box checks result\")", + "key": "Cannot receive Sing-box checks result", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2449" + ] + }, + { + "call": "_(\"Sing-box checks passed\")", + "key": "Sing-box checks passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2471" + ] + }, + { + "call": "_(\"Sing-box installed\")", + "key": "Sing-box installed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2476" + ] + }, + { + "call": "_(\"Sing-box version >= 1.12.4\")", + "key": "Sing-box version >= 1.12.4", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2481" + ] + }, + { + "call": "_(\"Sing-box service exist\")", + "key": "Sing-box service exist", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2486" + ] + }, + { + "call": "_(\"Sing-box autostart disabled\")", + "key": "Sing-box autostart disabled", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2491" + ] + }, + { + "call": "_(\"Sing-box process running\")", + "key": "Sing-box process running", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2496" + ] + }, + { + "call": "_(\"Sing-box listening ports\")", + "key": "Sing-box listening ports", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2501" + ] + }, + { + "call": "_(\"Checking nftables, please wait\")", + "key": "Checking nftables, please wait", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2518" + ] + }, + { + "call": "_(\"Cannot receive nftables checks result\")", + "key": "Cannot receive nftables checks result", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2530" + ] + }, + { + "call": "_(\"Nftables checks passed\")", + "key": "Nftables checks passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552" + ] + }, + { + "call": "_(\"Nftables checks partially passed\")", + "key": "Nftables checks partially passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552" + ] + }, + { + "call": "_(\"Table exist\")", + "key": "Table exist", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2557" + ] + }, + { + "call": "_(\"Rules mangle exist\")", + "key": "Rules mangle exist", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2562" + ] + }, + { + "call": "_(\"Rules mangle counters\")", + "key": "Rules mangle counters", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2567" + ] + }, + { + "call": "_(\"Rules mangle output exist\")", + "key": "Rules mangle output exist", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2572" + ] + }, + { + "call": "_(\"Rules mangle output counters\")", + "key": "Rules mangle output counters", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2577" + ] + }, + { + "call": "_(\"Rules proxy exist\")", + "key": "Rules proxy exist", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2582" + ] + }, + { + "call": "_(\"Rules proxy counters\")", + "key": "Rules proxy counters", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2587" + ] + }, + { + "call": "_(\"No other marking rules found\")", + "key": "No other marking rules found", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592" + ] + }, + { + "call": "_(\"Additional marking rules found\")", + "key": "Additional marking rules found", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592" + ] + }, + { + "call": "_(\"Checking FakeIP, please wait\")", + "key": "Checking FakeIP, please wait", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2609" + ] + }, + { + "call": "_(\"FakeIP checks passed\")", + "key": "FakeIP checks passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2627" + ] + }, + { + "call": "_(\"FakeIP checks partially passed\")", + "key": "FakeIP checks partially passed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2633" + ] + }, + { + "call": "_(\"FakeIP checks failed\")", + "key": "FakeIP checks failed", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2638" + ] + }, + { + "call": "_(\"Router DNS is routed through sing-box\")", + "key": "Router DNS is routed through sing-box", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651" + ] + }, + { + "call": "_(\"Router DNS is not routed through sing-box\")", + "key": "Router DNS is not routed through sing-box", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651" + ] + }, + { + "call": "_(\"Browser is using FakeIP correctly\")", + "key": "Browser is using FakeIP correctly", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656" + ] + }, + { + "call": "_(\"Browser is not using FakeIP\")", + "key": "Browser is not using FakeIP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656" + ] + }, + { + "call": "_(\"Proxy traffic is routed via FakeIP\")", + "key": "Proxy traffic is routed via FakeIP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662" + ] + }, + { + "call": "_(\"Proxy traffic is not routed via FakeIP\")", + "key": "Proxy traffic is not routed via FakeIP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662" + ] + }, + { + "call": "_(\"Successfully copied!\")", + "key": "Successfully copied!", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3288" + ] + }, + { + "call": "_(\"Failed to copy!\")", + "key": "Failed to copy!", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3290" + ] + }, + { + "call": "_(\"Download\")", + "key": "Download", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3306" + ] + }, + { + "call": "_(\"Copy\")", + "key": "Copy", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3311" + ] + }, + { + "call": "_(\"Close\")", + "key": "Close", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3318" + ] + }, + { + "call": "_(\"Restart podkop\")", + "key": "Restart podkop", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3350" + ] + }, + { + "call": "_(\"Stop podkop\")", + "key": "Stop podkop", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3360" + ] + }, + { + "call": "_(\"Start podkop\")", + "key": "Start podkop", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3370" + ] + }, + { + "call": "_(\"Disable autostart\")", + "key": "Disable autostart", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3380" + ] + }, + { + "call": "_(\"Enable autostart\")", + "key": "Enable autostart", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3390" + ] + }, + { + "call": "_(\"Get global check\")", + "key": "Get global check", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3399" + ] + }, + { + "call": "_(\"View logs\")", + "key": "View logs", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3408", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3840" + ] + }, + { + "call": "_(\"Show sing-box config\")", + "key": "Show sing-box config", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3417", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3867" + ] + }, + { + "call": "_(\"Not implement yet\")", + "key": "Not implement yet", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3577" + ] + }, + { + "call": "_(\"Run Diagnostic\")", + "key": "Run Diagnostic", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3587" + ] + }, + { + "call": "_(\"unknown\")", + "key": "unknown", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3651", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3652", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3653", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3654", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3655", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3656", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3950" + ] + }, + { + "call": "_(\"Global check\")", + "key": "Global check", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3813" + ] + }, + { + "call": "_(\"Outdated\")", + "key": "Outdated", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3969" + ] + }, + { + "call": "_(\"Latest\")", + "key": "Latest", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3978" + ] + }, + { + "call": "_(\"Operation timed out\")", + "key": "Operation timed out", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:4389" + ] + }, + { + "call": "_(\"Podkop Settings\")", + "key": "Podkop Settings", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:26" + ] + }, + { + "call": "_(\"Configuration for Podkop service\")", + "key": "Configuration for Podkop service", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:27" + ] + }, + { + "call": "_(\"Sections\")", + "key": "Sections", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36" + ] + }, + { + "call": "_(\"Settings\")", + "key": "Settings", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:49" + ] + }, + { + "call": "_(\"Diagnostics\")", + "key": "Diagnostics", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:65" + ] + }, + { + "call": "_(\"Dashboard\")", + "key": "Dashboard", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:80" + ] + }, + { + "call": "_(\"Connection Type\")", + "key": "Connection Type", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:12" + ] + }, + { + "call": "_(\"Select between VPN and Proxy connection methods for traffic routing\")", + "key": "Select between VPN and Proxy connection methods for traffic routing", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:13" + ] + }, + { + "call": "_(\"Configuration Type\")", + "key": "Configuration Type", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:22" + ] + }, + { + "call": "_(\"Select how to configure the proxy\")", + "key": "Select how to configure the proxy", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23" + ] + }, + { + "call": "_(\"Connection URL\")", + "key": "Connection URL", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:25" + ] + }, + { + "call": "_(\"Outbound Config\")", + "key": "Outbound Config", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26" + ] + }, + { + "call": "_(\"URLTest\")", + "key": "URLTest", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27" + ] + }, + { + "call": "_(\"Proxy Configuration URL\")", + "key": "Proxy Configuration URL", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:34" + ] + }, + { + "call": "_(\"Outbound Configuration\")", + "key": "Outbound Configuration", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64" + ] + }, + { + "call": "_(\"Enter complete outbound configuration in JSON format\")", + "key": "Enter complete outbound configuration in JSON format", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65" + ] + }, + { + "call": "_(\"URLTest Proxy Links\")", + "key": "URLTest Proxy Links", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:87" + ] + }, + { + "call": "_(\"UDP over TCP\")", + "key": "UDP over TCP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:110" + ] + }, + { + "call": "_(\"Applicable for SOCKS and Shadowsocks proxy\")", + "key": "Applicable for SOCKS and Shadowsocks proxy", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111" + ] + }, + { + "call": "_(\"Network Interface\")", + "key": "Network Interface", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120" + ] + }, + { + "call": "_(\"Select network interface for VPN connection\")", + "key": "Select network interface for VPN connection", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121" + ] + }, + { + "call": "_(\"Domain Resolver\")", + "key": "Domain Resolver", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166" + ] + }, + { + "call": "_(\"Enable built-in DNS resolver for domains handled by this section\")", + "key": "Enable built-in DNS resolver for domains handled by this section", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167" + ] + }, + { + "call": "_(\"DNS Protocol Type\")", + "key": "DNS Protocol Type", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12" + ] + }, + { + "call": "_(\"Select the DNS protocol type for the domain resolver\")", + "key": "Select the DNS protocol type for the domain resolver", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177" + ] + }, + { + "call": "_(\"DNS over HTTPS (DoH)\")", + "key": "DNS over HTTPS (DoH)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:15" + ] + }, + { + "call": "_(\"DNS over TLS (DoT)\")", + "key": "DNS over TLS (DoT)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:180", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:16" + ] + }, + { + "call": "_(\"UDP (Unprotected DNS)\")", + "key": "UDP (Unprotected DNS)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:17" + ] + }, + { + "call": "_(\"DNS Server\")", + "key": "DNS Server", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:189", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24" + ] + }, + { + "call": "_(\"Select or enter DNS server address\")", + "key": "Select or enter DNS server address", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:25" + ] + }, + { + "call": "_(label)", + "key": "", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:193", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:217", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:28", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:51", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:254" + ] + }, + { + "call": "_(\"Community Lists\")", + "key": "Community Lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211" + ] + }, + { + "call": "_(\"Select a predefined list for routing\")", + "key": "Select a predefined list for routing", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212" + ] + }, + { + "call": "_(\"Regional options cannot be used together\")", + "key": "Regional options cannot be used together", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245" + ] + }, + { + "call": "_(\"Warning: %s cannot be used together with %s. Previous selections have been removed.\")", + "key": "Warning: %s cannot be used together with %s. Previous selections have been removed.", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247" + ] + }, + { + "call": "_(\"Russia inside restrictions\")", + "key": "Russia inside restrictions", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:264" + ] + }, + { + "call": "_(\"Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.\")", + "key": "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266" + ] + }, + { + "call": "_(\"User Domain List Type\")", + "key": "User Domain List Type", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299" + ] + }, + { + "call": "_(\"Select the list type for adding custom domains\")", + "key": "Select the list type for adding custom domains", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300" + ] + }, + { + "call": "_(\"Disabled\")", + "key": "Disabled", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:302", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:382" + ] + }, + { + "call": "_(\"Dynamic List\")", + "key": "Dynamic List", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:303", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:383" + ] + }, + { + "call": "_(\"Text List\")", + "key": "Text List", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304" + ] + }, + { + "call": "_(\"User Domains\")", + "key": "User Domains", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311" + ] + }, + { + "call": "_(\"Enter domain names without protocols, e.g. example.com or sub.example.com\")", + "key": "Enter domain names without protocols, e.g. example.com or sub.example.com", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312" + ] + }, + { + "call": "_(\"User Domains List\")", + "key": "User Domains List", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:337" + ] + }, + { + "call": "_(\"Enter domain names separated by commas, spaces, or newlines. You can add comments using //\")", + "key": "Enter domain names separated by commas, spaces, or newlines. You can add comments using //", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338" + ] + }, + { + "call": "_(\"At least one valid domain must be specified. Comments-only content is not allowed.\")", + "key": "At least one valid domain must be specified. Comments-only content is not allowed.", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:356" + ] + }, + { + "call": "_(`${validation.value}: ${validation.message}`)", + "key": "${validation.value}: ${validation.message}", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:368", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:447" + ] + }, + { + "call": "_(\"Validation errors:\")", + "key": "Validation errors:", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:370", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:449" + ] + }, + { + "call": "_(\"User Subnet List Type\")", + "key": "User Subnet List Type", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379" + ] + }, + { + "call": "_(\"Select the list type for adding custom subnets\")", + "key": "Select the list type for adding custom subnets", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380" + ] + }, + { + "call": "_(\"Text List (comma/space/newline separated)\")", + "key": "Text List (comma/space/newline separated)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384" + ] + }, + { + "call": "_(\"User Subnets\")", + "key": "User Subnets", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391" + ] + }, + { + "call": "_(\"Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses\")", + "key": "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392" + ] + }, + { + "call": "_(\"User Subnets List\")", + "key": "User Subnets List", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:417" + ] + }, + { + "call": "_(\"Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //\")", + "key": "Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:418" + ] + }, + { + "call": "_(\"At least one valid subnet or IP must be specified. Comments-only content is not allowed.\")", + "key": "At least one valid subnet or IP must be specified. Comments-only content is not allowed.", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437" + ] + }, + { + "call": "_(\"Local Domain Lists\")", + "key": "Local Domain Lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458" + ] + }, + { + "call": "_(\"Specify the path to the list file located on the router filesystem\")", + "key": "Specify the path to the list file located on the router filesystem", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:459", + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:482" + ] + }, + { + "call": "_(\"Local Subnet Lists\")", + "key": "Local Subnet Lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481" + ] + }, + { + "call": "_(\"Remote Domain Lists\")", + "key": "Remote Domain Lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504" + ] + }, + { + "call": "_(\"Specify remote URLs to download and use domain lists\")", + "key": "Specify remote URLs to download and use domain lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505" + ] + }, + { + "call": "_(\"Remote Subnet Lists\")", + "key": "Remote Subnet Lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527" + ] + }, + { + "call": "_(\"Specify remote URLs to download and use subnet lists\")", + "key": "Specify remote URLs to download and use subnet lists", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528" + ] + }, + { + "call": "_(\"Fully Routed IPs\")", + "key": "Fully Routed IPs", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550" + ] + }, + { + "call": "_(\"Specify local IP addresses or subnets whose traffic will always be routed through the configured route\")", + "key": "Specify local IP addresses or subnets whose traffic will always be routed through the configured route", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551" + ] + }, + { + "call": "_(\"Enable Mixed Proxy\")", + "key": "Enable Mixed Proxy", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:575" + ] + }, + { + "call": "_(\"Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies\")", + "key": "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576" + ] + }, + { + "call": "_(\"Mixed Proxy Port\")", + "key": "Mixed Proxy Port", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:586" + ] + }, + { + "call": "_(\"Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service\")", + "key": "Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:587" + ] + }, + { + "call": "_(\"Select DNS protocol to use\")", + "key": "Select DNS protocol to use", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:13" + ] + }, + { + "call": "_(\"Bootstrap DNS server\")", + "key": "Bootstrap DNS server", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:45" + ] + }, + { + "call": "_(\"The DNS server used to look up the IP address of an upstream DNS server\")", + "key": "The DNS server used to look up the IP address of an upstream DNS server", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46" + ] + }, + { + "call": "_(\"DNS Rewrite TTL\")", + "key": "DNS Rewrite TTL", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:68" + ] + }, + { + "call": "_(\"Time in seconds for DNS record caching (default: 60)\")", + "key": "Time in seconds for DNS record caching (default: 60)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69" + ] + }, + { + "call": "_(\"TTL value cannot be empty\")", + "key": "TTL value cannot be empty", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:75" + ] + }, + { + "call": "_(\"TTL must be a positive number\")", + "key": "TTL must be a positive number", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:80" + ] + }, + { + "call": "_(\"Source Network Interface\")", + "key": "Source Network Interface", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89" + ] + }, + { + "call": "_(\"Select the network interface from which the traffic will originate\")", + "key": "Select the network interface from which the traffic will originate", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90" + ] + }, + { + "call": "_(\"Enable Output Network Interface\")", + "key": "Enable Output Network Interface", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:126" + ] + }, + { + "call": "_(\"You can select Output Network Interface, by default autodetect\")", + "key": "You can select Output Network Interface, by default autodetect", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127" + ] + }, + { + "call": "_(\"Output Network Interface\")", + "key": "Output Network Interface", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:135" + ] + }, + { + "call": "_(\"Select the network interface to which the traffic will originate\")", + "key": "Select the network interface to which the traffic will originate", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:136" + ] + }, + { + "call": "_(\"Interface Monitoring\")", + "key": "Interface Monitoring", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:182" + ] + }, + { + "call": "_(\"Interface monitoring for Bad WAN\")", + "key": "Interface monitoring for Bad WAN", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:183" + ] + }, + { + "call": "_(\"Monitored Interfaces\")", + "key": "Monitored Interfaces", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:191" + ] + }, + { + "call": "_(\"Select the WAN interfaces to be monitored\")", + "key": "Select the WAN interfaces to be monitored", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:192" + ] + }, + { + "call": "_(\"Interface Monitoring Delay\")", + "key": "Interface Monitoring Delay", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:214" + ] + }, + { + "call": "_(\"Delay in milliseconds before reloading podkop after interface UP\")", + "key": "Delay in milliseconds before reloading podkop after interface UP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:215" + ] + }, + { + "call": "_(\"Delay value cannot be empty\")", + "key": "Delay value cannot be empty", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222" + ] + }, + { + "call": "_(\"Enable YACD\")", + "key": "Enable YACD", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:230" + ] + }, + { + "call": "_(\"Disable QUIC\")", + "key": "Disable QUIC", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:239" + ] + }, + { + "call": "_(\"Disable the QUIC protocol to improve compatibility or fix issues with video streaming\")", + "key": "Disable the QUIC protocol to improve compatibility or fix issues with video streaming", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:240" + ] + }, + { + "call": "_(\"List Update Frequency\")", + "key": "List Update Frequency", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:250" + ] + }, + { + "call": "_(\"Select how often the domain or subnet lists are updated automatically\")", + "key": "Select how often the domain or subnet lists are updated automatically", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:251" + ] + }, + { + "call": "_(\"Download Lists via Proxy/VPN\")", + "key": "Download Lists via Proxy/VPN", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:262" + ] + }, + { + "call": "_(\"Downloading all lists via main Proxy/VPN\")", + "key": "Downloading all lists via main Proxy/VPN", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:263" + ] + }, + { + "call": "_(\"Download Lists via specific proxy section\")", + "key": "Download Lists via specific proxy section", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:271" + ] + }, + { + "call": "_(\"Downloading all lists via specific Proxy/VPN\")", + "key": "Downloading all lists via specific Proxy/VPN", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:272" + ] + }, + { + "call": "_(\"Dont Touch My DHCP!\")", + "key": "Dont Touch My DHCP!", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:300" + ] + }, + { + "call": "_(\"Podkop will not modify your DHCP configuration\")", + "key": "Podkop will not modify your DHCP configuration", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:301" + ] + }, + { + "call": "_(\"Config File Path\")", + "key": "Config File Path", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:309" + ] + }, + { + "call": "_(\"Select path for sing-box config file. Change this ONLY if you know what you are doing\")", + "key": "Select path for sing-box config file. Change this ONLY if you know what you are doing", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:310" + ] + }, + { + "call": "_(\"Cache File Path\")", + "key": "Cache File Path", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:322" + ] + }, + { + "call": "_(\"Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing\")", + "key": "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:323" + ] + }, + { + "call": "_(\"Cache file path cannot be empty\")", + "key": "Cache file path cannot be empty", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336" + ] + }, + { + "call": "_(\"Path must be absolute (start with /)\")", + "key": "Path must be absolute (start with /)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:340" + ] + }, + { + "call": "_(\"Path must end with cache.db\")", + "key": "Path must end with cache.db", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:344" + ] + }, + { + "call": "_(\"Path must contain at least one directory (like /tmp/cache.db)\")", + "key": "Path must contain at least one directory (like /tmp/cache.db)", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349" + ] + }, + { + "call": "_(\"Exclude NTP\")", + "key": "Exclude NTP", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:358" + ] + }, + { + "call": "_(\"Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN\")", + "key": "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:359" + ] + }, + { + "call": "_(\"Routing Excluded IPs\")", + "key": "Routing Excluded IPs", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:369" + ] + }, + { + "call": "_(\"Specify a local IP address to be excluded from routing\")", + "key": "Specify a local IP address to be excluded from routing", + "places": [ + "../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370" + ] + } +] \ No newline at end of file diff --git a/fe-app-podkop/locales/podkop.pot b/fe-app-podkop/locales/podkop.pot new file mode 100644 index 0000000..64f11d4 --- /dev/null +++ b/fe-app-podkop/locales/podkop.pot @@ -0,0 +1,1517 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2025 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PODKOP package. +# divocat , 2025. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PODKOP\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-10-21 18:31+0300\n" +"PO-Revision-Date: 2025-10-21 18:31+0300\n" +"Last-Translator: divocat \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/helpers/copyToClipboard.ts:10 +msgid "Successfully copied!" +msgstr "" + +#: src/helpers/copyToClipboard.ts:12 +msgid "Failed to copy!" +msgstr "" + +#: src/helpers/withTimeout.ts:7 +msgid "Operation timed out" +msgstr "" + +#: src/podkop/api.ts:27 +msgid "HTTP error" +msgstr "" + +#: src/podkop/api.ts:40 +msgid "Unknown error" +msgstr "" + +#: src/validators/validateDns.ts:7 +msgid "DNS server address cannot be empty" +msgstr "" + +#: src/validators/validateDns.ts:11 +#: src/validators/validateDns.ts:15 +#: src/validators/validateDomain.ts:13 +#: src/validators/validateDomain.ts:30 +#: src/validators/validateIp.ts:8 +#: src/validators/validateOutboundJson.ts:17 +#: 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 +msgid "Valid" +msgstr "" + +#: src/validators/validateDns.ts:20 +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "" + +#: src/validators/validateDomain.ts:18 +#: src/validators/validateDomain.ts:27 +msgid "Invalid domain address" +msgstr "" + +#: src/validators/validateIp.ts:11 +msgid "Invalid IP address" +msgstr "" + +#: src/validators/validateOutboundJson.ts:11 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:327 +msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" +msgstr "" + +#: src/validators/validateOutboundJson.ts:19 +msgid "Invalid JSON format" +msgstr "" + +#: src/validators/validatePath.ts:7 +msgid "Path cannot be empty" +msgstr "" + +#: src/validators/validatePath.ts:22 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:90 +msgid "Invalid path format. Path must start with \"/\" and contain valid characters" +msgstr "" + +#: src/validators/validateProxyUrl.ts:27 +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:8 +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:16 +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:27 +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:37 +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:46 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:171 +msgid "Invalid Shadowsocks URL: missing method and password separator \":\"" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:58 +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:67 +msgid "Invalid Shadowsocks URL: missing server" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:76 +msgid "Invalid Shadowsocks URL: missing port" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:85 +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "" + +#: src/validators/validateShadowsocksUrl.ts:91 +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "" + +#: src/validators/validateSocksUrl.ts:10 +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +#: src/validators/validateSocksUrl.ts:19 +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +#: src/validators/validateSocksUrl.ts:34 +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +#: src/validators/validateSocksUrl.ts:42 +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +#: src/validators/validateSocksUrl.ts:51 +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +#: src/validators/validateSocksUrl.ts:56 +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +#: src/validators/validateSocksUrl.ts:63 +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +#: src/validators/validateSocksUrl.ts:73 +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +#: src/validators/validateSocksUrl.ts:77 +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +#: src/validators/validateSubnet.ts:11 +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "" + +#: src/validators/validateSubnet.ts:18 +msgid "IP address 0.0.0.0 is not allowed" +msgstr "" + +#: src/validators/validateSubnet.ts:33 +msgid "CIDR must be between 0 and 32" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:8 +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:15 +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:56 +msgid "Invalid Trojan URL: parsing failed" +msgstr "" + +#: src/validators/validateUrl.ts:13 +msgid "URL must use one of the following protocols:" +msgstr "" + +#: src/validators/validateUrl.ts:18 +msgid "Invalid URL format" +msgstr "" + +#: src/validators/validateVlessUrl.ts:109 +msgid "Invalid VLESS URL: parsing failed" +msgstr "" + +#: src/partials/modal/renderModal.ts:15 +msgid "Download" +msgstr "" + +#: src/partials/modal/renderModal.ts:20 +msgid "Copy" +msgstr "" + +#: src/partials/modal/renderModal.ts:26 +msgid "Close" +msgstr "" + +#: src/podkop/methods/custom/getDashboardSections.ts:117 +msgid "Fastest" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:235 +msgid "Traffic" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:237 +#: src/podkop/tabs/dashboard/initController.ts:268 +msgid "Uplink" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:238 +#: src/podkop/tabs/dashboard/initController.ts:272 +msgid "Downlink" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:265 +msgid "Traffic Total" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:301 +msgid "System info" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:304 +msgid "Active Connections" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:308 +msgid "Memory Usage" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:337 +msgid "Services info" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:340 +msgid "Podkop" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:342 +msgid "✔ Enabled" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:343 +msgid "✘ Disabled" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:351 +msgid "Sing-box" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:353 +msgid "✔ Running" +msgstr "" + +#: src/podkop/tabs/dashboard/initController.ts:354 +msgid "✘ Stopped" +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 +msgid "Not running" +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 "" + +#: 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 +msgid "unknown" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:218 +msgid "Global check" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:248 +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107 +msgid "View logs" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:278 +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116 +msgid "Show sing-box config" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:394 +msgid "Outdated" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:404 +msgid "Latest" +msgstr "" + +#: src/podkop/tabs/dashboard/partials/renderSections.ts:19 +msgid "Dashboard currently unavailable" +msgstr "" + +#: src/podkop/tabs/dashboard/partials/renderSections.ts:108 +msgid "Test latency" +msgstr "" + +#: src/podkop/tabs/dashboard/partials/renderWidget.ts:22 +msgid "Currently unavailable" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/contstants.ts:14 +msgid "DNS checks" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/contstants.ts:19 +msgid "Sing-box checks" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/contstants.ts:24 +msgid "Nftables checks" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/contstants.ts:29 +msgid "FakeIP checks" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:14 +msgid "Checking dns, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:26 +msgid "Cannot receive DNS checks result" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:64 +msgid "DNS checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72 +msgid "Bootsrap DNS" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:79 +msgid "Main DNS" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:84 +msgid "DNS on router" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:89 +msgid "DHCP has DNS server" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:14 +msgid "Checking FakeIP, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:44 +msgid "FakeIP checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51 +msgid "FakeIP checks partially passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57 +msgid "FakeIP checks failed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:73 +msgid "Router DNS is routed through sing-box" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:74 +msgid "Router DNS is not routed through sing-box" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:80 +msgid "Browser is using FakeIP correctly" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:81 +msgid "Browser is not using FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:88 +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:89 +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:12 +msgid "Checking nftables, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:27 +msgid "Cannot receive nftables checks result" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74 +msgid "Nftables checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:75 +msgid "Nftables checks partially passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:80 +msgid "Table exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:85 +msgid "Rules mangle exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:90 +msgid "Rules mangle counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:95 +msgid "Rules mangle output exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:100 +msgid "Rules mangle output counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105 +msgid "Rules proxy exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:110 +msgid "Rules proxy counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:116 +msgid "No other marking rules found" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:117 +msgid "Additional marking rules found" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:12 +msgid "Checking sing-box, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:24 +msgid "Cannot receive Sing-box checks result" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:66 +msgid "Sing-box checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:71 +msgid "Sing-box installed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:76 +msgid "Sing-box version >= 1.12.4" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:81 +msgid "Sing-box service exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:86 +msgid "Sing-box autostart disabled" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:91 +msgid "Sing-box process running" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:96 +msgid "Sing-box listening ports" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49 +msgid "Restart podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:59 +msgid "Stop podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:69 +msgid "Start podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:79 +msgid "Disable autostart" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:89 +msgid "Enable autostart" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:98 +msgid "Get global check" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderCheckSection.ts:189 +msgid "Not implement yet" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderRunAction.ts:15 +msgid "Run Diagnostic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:12 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:23 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:35 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:44 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:47 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:67 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:85 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:122 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:211 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:314 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:332 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:383 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:449 +msgid "Valid" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:14 +msgid "Invalid IP address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:27 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:33 +msgid "Invalid domain address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:41 +msgid "DNS server address cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:51 +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:64 +msgid "URL must use one of the following protocols:" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:69 +msgid "Invalid URL format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:78 +msgid "Path cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:102 +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:107 +msgid "IP address 0.0.0.0 is not allowed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:118 +msgid "CIDR must be between 0 and 32" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:139 +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:146 +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:154 +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:162 +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:181 +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:188 +msgid "Invalid Shadowsocks URL: missing server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:195 +msgid "Invalid Shadowsocks URL: missing port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:202 +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:208 +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:316 +msgid "Invalid VLESS URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:334 +msgid "Invalid JSON format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:344 +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:350 +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:381 +msgid "Invalid Trojan URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:392 +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:400 +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:411 +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:418 +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:425 +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:429 +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:435 +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:443 +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:447 +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:468 +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:692 +msgid "Fastest" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:864 +msgid "HTTP error" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:875 +msgid "Unknown error" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:985 +msgid "DNS checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:990 +msgid "Sing-box checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:995 +msgid "Nftables checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1000 +msgid "FakeIP checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1048 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1056 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1064 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1072 +msgid "Not running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1084 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1092 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1100 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1108 +msgid "Queued" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1578 +msgid "Dashboard currently unavailable" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1654 +msgid "Test latency" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1683 +msgid "Currently unavailable" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2024 +msgid "Traffic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2026 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2051 +msgid "Uplink" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2027 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2055 +msgid "Downlink" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2048 +msgid "Traffic Total" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2078 +msgid "System info" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2081 +msgid "Active Connections" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2085 +msgid "Memory Usage" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2108 +msgid "Services info" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2111 +msgid "Podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112 +msgid "\\u2714 Enabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112 +msgid "\\u2718 Disabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2118 +msgid "Sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119 +msgid "\\u2714 Running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119 +msgid "\\u2718 Stopped" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2365 +msgid "Checking dns, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2375 +msgid "Cannot receive DNS checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2397 +msgid "DNS checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2405 +msgid "Bootsrap DNS" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2412 +msgid "Main DNS" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2417 +msgid "DNS on router" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2422 +msgid "DHCP has DNS server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2439 +msgid "Checking sing-box, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2449 +msgid "Cannot receive Sing-box checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2471 +msgid "Sing-box checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2476 +msgid "Sing-box installed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2481 +msgid "Sing-box version >= 1.12.4" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2486 +msgid "Sing-box service exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2491 +msgid "Sing-box autostart disabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2496 +msgid "Sing-box process running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2501 +msgid "Sing-box listening ports" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2518 +msgid "Checking nftables, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2530 +msgid "Cannot receive nftables checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552 +msgid "Nftables checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552 +msgid "Nftables checks partially passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2557 +msgid "Table exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2562 +msgid "Rules mangle exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2567 +msgid "Rules mangle counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2572 +msgid "Rules mangle output exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2577 +msgid "Rules mangle output counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2582 +msgid "Rules proxy exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2587 +msgid "Rules proxy counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592 +msgid "No other marking rules found" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592 +msgid "Additional marking rules found" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2609 +msgid "Checking FakeIP, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2627 +msgid "FakeIP checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2633 +msgid "FakeIP checks partially passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2638 +msgid "FakeIP checks failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651 +msgid "Router DNS is routed through sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651 +msgid "Router DNS is not routed through sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656 +msgid "Browser is using FakeIP correctly" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656 +msgid "Browser is not using FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662 +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662 +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3288 +msgid "Successfully copied!" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3290 +msgid "Failed to copy!" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3306 +msgid "Download" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3311 +msgid "Copy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3318 +msgid "Close" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3350 +msgid "Restart podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3360 +msgid "Stop podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3370 +msgid "Start podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3380 +msgid "Disable autostart" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3390 +msgid "Enable autostart" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3399 +msgid "Get global check" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3408 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3840 +msgid "View logs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3417 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3867 +msgid "Show sing-box config" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3577 +msgid "Not implement yet" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3587 +msgid "Run Diagnostic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3651 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3652 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3653 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3654 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3655 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3656 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3950 +msgid "unknown" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3813 +msgid "Global check" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3969 +msgid "Outdated" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3978 +msgid "Latest" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:4389 +msgid "Operation timed out" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:26 +msgid "Podkop Settings" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:27 +msgid "Configuration for Podkop service" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36 +msgid "Sections" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:49 +msgid "Settings" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:65 +msgid "Diagnostics" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:80 +msgid "Dashboard" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:12 +msgid "Connection Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:13 +msgid "Select between VPN and Proxy connection methods for traffic routing" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:22 +msgid "Configuration Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23 +msgid "Select how to configure the proxy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:25 +msgid "Connection URL" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26 +msgid "Outbound Config" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27 +msgid "URLTest" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:34 +msgid "Proxy Configuration URL" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64 +msgid "Outbound Configuration" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65 +msgid "Enter complete outbound configuration in JSON format" +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:110 +msgid "UDP over TCP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111 +msgid "Applicable for SOCKS and Shadowsocks proxy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120 +msgid "Network Interface" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121 +msgid "Select network interface for VPN connection" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166 +msgid "Domain Resolver" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167 +msgid "Enable built-in DNS resolver for domains handled by this section" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12 +msgid "DNS Protocol Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177 +msgid "Select the DNS protocol type for the domain resolver" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179 +#: ../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/settings.js:16 +msgid "DNS over TLS (DoT)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181 +#: ../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:189 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24 +msgid "DNS Server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190 +#: ../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/section.js:193 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:217 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:28 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:51 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:254 +msgid "" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211 +msgid "Community Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212 +msgid "Select a predefined list for routing" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245 +msgid "Regional options cannot be used together" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247 +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:264 +msgid "Russia inside restrictions" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266 +msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299 +msgid "User Domain List Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300 +msgid "Select the list type for adding custom domains" +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 +msgid "Disabled" +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 +msgid "Dynamic List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304 +msgid "Text List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311 +msgid "User Domains" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312 +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:337 +msgid "User Domains List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338 +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:356 +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:368 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:447 +msgid "${validation.value}: ${validation.message}" +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 +msgid "Validation errors:" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379 +msgid "User Subnet List Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380 +msgid "Select the list type for adding custom subnets" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384 +msgid "Text List (comma/space/newline separated)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391 +msgid "User Subnets" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392 +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/section.js:417 +msgid "User Subnets List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:418 +msgid "Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437 +msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458 +msgid "Local Domain 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 +msgid "Specify the path to the list file located on the router filesystem" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481 +msgid "Local Subnet Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504 +msgid "Remote Domain Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505 +msgid "Specify remote URLs to download and use domain lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527 +msgid "Remote Subnet Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528 +msgid "Specify remote URLs to download and use subnet lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550 +msgid "Fully Routed IPs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551 +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:575 +msgid "Enable Mixed Proxy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576 +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/section.js:586 +msgid "Mixed Proxy Port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:587 +msgid "Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:13 +msgid "Select DNS protocol to use" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:45 +msgid "Bootstrap DNS server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46 +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/settings.js:68 +msgid "DNS Rewrite TTL" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69 +msgid "Time in seconds for DNS record caching (default: 60)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:75 +msgid "TTL value cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:80 +msgid "TTL must be a positive number" +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:90 +msgid "Select the network interface from which the traffic will originate" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:126 +msgid "Enable Output Network Interface" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127 +msgid "You can select Output Network Interface, by default autodetect" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:135 +msgid "Output Network Interface" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:136 +msgid "Select the network interface to which the traffic will originate" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:182 +msgid "Interface Monitoring" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:183 +msgid "Interface monitoring for Bad WAN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:191 +msgid "Monitored Interfaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:192 +msgid "Select the WAN interfaces to be monitored" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:214 +msgid "Interface Monitoring Delay" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:215 +msgid "Delay in milliseconds before reloading podkop after interface UP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222 +msgid "Delay value cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:230 +msgid "Enable YACD" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:239 +msgid "Disable QUIC" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:240 +msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:250 +msgid "List Update Frequency" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:251 +msgid "Select how often the domain or subnet lists are updated automatically" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:262 +msgid "Download Lists via Proxy/VPN" +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:271 +msgid "Download Lists via specific proxy section" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:272 +msgid "Downloading all lists via specific Proxy/VPN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:300 +msgid "Dont Touch My DHCP!" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:301 +msgid "Podkop will not modify your DHCP configuration" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:309 +msgid "Config File Path" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:310 +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/settings.js:322 +msgid "Cache File Path" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:323 +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:336 +msgid "Cache file path cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:340 +msgid "Path must be absolute (start with /)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:344 +msgid "Path must end with cache.db" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349 +msgid "Path must contain at least one directory (like /tmp/cache.db)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:358 +msgid "Exclude NTP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:359 +msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:369 +msgid "Routing Excluded IPs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370 +msgid "Specify a local IP address to be excluded from routing" +msgstr "" diff --git a/fe-app-podkop/locales/podkop.ru.po b/fe-app-podkop/locales/podkop.ru.po new file mode 100644 index 0000000..10dd5ae --- /dev/null +++ b/fe-app-podkop/locales/podkop.ru.po @@ -0,0 +1,1086 @@ +# RU translations for PODKOP package. +# Copyright (C) 2025 THE PODKOP'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PODKOP package. +# divocat, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PODKOP\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-10-21 21:31+0300\n" +"PO-Revision-Date: 2025-10-21 21:31+0300\n" +"Last-Translator: divocat\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Successfully copied!" +msgstr "" + +msgid "Failed to copy!" +msgstr "" + +msgid "Operation timed out" +msgstr "Время ожидания истекло" + +msgid "HTTP error" +msgstr "Ошибка HTTP" + +msgid "Unknown error" +msgstr "Неизвестная ошибка" + +msgid "DNS server address cannot be empty" +msgstr "Адрес DNS-сервера не может быть пустым" + +msgid "Valid" +msgstr "Валидно" + +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "Неверный формат DNS-сервера. Примеры: 8.8.8.8, dns.example.com или dns.example.com/nicedns для DoH" + +msgid "Invalid domain address" +msgstr "Неверный домен" + +msgid "Invalid IP address" +msgstr "Неверный IP-адрес" + +msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" +msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\"" + +msgid "Invalid JSON format" +msgstr "Неверный формат JSON" + +msgid "Path cannot be empty" +msgstr "Путь не может быть пустым" + +msgid "Invalid path format. Path must start with \"/\" and contain valid characters" +msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы" + +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "Неверный URL Shadowsocks: должен начинаться с ss://" + +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "Неверный URL Shadowsocks: не должен содержать пробелов" + +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "Неверный URL Shadowsocks: отсутствуют учетные данные" + +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "Неверный URL Shadowsocks: декодированные данные должны содержать method:password" + +msgid "Invalid Shadowsocks URL: missing method and password separator \":\"" +msgstr "Неверный URL Shadowsocks: отсутствует разделитель метода и пароля \":\"" + +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "Неверный URL Shadowsocks: отсутствует адрес сервера" + +msgid "Invalid Shadowsocks URL: missing server" +msgstr "Неверный URL Shadowsocks: отсутствует сервер" + +msgid "Invalid Shadowsocks URL: missing port" +msgstr "Неверный URL Shadowsocks: отсутствует порт" + +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "Неверный номер порта. Допустимо от 1 до 65535" + +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "Неверный URL Shadowsocks: ошибка разбора" + +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y" + +msgid "IP address 0.0.0.0 is not allowed" +msgstr "IP-адрес 0.0.0.0 не допускается" + +msgid "CIDR must be between 0 and 32" +msgstr "CIDR должен быть между 0 и 32" + +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "Неверный URL Trojan: должен начинаться с trojan://" + +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "Неверный URL Trojan: не должен содержать пробелов" + +msgid "Invalid Trojan URL: parsing failed" +msgstr "Неверный URL Trojan: ошибка разбора" + +msgid "URL must use one of the following protocols:" +msgstr "URL должен использовать один из следующих протоколов:" + +msgid "Invalid URL format" +msgstr "Неверный формат URL" + +msgid "Invalid VLESS URL: parsing failed" +msgstr "Неверный URL VLESS: ошибка разбора" + +msgid "Download" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Close" +msgstr "Закрыть" + +msgid "Fastest" +msgstr "Самый быстрый" + +msgid "Traffic" +msgstr "Трафик" + +msgid "Uplink" +msgstr "Исходящий" + +msgid "Downlink" +msgstr "Входящий" + +msgid "Traffic Total" +msgstr "Всего трафика" + +msgid "System info" +msgstr "Системная информация" + +msgid "Active Connections" +msgstr "Активные соединения" + +msgid "Memory Usage" +msgstr "Использование памяти" + +msgid "Services info" +msgstr "Информация о сервисах" + +msgid "Podkop" +msgstr "Podkop" + +msgid "✔ Enabled" +msgstr "✔ Включено" + +msgid "✘ Disabled" +msgstr "✘ Отключено" + +msgid "Sing-box" +msgstr "Sing-box" + +msgid "✔ Running" +msgstr "✔ Работает" + +msgid "✘ Stopped" +msgstr "✘ Остановлен" + +msgid "Not running" +msgstr "" + +msgid "Queued" +msgstr "" + +msgid "unknown" +msgstr "" + +msgid "Global check" +msgstr "Глобальная проверка" + +msgid "View logs" +msgstr "" + +msgid "Show sing-box config" +msgstr "" + +msgid "Outdated" +msgstr "" + +msgid "Latest" +msgstr "" + +msgid "Dashboard currently unavailable" +msgstr "Дашборд сейчас недоступен" + +msgid "Test latency" +msgstr "" + +msgid "Currently unavailable" +msgstr "Временно недоступно" + +msgid "DNS checks" +msgstr "" + +msgid "Sing-box checks" +msgstr "" + +msgid "Nftables checks" +msgstr "" + +msgid "FakeIP checks" +msgstr "" + +msgid "Checking dns, please wait" +msgstr "" + +msgid "Cannot receive DNS checks result" +msgstr "" + +msgid "DNS checks passed" +msgstr "" + +msgid "Bootsrap DNS" +msgstr "" + +msgid "Main DNS" +msgstr "" + +msgid "DNS on router" +msgstr "" + +msgid "DHCP has DNS server" +msgstr "" + +msgid "Checking FakeIP, please wait" +msgstr "" + +msgid "FakeIP checks passed" +msgstr "" + +msgid "FakeIP checks partially passed" +msgstr "" + +msgid "FakeIP checks failed" +msgstr "" + +msgid "Router DNS is routed through sing-box" +msgstr "" + +msgid "Router DNS is not routed through sing-box" +msgstr "" + +msgid "Browser is using FakeIP correctly" +msgstr "" + +msgid "Browser is not using FakeIP" +msgstr "" + +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +msgid "Checking nftables, please wait" +msgstr "" + +msgid "Cannot receive nftables checks result" +msgstr "" + +msgid "Nftables checks passed" +msgstr "" + +msgid "Nftables checks partially passed" +msgstr "" + +msgid "Table exist" +msgstr "" + +msgid "Rules mangle exist" +msgstr "" + +msgid "Rules mangle counters" +msgstr "" + +msgid "Rules mangle output exist" +msgstr "" + +msgid "Rules mangle output counters" +msgstr "" + +msgid "Rules proxy exist" +msgstr "" + +msgid "Rules proxy counters" +msgstr "" + +msgid "No other marking rules found" +msgstr "" + +msgid "Additional marking rules found" +msgstr "" + +msgid "Checking sing-box, please wait" +msgstr "" + +msgid "Cannot receive Sing-box checks result" +msgstr "" + +msgid "Sing-box checks passed" +msgstr "" + +msgid "Sing-box installed" +msgstr "" + +msgid "Sing-box version >= 1.12.4" +msgstr "" + +msgid "Sing-box service exist" +msgstr "" + +msgid "Sing-box autostart disabled" +msgstr "" + +msgid "Sing-box process running" +msgstr "" + +msgid "Sing-box listening ports" +msgstr "" + +msgid "Restart podkop" +msgstr "" + +msgid "Stop podkop" +msgstr "" + +msgid "Start podkop" +msgstr "" + +msgid "Disable autostart" +msgstr "" + +msgid "Enable autostart" +msgstr "" + +msgid "Get global check" +msgstr "" + +msgid "Not implement yet" +msgstr "" + +msgid "Run Diagnostic" +msgstr "" + +msgid "Valid" +msgstr "Валидно" + +msgid "Invalid IP address" +msgstr "Неверный IP-адрес" + +msgid "Invalid domain address" +msgstr "Неверный домен" + +msgid "DNS server address cannot be empty" +msgstr "Адрес DNS-сервера не может быть пустым" + +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "Неверный формат DNS-сервера. Примеры: 8.8.8.8, dns.example.com или dns.example.com/nicedns для DoH" + +msgid "URL must use one of the following protocols:" +msgstr "URL должен использовать один из следующих протоколов:" + +msgid "Invalid URL format" +msgstr "Неверный формат URL" + +msgid "Path cannot be empty" +msgstr "Путь не может быть пустым" + +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y" + +msgid "IP address 0.0.0.0 is not allowed" +msgstr "IP-адрес 0.0.0.0 не допускается" + +msgid "CIDR must be between 0 and 32" +msgstr "CIDR должен быть между 0 и 32" + +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "Неверный URL Shadowsocks: должен начинаться с ss://" + +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "Неверный URL Shadowsocks: не должен содержать пробелов" + +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "Неверный URL Shadowsocks: отсутствуют учетные данные" + +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "Неверный URL Shadowsocks: декодированные данные должны содержать method:password" + +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "Неверный URL Shadowsocks: отсутствует адрес сервера" + +msgid "Invalid Shadowsocks URL: missing server" +msgstr "Неверный URL Shadowsocks: отсутствует сервер" + +msgid "Invalid Shadowsocks URL: missing port" +msgstr "Неверный URL Shadowsocks: отсутствует порт" + +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "Неверный номер порта. Допустимо от 1 до 65535" + +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "Неверный URL Shadowsocks: ошибка разбора" + +msgid "Invalid VLESS URL: parsing failed" +msgstr "Неверный URL VLESS: ошибка разбора" + +msgid "Invalid JSON format" +msgstr "Неверный формат JSON" + +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "Неверный URL Trojan: должен начинаться с trojan://" + +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "Неверный URL Trojan: не должен содержать пробелов" + +msgid "Invalid Trojan URL: parsing failed" +msgstr "Неверный URL Trojan: ошибка разбора" + +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +msgid "Fastest" +msgstr "Самый быстрый" + +msgid "HTTP error" +msgstr "Ошибка HTTP" + +msgid "Unknown error" +msgstr "Неизвестная ошибка" + +msgid "DNS checks" +msgstr "" + +msgid "Sing-box checks" +msgstr "" + +msgid "Nftables checks" +msgstr "" + +msgid "FakeIP checks" +msgstr "" + +msgid "Not running" +msgstr "" + +msgid "Queued" +msgstr "" + +msgid "Dashboard currently unavailable" +msgstr "Дашборд сейчас недоступен" + +msgid "Test latency" +msgstr "" + +msgid "Currently unavailable" +msgstr "Временно недоступно" + +msgid "Traffic" +msgstr "Трафик" + +msgid "Uplink" +msgstr "Исходящий" + +msgid "Downlink" +msgstr "Входящий" + +msgid "Traffic Total" +msgstr "Всего трафика" + +msgid "System info" +msgstr "Системная информация" + +msgid "Active Connections" +msgstr "Активные соединения" + +msgid "Memory Usage" +msgstr "Использование памяти" + +msgid "Services info" +msgstr "Информация о сервисах" + +msgid "Podkop" +msgstr "Podkop" + +msgid "\\u2714 Enabled" +msgstr "" + +msgid "\\u2718 Disabled" +msgstr "" + +msgid "Sing-box" +msgstr "Sing-box" + +msgid "\\u2714 Running" +msgstr "" + +msgid "\\u2718 Stopped" +msgstr "" + +msgid "Checking dns, please wait" +msgstr "" + +msgid "Cannot receive DNS checks result" +msgstr "" + +msgid "DNS checks passed" +msgstr "" + +msgid "Bootsrap DNS" +msgstr "" + +msgid "Main DNS" +msgstr "" + +msgid "DNS on router" +msgstr "" + +msgid "DHCP has DNS server" +msgstr "" + +msgid "Checking sing-box, please wait" +msgstr "" + +msgid "Cannot receive Sing-box checks result" +msgstr "" + +msgid "Sing-box checks passed" +msgstr "" + +msgid "Sing-box installed" +msgstr "" + +msgid "Sing-box version >= 1.12.4" +msgstr "" + +msgid "Sing-box service exist" +msgstr "" + +msgid "Sing-box autostart disabled" +msgstr "" + +msgid "Sing-box process running" +msgstr "" + +msgid "Sing-box listening ports" +msgstr "" + +msgid "Checking nftables, please wait" +msgstr "" + +msgid "Cannot receive nftables checks result" +msgstr "" + +msgid "Nftables checks passed" +msgstr "" + +msgid "Nftables checks partially passed" +msgstr "" + +msgid "Table exist" +msgstr "" + +msgid "Rules mangle exist" +msgstr "" + +msgid "Rules mangle counters" +msgstr "" + +msgid "Rules mangle output exist" +msgstr "" + +msgid "Rules mangle output counters" +msgstr "" + +msgid "Rules proxy exist" +msgstr "" + +msgid "Rules proxy counters" +msgstr "" + +msgid "No other marking rules found" +msgstr "" + +msgid "Additional marking rules found" +msgstr "" + +msgid "Checking FakeIP, please wait" +msgstr "" + +msgid "FakeIP checks passed" +msgstr "" + +msgid "FakeIP checks partially passed" +msgstr "" + +msgid "FakeIP checks failed" +msgstr "" + +msgid "Router DNS is routed through sing-box" +msgstr "" + +msgid "Router DNS is not routed through sing-box" +msgstr "" + +msgid "Browser is using FakeIP correctly" +msgstr "" + +msgid "Browser is not using FakeIP" +msgstr "" + +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +msgid "Successfully copied!" +msgstr "" + +msgid "Failed to copy!" +msgstr "" + +msgid "Download" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Close" +msgstr "Закрыть" + +msgid "Restart podkop" +msgstr "" + +msgid "Stop podkop" +msgstr "" + +msgid "Start podkop" +msgstr "" + +msgid "Disable autostart" +msgstr "" + +msgid "Enable autostart" +msgstr "" + +msgid "Get global check" +msgstr "" + +msgid "View logs" +msgstr "" + +msgid "Show sing-box config" +msgstr "" + +msgid "Not implement yet" +msgstr "" + +msgid "Run Diagnostic" +msgstr "" + +msgid "unknown" +msgstr "" + +msgid "Global check" +msgstr "Глобальная проверка" + +msgid "Outdated" +msgstr "" + +msgid "Latest" +msgstr "" + +msgid "Operation timed out" +msgstr "Время ожидания истекло" + +msgid "Podkop Settings" +msgstr "" + +msgid "Configuration for Podkop service" +msgstr "" + +msgid "Sections" +msgstr "" + +msgid "Settings" +msgstr "" + +msgid "Diagnostics" +msgstr "Диагностика" + +msgid "Dashboard" +msgstr "Дашборд" + +msgid "Connection Type" +msgstr "Тип подключения" + +msgid "Select between VPN and Proxy connection methods for traffic routing" +msgstr "Выберите между VPN и Proxy методами для маршрутизации трафика" + +msgid "Configuration Type" +msgstr "Тип конфигурации" + +msgid "Select how to configure the proxy" +msgstr "Выберите способ настройки прокси" + +msgid "Connection URL" +msgstr "URL подключения" + +msgid "Outbound Config" +msgstr "Конфигурация Outbound" + +msgid "URLTest" +msgstr "URLTest" + +msgid "Proxy Configuration URL" +msgstr "URL конфигурации прокси" + +msgid "Outbound Configuration" +msgstr "Конфигурация исходящего соединения" + +msgid "Enter complete outbound configuration in JSON format" +msgstr "Введите полную конфигурацию исходящего соединения в формате JSON" + +msgid "URLTest Proxy Links" +msgstr "Ссылки прокси для URLTest" + +msgid "UDP over TCP" +msgstr "" + +msgid "Applicable for SOCKS and Shadowsocks proxy" +msgstr "" + +msgid "Network Interface" +msgstr "Сетевой интерфейс" + +msgid "Select network interface for VPN connection" +msgstr "Выберите сетевой интерфейс для VPN подключения" + +msgid "Domain Resolver" +msgstr "Резолвер доменов" + +msgid "Enable built-in DNS resolver for domains handled by this section" +msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе" + +msgid "DNS Protocol Type" +msgstr "Тип протокола DNS" + +msgid "Select the DNS protocol type for the domain resolver" +msgstr "Выберите тип протокола DNS для резолвера доменов" + +msgid "DNS over HTTPS (DoH)" +msgstr "DNS через HTTPS (DoH)" + +msgid "DNS over TLS (DoT)" +msgstr "DNS через TLS (DoT)" + +msgid "UDP (Unprotected DNS)" +msgstr "UDP (Незащищённый DNS)" + +msgid "DNS Server" +msgstr "DNS-сервер" + +msgid "Select or enter DNS server address" +msgstr "Выберите или введите адрес DNS-сервера" + +msgid "" +msgstr "" + +msgid "Community Lists" +msgstr "Списки сообщества" + +msgid "Select a predefined list for routing" +msgstr "" + +msgid "Regional options cannot be used together" +msgstr "Нельзя использовать несколько региональных опций одновременно" + +msgid "Warning: %s cannot be used together with %s. Previous selections have been removed." +msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены." + +msgid "Russia inside restrictions" +msgstr "Ограничения Russia inside" + +msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." +msgstr "" + +msgid "User Domain List Type" +msgstr "Тип пользовательского списка доменов" + +msgid "Select the list type for adding custom domains" +msgstr "" + +msgid "Disabled" +msgstr "Отключено" + +msgid "Dynamic List" +msgstr "Динамический список" + +msgid "Text List" +msgstr "Текстовый список" + +msgid "User Domains" +msgstr "Пользовательские домены" + +msgid "Enter domain names without protocols, e.g. example.com or sub.example.com" +msgstr "" + +msgid "User Domains List" +msgstr "Список пользовательских доменов" + +msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //" +msgstr "" + +msgid "At least one valid domain must be specified. Comments-only content is not allowed." +msgstr "Необходимо указать хотя бы один действительный домен. Содержимое только из комментариев не допускается." + +msgid "${validation.value}: ${validation.message}" +msgstr "" + +msgid "Validation errors:" +msgstr "Ошибки валидации:" + +msgid "User Subnet List Type" +msgstr "Тип пользовательского списка подсетей" + +msgid "Select the list type for adding custom subnets" +msgstr "" + +msgid "Text List (comma/space/newline separated)" +msgstr "Текстовый список (через запятую, пробел или новую строку)" + +msgid "User Subnets" +msgstr "Пользовательские подсети" + +msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses" +msgstr "" + +msgid "User Subnets List" +msgstr "Список пользовательских подсетей" + +msgid "Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //" +msgstr "" + +msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." +msgstr "Необходимо указать хотя бы одну действительную подсеть или IP. Только комментарии недопустимы." + +msgid "Local Domain Lists" +msgstr "Локальные списки доменов" + +msgid "Specify the path to the list file located on the router filesystem" +msgstr "" + +msgid "Local Subnet Lists" +msgstr "Локальные списки подсетей" + +msgid "Remote Domain Lists" +msgstr "Удалённые списки доменов" + +msgid "Specify remote URLs to download and use domain lists" +msgstr "" + +msgid "Remote Subnet Lists" +msgstr "Удалённые списки подсетей" + +msgid "Specify remote URLs to download and use subnet lists" +msgstr "" + +msgid "Fully Routed IPs" +msgstr "" + +msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route" +msgstr "" + +msgid "Enable Mixed Proxy" +msgstr "" + +msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies" +msgstr "" + +msgid "Mixed Proxy Port" +msgstr "" + +msgid "Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service" +msgstr "" + +msgid "Select DNS protocol to use" +msgstr "Выберите протокол DNS" + +msgid "Bootstrap DNS server" +msgstr "Bootstrap DNS-сервер" + +msgid "The DNS server used to look up the IP address of an upstream DNS server" +msgstr "DNS-сервер, используемый для поиска IP-адреса вышестоящего DNS-сервера" + +msgid "DNS Rewrite TTL" +msgstr "Перезапись TTL для DNS" + +msgid "Time in seconds for DNS record caching (default: 60)" +msgstr "Время в секундах для кэширования DNS записей (по умолчанию: 60)" + +msgid "TTL value cannot be empty" +msgstr "Значение TTL не может быть пустым" + +msgid "TTL must be a positive number" +msgstr "TTL должно быть положительным числом" + +msgid "Source Network Interface" +msgstr "Сетевой интерфейс источника" + +msgid "Select the network interface from which the traffic will originate" +msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик" + +msgid "Enable Output Network Interface" +msgstr "" + +msgid "You can select Output Network Interface, by default autodetect" +msgstr "" + +msgid "Output Network Interface" +msgstr "" + +msgid "Select the network interface to which the traffic will originate" +msgstr "" + +msgid "Interface Monitoring" +msgstr "" + +msgid "Interface monitoring for Bad WAN" +msgstr "" + +msgid "Monitored Interfaces" +msgstr "" + +msgid "Select the WAN interfaces to be monitored" +msgstr "Выберите WAN интерфейсы для мониторинга" + +msgid "Interface Monitoring Delay" +msgstr "Задержка при мониторинге интерфейсов" + +msgid "Delay in milliseconds before reloading podkop after interface UP" +msgstr "Задержка в миллисекундах перед перезагрузкой podkop после поднятия интерфейса" + +msgid "Delay value cannot be empty" +msgstr "Значение задержки не может быть пустым" + +msgid "Enable YACD" +msgstr "" + +msgid "Disable QUIC" +msgstr "" + +msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming" +msgstr "" + +msgid "List Update Frequency" +msgstr "Частота обновления списков" + +msgid "Select how often the domain or subnet lists are updated automatically" +msgstr "" + +msgid "Download Lists via Proxy/VPN" +msgstr "" + +msgid "Downloading all lists via main Proxy/VPN" +msgstr "Загрузка всех списков через основной прокси/VPN" + +msgid "Download Lists via specific proxy section" +msgstr "" + +msgid "Downloading all lists via specific Proxy/VPN" +msgstr "" + +msgid "Dont Touch My DHCP!" +msgstr "" + +msgid "Podkop will not modify your DHCP configuration" +msgstr "" + +msgid "Config File Path" +msgstr "Путь к файлу конфигурации" + +msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing" +msgstr "Выберите путь к файлу конфигурации sing-box. Изменяйте это, ТОЛЬКО если вы знаете, что делаете" + +msgid "Cache File Path" +msgstr "Путь к файлу кэша" + +msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing" +msgstr "Выберите или введите путь к файлу кеша sing-box. Изменяйте это, ТОЛЬКО если вы знаете, что делаете" + +msgid "Cache file path cannot be empty" +msgstr "Путь к файлу кэша не может быть пустым" + +msgid "Path must be absolute (start with /)" +msgstr "Путь должен быть абсолютным (начинаться с /)" + +msgid "Path must end with cache.db" +msgstr "Путь должен заканчиваться на cache.db" + +msgid "Path must contain at least one directory (like /tmp/cache.db)" +msgstr "Путь должен содержать хотя бы одну директорию (например /tmp/cache.db)" + +msgid "Exclude NTP" +msgstr "Исключить NTP" + +msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN" +msgstr "" + +msgid "Routing Excluded IPs" +msgstr "" + +msgid "Specify a local IP address to be excluded from routing" +msgstr "" diff --git a/fe-app-podkop/package.json b/fe-app-podkop/package.json index 8eeb286..1b8a4bd 100644 --- a/fe-app-podkop/package.json +++ b/fe-app-podkop/package.json @@ -12,7 +12,12 @@ "dev": "tsup src/main.ts --watch", "test": "vitest", "ci": "yarn format && yarn lint --max-warnings=0 && yarn test --run && yarn build", - "watch:sftp": "node watch-upload.js" + "watch:sftp": "node watch-upload.js", + "locales:exctract-calls": "node extract-calls.js", + "locales:generate-pot": "node generate-pot.js", + "locales:generate-po:ru": "node generate-po.js ru", + "locales:distribute": "node distribute-locales.js", + "locales:actualize": "yarn locales:exctract-calls && yarn locales:generate-pot && yarn locales:generate-po:ru && yarn locales:distribute" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "8.45.0", @@ -21,6 +26,7 @@ "dotenv": "17.2.3", "eslint": "9.36.0", "eslint-config-prettier": "10.1.8", + "fast-glob": "3.3.3", "glob": "11.0.3", "prettier": "3.6.2", "ssh2-sftp-client": "12.0.1", diff --git a/fe-app-podkop/yarn.lock b/fe-app-podkop/yarn.lock index 93738ea..62d5fe2 100644 --- a/fe-app-podkop/yarn.lock +++ b/fe-app-podkop/yarn.lock @@ -996,6 +996,17 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-glob@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + fast-glob@^3.3.2: version "3.3.3" resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js index 81d7460..9f60cd7 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js @@ -1,4 +1,4 @@ -// This file is autogenerated, please don't change manually +// This file is autogenerated, please don't change manually "use strict"; "require baseclass"; "require fs"; @@ -7,8 +7,7 @@ // src/validators/validateIp.ts function validateIPV4(ip) { - const ipRegex = - /^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/; + const ipRegex = /^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/; if (ipRegex.test(ip)) { return { valid: true, message: _("Valid") }; } @@ -17,8 +16,7 @@ function validateIPV4(ip) { // src/validators/validateDomain.ts function validateDomain(domain, allowDotTLD = false) { - const domainRegex = - /^(?=.{1,253}(?:\/|$))(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9-]{1,59}[a-zA-Z0-9])(?:\/[^\s]*)?$/; + const domainRegex = /^(?=.{1,253}(?:\/|$))(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9-]{1,59}[a-zA-Z0-9])(?:\/[^\s]*)?$/; if (allowDotTLD) { const dotTLD = /^\.[a-zA-Z]{2,}$/; if (dotTLD.test(domain)) { @@ -51,8 +49,8 @@ function validateDNS(value) { return { valid: false, message: _( - "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH", - ), + "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" + ) }; } @@ -63,7 +61,7 @@ function validateUrl(url, protocols = ["http:", "https:"]) { if (!protocols.includes(parsedUrl.protocol)) { return { valid: false, - message: `${_("URL must use one of the following protocols:")} ${protocols.join(", ")}`, + message: `${_("URL must use one of the following protocols:")} ${protocols.join(", ")}` }; } return { valid: true, message: _("Valid") }; @@ -77,21 +75,21 @@ function validatePath(value) { if (!value) { return { valid: false, - message: _("Path cannot be empty"), + message: _("Path cannot be empty") }; } const pathRegex = /^\/[a-zA-Z0-9_\-/.]+$/; if (pathRegex.test(value)) { return { valid: true, - message: _("Valid"), + message: _("Valid") }; } return { valid: false, message: _( - 'Invalid path format. Path must start with "/" and contain valid characters', - ), + 'Invalid path format. Path must start with "/" and contain valid characters' + ) }; } @@ -101,7 +99,7 @@ function validateSubnet(value) { if (!subnetRegex.test(value)) { return { valid: false, - message: _("Invalid format. Use X.X.X.X or X.X.X.X/Y"), + message: _("Invalid format. Use X.X.X.X or X.X.X.X/Y") }; } const [ip, cidr] = value.split("/"); @@ -117,7 +115,7 @@ function validateSubnet(value) { if (cidrNum < 0 || cidrNum > 32) { return { valid: false, - message: _("CIDR must be between 0 and 32"), + message: _("CIDR must be between 0 and 32") }; } } @@ -129,7 +127,7 @@ function bulkValidate(values, validate) { const results = values.map((value) => ({ ...validate(value), value })); return { valid: results.every((r) => r.valid), - results, + results }; } @@ -138,14 +136,14 @@ function validateShadowsocksUrl(url) { if (!url.startsWith("ss://")) { return { valid: false, - message: _("Invalid Shadowsocks URL: must start with ss://"), + message: _("Invalid Shadowsocks URL: must start with ss://") }; } try { if (!url || /\s/.test(url)) { return { valid: false, - message: _("Invalid Shadowsocks URL: must not contain spaces"), + message: _("Invalid Shadowsocks URL: must not contain spaces") }; } const mainPart = url.includes("?") ? url.split("?")[0] : url.split("#")[0]; @@ -153,7 +151,7 @@ function validateShadowsocksUrl(url) { if (!encryptedPart) { return { valid: false, - message: _("Invalid Shadowsocks URL: missing credentials"), + message: _("Invalid Shadowsocks URL: missing credentials") }; } try { @@ -162,8 +160,8 @@ function validateShadowsocksUrl(url) { return { valid: false, message: _( - "Invalid Shadowsocks URL: decoded credentials must contain method:password", - ), + "Invalid Shadowsocks URL: decoded credentials must contain method:password" + ) }; } } catch (_e) { @@ -171,8 +169,8 @@ function validateShadowsocksUrl(url) { return { valid: false, message: _( - 'Invalid Shadowsocks URL: missing method and password separator ":"', - ), + 'Invalid Shadowsocks URL: missing method and password separator ":"' + ) }; } } @@ -180,34 +178,34 @@ function validateShadowsocksUrl(url) { if (!serverPart) { return { valid: false, - message: _("Invalid Shadowsocks URL: missing server address"), + message: _("Invalid Shadowsocks URL: missing server address") }; } const [server, portAndRest] = serverPart.split(":"); if (!server) { return { valid: false, - message: _("Invalid Shadowsocks URL: missing server"), + message: _("Invalid Shadowsocks URL: missing server") }; } const port = portAndRest ? portAndRest.split(/[?#]/)[0] : null; if (!port) { return { valid: false, - message: _("Invalid Shadowsocks URL: missing port"), + message: _("Invalid Shadowsocks URL: missing port") }; } const portNum = parseInt(port, 10); if (isNaN(portNum) || portNum < 1 || portNum > 65535) { return { valid: false, - message: _("Invalid port number. Must be between 1 and 65535"), + message: _("Invalid port number. Must be between 1 and 65535") }; } } catch (_e) { return { valid: false, - message: _("Invalid Shadowsocks URL: parsing failed"), + message: _("Invalid Shadowsocks URL: parsing failed") }; } return { valid: true, message: _("Valid") }; @@ -216,10 +214,8 @@ function validateShadowsocksUrl(url) { // src/helpers/parseQueryString.ts function parseQueryString(query) { const clean = query.startsWith("?") ? query.slice(1) : query; - return clean - .split("&") - .filter(Boolean) - .reduce((acc, pair) => { + return clean.split("&").filter(Boolean).reduce( + (acc, pair) => { const [rawKey, rawValue = ""] = pair.split("="); if (!rawKey) { return acc; @@ -227,7 +223,9 @@ function parseQueryString(query) { const key = decodeURIComponent(rawKey); const value = decodeURIComponent(rawValue); return { ...acc, [key]: value }; - }, {}); + }, + {} + ); } // src/validators/validateVlessUrl.ts @@ -236,12 +234,12 @@ function validateVlessUrl(url) { if (!url.startsWith("vless://")) return { valid: false, - message: "Invalid VLESS URL: must start with vless://", + message: "Invalid VLESS URL: must start with vless://" }; if (/\s/.test(url)) return { valid: false, - message: "Invalid VLESS URL: must not contain spaces", + message: "Invalid VLESS URL: must not contain spaces" }; const body = url.slice("vless://".length); const [mainPart] = body.split("#"); @@ -249,7 +247,7 @@ function validateVlessUrl(url) { if (!userHostPort) return { valid: false, - message: "Invalid VLESS URL: missing host and UUID", + message: "Invalid VLESS URL: missing host and UUID" }; const [userPart, hostPortPart] = userHostPort.split("@"); if (!userPart) @@ -265,12 +263,12 @@ function validateVlessUrl(url) { if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) return { valid: false, - message: "Invalid VLESS URL: invalid port number", + message: "Invalid VLESS URL: invalid port number" }; if (!queryString) return { valid: false, - message: "Invalid VLESS URL: missing query parameters", + message: "Invalid VLESS URL: missing query parameters" }; const params = parseQueryString(queryString); const validTypes = [ @@ -282,36 +280,35 @@ function validateVlessUrl(url) { "httpupgrade", "xhttp", "ws", - "kcp", + "kcp" ]; const validSecurities = ["tls", "reality", "none"]; if (!params.type || !validTypes.includes(params.type)) return { valid: false, - message: "Invalid VLESS URL: unsupported or missing type", + message: "Invalid VLESS URL: unsupported or missing type" }; if (!params.security || !validSecurities.includes(params.security)) return { valid: false, - message: "Invalid VLESS URL: unsupported or missing security", + message: "Invalid VLESS URL: unsupported or missing security" }; if (params.security === "reality") { if (!params.pbk) return { valid: false, - message: "Invalid VLESS URL: missing pbk for reality", + message: "Invalid VLESS URL: missing pbk for reality" }; if (!params.fp) return { valid: false, - message: "Invalid VLESS URL: missing fp for reality", + message: "Invalid VLESS URL: missing fp for reality" }; } if (params.flow === "xtls-rprx-vision-udp443") { return { valid: false, - message: - "Invalid VLESS URL: flow xtls-rprx-vision-udp443 does not supported", + message: "Invalid VLESS URL: flow xtls-rprx-vision-udp443 does not supported" }; } return { valid: true, message: _("Valid") }; @@ -328,8 +325,8 @@ function validateOutboundJson(value) { return { valid: false, message: _( - 'Outbound JSON must contain at least "type", "server" and "server_port" fields', - ), + 'Outbound JSON must contain at least "type", "server" and "server_port" fields' + ) }; } return { valid: true, message: _("Valid") }; @@ -344,13 +341,13 @@ function validateTrojanUrl(url) { if (!url.startsWith("trojan://")) { return { valid: false, - message: _("Invalid Trojan URL: must start with trojan://"), + message: _("Invalid Trojan URL: must start with trojan://") }; } if (!url || /\s/.test(url)) { return { valid: false, - message: _("Invalid Trojan URL: must not contain spaces"), + message: _("Invalid Trojan URL: must not contain spaces") }; } const body = url.slice("trojan://".length); @@ -360,14 +357,14 @@ function validateTrojanUrl(url) { if (!userHostPort) return { valid: false, - message: "Invalid Trojan URL: missing credentials and host", + message: "Invalid Trojan URL: missing credentials and host" }; if (!userPart) return { valid: false, message: "Invalid Trojan URL: missing password" }; if (!hostPortPart) return { valid: false, - message: "Invalid Trojan URL: missing hostname and port", + message: "Invalid Trojan URL: missing hostname and port" }; const [host, port] = hostPortPart.split(":"); if (!host) @@ -378,7 +375,7 @@ function validateTrojanUrl(url) { if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) return { valid: false, - message: "Invalid Trojan URL: invalid port number", + message: "Invalid Trojan URL: invalid port number" }; } catch (_e) { return { valid: false, message: _("Invalid Trojan URL: parsing failed") }; @@ -393,41 +390,39 @@ function validateSocksUrl(url) { return { valid: false, message: _( - "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://", - ), + "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" + ) }; } if (!url || /\s/.test(url)) { return { valid: false, - message: _("Invalid SOCKS URL: must not contain spaces"), + message: _("Invalid SOCKS URL: must not contain spaces") }; } const body = url.replace(/^socks(4|4a|5):\/\//, ""); const [authAndHost] = body.split("#"); - const [credentials, hostPortPart] = authAndHost.includes("@") - ? authAndHost.split("@") - : [null, authAndHost]; + const [credentials, hostPortPart] = authAndHost.includes("@") ? authAndHost.split("@") : [null, authAndHost]; if (credentials) { const [username, _password] = credentials.split(":"); if (!username) { return { valid: false, - message: _("Invalid SOCKS URL: missing username"), + message: _("Invalid SOCKS URL: missing username") }; } } if (!hostPortPart) { return { valid: false, - message: _("Invalid SOCKS URL: missing host and port"), + message: _("Invalid SOCKS URL: missing host and port") }; } const [host, port] = hostPortPart.split(":"); if (!host) { return { valid: false, - message: _("Invalid SOCKS URL: missing hostname or IP"), + message: _("Invalid SOCKS URL: missing hostname or IP") }; } if (!port) { @@ -437,7 +432,7 @@ function validateSocksUrl(url) { if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) { return { valid: false, - message: _("Invalid SOCKS URL: invalid port number"), + message: _("Invalid SOCKS URL: invalid port number") }; } const ipv4Result = validateIPV4(host); @@ -445,7 +440,7 @@ function validateSocksUrl(url) { if (!ipv4Result.valid && !domainResult.valid) { return { valid: false, - message: _("Invalid SOCKS URL: invalid host format"), + message: _("Invalid SOCKS URL: invalid host format") }; } } catch (_e) { @@ -471,20 +466,14 @@ function validateProxyUrl(url) { return { valid: false, message: _( - "URL must start with vless://, ss://, trojan://, or socks4/5://", - ), + "URL must start with vless://, ss://, trojan://, or socks4/5://" + ) }; } // src/helpers/parseValueList.ts function parseValueList(value) { - return value - .split(/\n/) - .map((line) => line.split("//")[0]) - .join(" ") - .split(/[,\s]+/) - .map((s) => s.trim()) - .filter(Boolean); + return value.split(/\n/).map((line) => line.split("//")[0]).join(" ").split(/[,\s]+/).map((s) => s.trim()).filter(Boolean); } // src/podkop/methods/custom/getConfigSections.ts @@ -497,24 +486,24 @@ async function callBaseMethod(method, args = [], command = "/usr/bin/podkop") { const response = await executeShellCommand({ command, args: [method, ...args], - timeout: 1e4, + timeout: 1e4 }); if (response.stdout) { try { return { success: true, - data: JSON.parse(response.stdout), + data: JSON.parse(response.stdout) }; } catch (_e) { return { success: true, - data: response.stdout, + data: response.stdout }; } } return { success: false, - error: "", + error: "" }; } @@ -539,71 +528,81 @@ var Podkop; AvailableMethods2["SHOW_SING_BOX_CONFIG"] = "show_sing_box_config"; AvailableMethods2["CHECK_LOGS"] = "check_logs"; AvailableMethods2["GET_SYSTEM_INFO"] = "get_system_info"; - })( - (AvailableMethods = - Podkop2.AvailableMethods || (Podkop2.AvailableMethods = {})), - ); + })(AvailableMethods = Podkop2.AvailableMethods || (Podkop2.AvailableMethods = {})); let AvailableClashAPIMethods; ((AvailableClashAPIMethods2) => { AvailableClashAPIMethods2["GET_PROXIES"] = "get_proxies"; AvailableClashAPIMethods2["GET_PROXY_LATENCY"] = "get_proxy_latency"; AvailableClashAPIMethods2["GET_GROUP_LATENCY"] = "get_group_latency"; AvailableClashAPIMethods2["SET_GROUP_PROXY"] = "set_group_proxy"; - })( - (AvailableClashAPIMethods = - Podkop2.AvailableClashAPIMethods || - (Podkop2.AvailableClashAPIMethods = {})), - ); + })(AvailableClashAPIMethods = Podkop2.AvailableClashAPIMethods || (Podkop2.AvailableClashAPIMethods = {})); })(Podkop || (Podkop = {})); // src/podkop/methods/shell/index.ts var PodkopShellMethods = { - checkDNSAvailable: async () => - callBaseMethod(Podkop.AvailableMethods.CHECK_DNS_AVAILABLE), - checkFakeIP: async () => callBaseMethod(Podkop.AvailableMethods.CHECK_FAKEIP), - checkNftRules: async () => - callBaseMethod(Podkop.AvailableMethods.CHECK_NFT_RULES), + checkDNSAvailable: async () => callBaseMethod( + Podkop.AvailableMethods.CHECK_DNS_AVAILABLE + ), + checkFakeIP: async () => callBaseMethod( + Podkop.AvailableMethods.CHECK_FAKEIP + ), + checkNftRules: async () => callBaseMethod( + Podkop.AvailableMethods.CHECK_NFT_RULES + ), getStatus: async () => callBaseMethod(Podkop.AvailableMethods.GET_STATUS), - checkSingBox: async () => - callBaseMethod(Podkop.AvailableMethods.CHECK_SING_BOX), - getSingBoxStatus: async () => - callBaseMethod(Podkop.AvailableMethods.GET_SING_BOX_STATUS), - 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, - ]), - setClashApiGroupProxy: async (group, proxy) => - callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ - Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY, - group, - proxy, - ]), - restart: async () => - callBaseMethod(Podkop.AvailableMethods.RESTART, [], "/etc/init.d/podkop"), - start: async () => - callBaseMethod(Podkop.AvailableMethods.START, [], "/etc/init.d/podkop"), - stop: async () => - callBaseMethod(Podkop.AvailableMethods.STOP, [], "/etc/init.d/podkop"), - enable: async () => - callBaseMethod(Podkop.AvailableMethods.ENABLE, [], "/etc/init.d/podkop"), - disable: async () => - callBaseMethod(Podkop.AvailableMethods.DISABLE, [], "/etc/init.d/podkop"), + checkSingBox: async () => callBaseMethod( + Podkop.AvailableMethods.CHECK_SING_BOX + ), + getSingBoxStatus: async () => callBaseMethod( + Podkop.AvailableMethods.GET_SING_BOX_STATUS + ), + 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 + ]), + setClashApiGroupProxy: async (group, proxy) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ + Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY, + group, + proxy + ]), + restart: async () => callBaseMethod( + Podkop.AvailableMethods.RESTART, + [], + "/etc/init.d/podkop" + ), + start: async () => callBaseMethod( + Podkop.AvailableMethods.START, + [], + "/etc/init.d/podkop" + ), + stop: async () => callBaseMethod( + Podkop.AvailableMethods.STOP, + [], + "/etc/init.d/podkop" + ), + enable: async () => callBaseMethod( + Podkop.AvailableMethods.ENABLE, + [], + "/etc/init.d/podkop" + ), + disable: async () => callBaseMethod( + Podkop.AvailableMethods.DISABLE, + [], + "/etc/init.d/podkop" + ), globalCheck: async () => callBaseMethod(Podkop.AvailableMethods.GLOBAL_CHECK), - showSingBoxConfig: async () => - callBaseMethod(Podkop.AvailableMethods.SHOW_SING_BOX_CONFIG), + showSingBoxConfig: async () => callBaseMethod(Podkop.AvailableMethods.SHOW_SING_BOX_CONFIG), checkLogs: async () => callBaseMethod(Podkop.AvailableMethods.CHECK_LOGS), - getSystemInfo: async () => - callBaseMethod(Podkop.AvailableMethods.GET_SYSTEM_INFO), + getSystemInfo: async () => callBaseMethod( + Podkop.AvailableMethods.GET_SYSTEM_INFO + ) }; // src/podkop/methods/custom/getDashboardSections.ts @@ -613,108 +612,25 @@ async function getDashboardSections() { if (!clashProxies.success) { return { success: false, - data: [], + data: [] }; } const proxies = Object.entries(clashProxies.data.proxies).map( ([key, value]) => ({ code: key, - value, - }), + value + }) ); - const data = configSections - .filter( - (section) => - section.connection_type !== "block" && section[".type"] !== "settings", - ) - .map((section) => { - if (section.connection_type === "proxy") { - if (section.proxy_config_type === "url") { - const outbound = proxies.find( - (proxy) => proxy.code === `${section[".name"]}-out`, - ); - const activeConfigs = splitProxyString(section.proxy_string); - const proxyDisplayName = - getProxyUrlName(activeConfigs?.[0]) || outbound?.value?.name || ""; - return { - withTagSelect: false, - code: outbound?.code || section[".name"], - displayName: section[".name"], - outbounds: [ - { - code: outbound?.code || section[".name"], - displayName: proxyDisplayName, - latency: outbound?.value?.history?.[0]?.delay || 0, - type: outbound?.value?.type || "", - selected: true, - }, - ], - }; - } - if (section.proxy_config_type === "outbound") { - const outbound = proxies.find( - (proxy) => proxy.code === `${section[".name"]}-out`, - ); - const parsedOutbound = JSON.parse(section.outbound_json); - const parsedTag = parsedOutbound?.tag - ? decodeURIComponent(parsedOutbound?.tag) - : void 0; - const proxyDisplayName = parsedTag || outbound?.value?.name || ""; - return { - withTagSelect: false, - code: outbound?.code || section[".name"], - displayName: section[".name"], - outbounds: [ - { - code: outbound?.code || section[".name"], - displayName: proxyDisplayName, - latency: outbound?.value?.history?.[0]?.delay || 0, - type: outbound?.value?.type || "", - selected: true, - }, - ], - }; - } - if (section.proxy_config_type === "urltest") { - const selector = proxies.find( - (proxy) => proxy.code === `${section[".name"]}-out`, - ); - const outbound = proxies.find( - (proxy) => proxy.code === `${section[".name"]}-urltest-out`, - ); - const outbounds = (outbound?.value?.all ?? []) - .map((code) => proxies.find((item) => item.code === code)) - .map((item, index) => ({ - code: item?.code || "", - displayName: - getProxyUrlName(section.urltest_proxy_links?.[index]) || - item?.value?.name || - "", - latency: item?.value?.history?.[0]?.delay || 0, - type: item?.value?.type || "", - selected: selector?.value?.now === item?.code, - })); - return { - withTagSelect: true, - code: selector?.code || section[".name"], - displayName: section[".name"], - outbounds: [ - { - code: outbound?.code || "", - displayName: _("Fastest"), - latency: outbound?.value?.history?.[0]?.delay || 0, - type: outbound?.value?.type || "", - selected: selector?.value?.now === outbound?.code, - }, - ...outbounds, - ], - }; - } - } - if (section.connection_type === "vpn") { + const data = configSections.filter( + (section) => section.connection_type !== "block" && section[".type"] !== "settings" + ).map((section) => { + if (section.connection_type === "proxy") { + if (section.proxy_config_type === "url") { const outbound = proxies.find( - (proxy) => proxy.code === `${section[".name"]}-out`, + (proxy) => proxy.code === `${section[".name"]}-out` ); + const activeConfigs = splitProxyString(section.proxy_string); + const proxyDisplayName = getProxyUrlName(activeConfigs?.[0]) || outbound?.value?.name || ""; return { withTagSelect: false, code: outbound?.code || section[".name"], @@ -722,43 +638,119 @@ async function getDashboardSections() { outbounds: [ { code: outbound?.code || section[".name"], - displayName: section.interface || outbound?.value?.name || "", + displayName: proxyDisplayName, latency: outbound?.value?.history?.[0]?.delay || 0, type: outbound?.value?.type || "", - selected: true, - }, - ], + selected: true + } + ] }; } + if (section.proxy_config_type === "outbound") { + const outbound = proxies.find( + (proxy) => proxy.code === `${section[".name"]}-out` + ); + const parsedOutbound = JSON.parse(section.outbound_json); + const parsedTag = parsedOutbound?.tag ? decodeURIComponent(parsedOutbound?.tag) : void 0; + const proxyDisplayName = parsedTag || outbound?.value?.name || ""; + return { + withTagSelect: false, + code: outbound?.code || section[".name"], + displayName: section[".name"], + outbounds: [ + { + code: outbound?.code || section[".name"], + displayName: proxyDisplayName, + latency: outbound?.value?.history?.[0]?.delay || 0, + type: outbound?.value?.type || "", + selected: true + } + ] + }; + } + if (section.proxy_config_type === "urltest") { + const selector = proxies.find( + (proxy) => proxy.code === `${section[".name"]}-out` + ); + const outbound = proxies.find( + (proxy) => proxy.code === `${section[".name"]}-urltest-out` + ); + const outbounds = (outbound?.value?.all ?? []).map((code) => proxies.find((item) => item.code === code)).map((item, index) => ({ + code: item?.code || "", + displayName: getProxyUrlName(section.urltest_proxy_links?.[index]) || item?.value?.name || "", + latency: item?.value?.history?.[0]?.delay || 0, + type: item?.value?.type || "", + selected: selector?.value?.now === item?.code + })); + return { + withTagSelect: true, + code: selector?.code || section[".name"], + displayName: section[".name"], + outbounds: [ + { + code: outbound?.code || "", + displayName: _("Fastest"), + latency: outbound?.value?.history?.[0]?.delay || 0, + type: outbound?.value?.type || "", + selected: selector?.value?.now === outbound?.code + }, + ...outbounds + ] + }; + } + } + if (section.connection_type === "vpn") { + const outbound = proxies.find( + (proxy) => proxy.code === `${section[".name"]}-out` + ); return { withTagSelect: false, - code: section[".name"], + code: outbound?.code || section[".name"], displayName: section[".name"], - outbounds: [], + outbounds: [ + { + code: outbound?.code || section[".name"], + displayName: section.interface || outbound?.value?.name || "", + latency: outbound?.value?.history?.[0]?.delay || 0, + type: outbound?.value?.type || "", + selected: true + } + ] }; - }); + } + return { + withTagSelect: false, + code: section[".name"], + displayName: section[".name"], + outbounds: [] + }; + }); return { success: true, - data, + data }; } // src/podkop/methods/custom/index.ts var CustomPodkopMethods = { getConfigSections, - getDashboardSections, + getDashboardSections }; // src/constants.ts var STATUS_COLORS = { SUCCESS: "#4caf50", ERROR: "#f44336", - WARNING: "#ff9800", + WARNING: "#ff9800" }; var PODKOP_LUCI_APP_VERSION = "__COMPILED_VERSION_VARIABLE__"; var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi"; var IP_CHECK_DOMAIN = "ip.podkop.fyi"; -var REGIONAL_OPTIONS = ["russia_inside", "russia_outside", "ukraine_inside"]; +var REGIONAL_OPTIONS = [ + "russia_inside", + "russia_outside", + "ukraine_inside" +]; var ALLOWED_WITH_RUSSIA_INSIDE = [ "russia_inside", "meta", @@ -772,7 +764,7 @@ var ALLOWED_WITH_RUSSIA_INSIDE = [ "ovh", "hodca", "digitalocean", - "cloudfront", + "cloudfront" ]; var DOMAIN_LIST_OPTIONS = { russia_inside: "Russia inside", @@ -797,23 +789,22 @@ var DOMAIN_LIST_OPTIONS = { hetzner: "Hetzner ASN", ovh: "OVH ASN", digitalocean: "Digital Ocean ASN", - cloudfront: "CloudFront ASN", + cloudfront: "CloudFront ASN" }; var UPDATE_INTERVAL_OPTIONS = { "1h": "Every hour", "3h": "Every 3 hours", "12h": "Every 12 hours", "1d": "Every day", - "3d": "Every 3 days", + "3d": "Every 3 days" }; var DNS_SERVER_OPTIONS = { "1.1.1.1": "1.1.1.1 (Cloudflare)", "8.8.8.8": "8.8.8.8 (Google)", "9.9.9.9": "9.9.9.9 (Quad9)", "dns.adguard-dns.com": "dns.adguard-dns.com (AdGuard Default)", - "unfiltered.adguard-dns.com": - "unfiltered.adguard-dns.com (AdGuard Unfiltered)", - "family.adguard-dns.com": "family.adguard-dns.com (AdGuard Family)", + "unfiltered.adguard-dns.com": "unfiltered.adguard-dns.com (AdGuard Unfiltered)", + "family.adguard-dns.com": "family.adguard-dns.com (AdGuard Family)" }; var BOOTSTRAP_DNS_SERVER_OPTIONS = { "77.88.8.8": "77.88.8.8 (Yandex DNS)", @@ -823,7 +814,7 @@ var BOOTSTRAP_DNS_SERVER_OPTIONS = { "8.8.8.8": "8.8.8.8 (Google DNS)", "8.8.4.4": "8.8.4.4 (Google DNS)", "9.9.9.9": "9.9.9.9 (Quad9 DNS)", - "9.9.9.11": "9.9.9.11 (Quad9 DNS)", + "9.9.9.11": "9.9.9.11 (Quad9 DNS)" }; var DIAGNOSTICS_UPDATE_INTERVAL = 1e4; var CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1e3; @@ -853,38 +844,35 @@ var COMMAND_SCHEDULING = { // Background execution P9_PRIORITY: 1700, // Idle mode execution - P10_PRIORITY: 1900, + P10_PRIORITY: 1900 // Lowest priority }; // src/podkop/api.ts async function createBaseApiRequest(fetchFn, options) { - const wrappedFn = () => - options?.timeoutMs && options?.operationName - ? withTimeout( - fetchFn(), - options.timeoutMs, - options.operationName, - options.timeoutMessage, - ) - : fetchFn(); + const wrappedFn = () => options?.timeoutMs && options?.operationName ? withTimeout( + fetchFn(), + options.timeoutMs, + options.operationName, + options.timeoutMessage + ) : fetchFn(); try { const response = await wrappedFn(); if (!response.ok) { return { success: false, - message: `${_("HTTP error")} ${response.status}: ${response.statusText}`, + message: `${_("HTTP error")} ${response.status}: ${response.statusText}` }; } const data = await response.json(); return { success: true, - data, + data }; } catch (e) { return { success: false, - message: e instanceof Error ? e.message : _("Unknown error"), + message: e instanceof Error ? e.message : _("Unknown error") }; } } @@ -892,37 +880,35 @@ async function createBaseApiRequest(fetchFn, options) { // src/podkop/methods/fakeip/getFakeIpCheck.ts async function getFakeIpCheck() { return createBaseApiRequest( - () => - fetch(`https://${FAKEIP_CHECK_DOMAIN}/check`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }), + () => fetch(`https://${FAKEIP_CHECK_DOMAIN}/check`, { + method: "GET", + headers: { "Content-Type": "application/json" } + }), { operationName: "getFakeIpCheck", - timeoutMs: 5e3, - }, + timeoutMs: 5e3 + } ); } // src/podkop/methods/fakeip/getIpCheck.ts async function getIpCheck() { return createBaseApiRequest( - () => - fetch(`https://${IP_CHECK_DOMAIN}/check`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }), + () => fetch(`https://${IP_CHECK_DOMAIN}/check`, { + method: "GET", + headers: { "Content-Type": "application/json" } + }), { operationName: "getIpCheck", - timeoutMs: 5e3, - }, + timeoutMs: 5e3 + } ); } // src/podkop/methods/fakeip/index.ts var RemoteFakeIPMethods = { getFakeIpCheck, - getIpCheck, + getIpCheck }; // src/podkop/services/tab.service.ts @@ -944,7 +930,7 @@ var TabService = class _TabService { subtree: true, childList: true, attributes: true, - attributeFilter: ["class"], + attributeFilter: ["class"] }); this.notify(); } @@ -953,18 +939,18 @@ var TabService = class _TabService { } getTabsInfo() { const tabs = Array.from( - document.querySelectorAll(".cbi-tab, .cbi-tab-disabled"), + document.querySelectorAll(".cbi-tab, .cbi-tab-disabled") ); return tabs.map((el) => ({ el, id: el.dataset.tab || "", - active: - el.classList.contains("cbi-tab") && - !el.classList.contains("cbi-tab-disabled"), + active: el.classList.contains("cbi-tab") && !el.classList.contains("cbi-tab-disabled") })); } getActiveTabId() { - const active = document.querySelector(".cbi-tab:not(.cbi-tab-disabled)"); + const active = document.querySelector( + ".cbi-tab:not(.cbi-tab-disabled)" + ); return active?.dataset.tab || null; } notify() { @@ -997,23 +983,23 @@ var DIAGNOSTICS_CHECKS_MAP = { ["DNS" /* DNS */]: { order: 1, title: _("DNS checks"), - code: "DNS" /* DNS */, + code: "DNS" /* DNS */ }, ["SINGBOX" /* SINGBOX */]: { order: 2, title: _("Sing-box checks"), - code: "SINGBOX" /* SINGBOX */, + code: "SINGBOX" /* SINGBOX */ }, ["NFT" /* NFT */]: { order: 3, title: _("Nftables checks"), - code: "NFT" /* NFT */, + code: "NFT" /* NFT */ }, ["FAKEIP" /* FAKEIP */]: { order: 4, title: _("FakeIP checks"), - code: "FAKEIP" /* FAKEIP */, - }, + code: "FAKEIP" /* FAKEIP */ + } }; // src/podkop/tabs/diagnostic/diagnostic.store.ts @@ -1025,33 +1011,33 @@ var initialDiagnosticStore = { luci_app_version: "loading", sing_box_version: "loading", openwrt_version: "loading", - device_model: "loading", + device_model: "loading" }, diagnosticsActions: { restart: { - loading: false, + loading: false }, start: { - loading: false, + loading: false }, stop: { - loading: false, + loading: false }, enable: { - loading: false, + loading: false }, disable: { - loading: false, + loading: false }, globalCheck: { - loading: false, + loading: false }, viewLogs: { - loading: false, + loading: false }, showSingBoxConfig: { - loading: false, - }, + loading: false + } }, diagnosticsRunAction: { loading: false }, diagnosticsChecks: [ @@ -1061,7 +1047,7 @@ var initialDiagnosticStore = { order: DIAGNOSTICS_CHECKS_MAP.DNS.order, description: _("Not running"), items: [], - state: "skipped", + state: "skipped" }, { code: "SINGBOX" /* SINGBOX */, @@ -1069,7 +1055,7 @@ var initialDiagnosticStore = { order: DIAGNOSTICS_CHECKS_MAP.SINGBOX.order, description: _("Not running"), items: [], - state: "skipped", + state: "skipped" }, { code: "NFT" /* NFT */, @@ -1077,7 +1063,7 @@ var initialDiagnosticStore = { order: DIAGNOSTICS_CHECKS_MAP.NFT.order, description: _("Not running"), items: [], - state: "skipped", + state: "skipped" }, { code: "FAKEIP" /* FAKEIP */, @@ -1085,9 +1071,9 @@ var initialDiagnosticStore = { order: DIAGNOSTICS_CHECKS_MAP.FAKEIP.order, description: _("Not running"), items: [], - state: "skipped", - }, - ], + state: "skipped" + } + ] }; var loadingDiagnosticsChecksStore = { diagnosticsChecks: [ @@ -1097,7 +1083,7 @@ var loadingDiagnosticsChecksStore = { order: DIAGNOSTICS_CHECKS_MAP.DNS.order, description: _("Queued"), items: [], - state: "skipped", + state: "skipped" }, { code: "SINGBOX" /* SINGBOX */, @@ -1105,7 +1091,7 @@ var loadingDiagnosticsChecksStore = { order: DIAGNOSTICS_CHECKS_MAP.SINGBOX.order, description: _("Queued"), items: [], - state: "skipped", + state: "skipped" }, { code: "NFT" /* NFT */, @@ -1113,7 +1099,7 @@ var loadingDiagnosticsChecksStore = { order: DIAGNOSTICS_CHECKS_MAP.NFT.order, description: _("Queued"), items: [], - state: "skipped", + state: "skipped" }, { code: "FAKEIP" /* FAKEIP */, @@ -1121,21 +1107,22 @@ var loadingDiagnosticsChecksStore = { order: DIAGNOSTICS_CHECKS_MAP.FAKEIP.order, description: _("Queued"), items: [], - state: "skipped", - }, - ], + state: "skipped" + } + ] }; // src/podkop/services/store.service.ts function jsonStableStringify(obj) { return JSON.stringify(obj, (_2, value) => { if (value && typeof value === "object" && !Array.isArray(value)) { - return Object.keys(value) - .sort() - .reduce((acc, key) => { + return Object.keys(value).sort().reduce( + (acc, key) => { acc[key] = value[key]; return acc; - }, {}); + }, + {} + ); } return value; }); @@ -1218,35 +1205,35 @@ var StoreService = class { var initialStore = { tabService: { current: "", - all: [], + all: [] }, bandwidthWidget: { loading: true, failed: false, - data: { up: 0, down: 0 }, + data: { up: 0, down: 0 } }, trafficTotalWidget: { loading: true, failed: false, - data: { downloadTotal: 0, uploadTotal: 0 }, + data: { downloadTotal: 0, uploadTotal: 0 } }, systemInfoWidget: { loading: true, failed: false, - data: { connections: 0, memory: 0 }, + data: { connections: 0, memory: 0 } }, servicesInfoWidget: { loading: true, failed: false, - data: { singbox: 0, podkop: 0 }, + data: { singbox: 0, podkop: 0 } }, sectionsWidget: { loading: true, failed: false, latencyFetching: false, - data: [], + data: [] }, - ...initialDiagnosticStore, + ...initialDiagnosticStore }; var store = new StoreService(initialStore); @@ -1310,9 +1297,7 @@ var Logger = class { } download(filename = "logs.txt") { if (typeof document === "undefined") { - console.warn( - "Logger.download() \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435", - ); + console.warn("Logger.download() \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435"); return; } downloadAsTxt(this.getLogs(), filename); @@ -1346,7 +1331,7 @@ var PodkopLogWatcher = class _PodkopLogWatcher { this.intervalMs = options?.intervalMs ?? 5e3; logger.info( "[PodkopLogWatcher]", - `initialized (interval: ${this.intervalMs}ms)`, + `initialized (interval: ${this.intervalMs}ms)` ); } async checkOnce() { @@ -1355,10 +1340,7 @@ var PodkopLogWatcher = class _PodkopLogWatcher { return; } if (this.paused) { - logger.debug( - "[PodkopLogWatcher]", - "skipped check \u2014 tab not visible", - ); + logger.debug("[PodkopLogWatcher]", "skipped check \u2014 tab not visible"); return; } try { @@ -1388,7 +1370,7 @@ var PodkopLogWatcher = class _PodkopLogWatcher { this.timer = setInterval(() => this.checkOnce(), this.intervalMs); logger.info( "[PodkopLogWatcher]", - `started (interval: ${this.intervalMs}ms)`, + `started (interval: ${this.intervalMs}ms)` ); } stop() { @@ -1421,8 +1403,8 @@ function coreService() { store.set({ tabService: { current: activeId || "", - all: tabs.map((tab) => tab.id), - }, + all: tabs.map((tab) => tab.id) + } }); }); const watcher = PodkopLogWatcher.getInstance(); @@ -1437,14 +1419,11 @@ function coreService() { { intervalMs: 3e3, onNewLog: (line) => { - if ( - line.toLowerCase().includes("[error]") || - line.toLowerCase().includes("[fatal]") - ) { + if (line.toLowerCase().includes("[error]") || line.toLowerCase().includes("[fatal]")) { ui.addNotification("Podkop Error", E("div", {}, line), "error"); } - }, - }, + } + } ); watcher.start(); } @@ -1466,17 +1445,14 @@ var SocketManager = class _SocketManager { resetAll() { for (const [url, ws] of this.sockets.entries()) { try { - if ( - ws.readyState === WebSocket.OPEN || - ws.readyState === WebSocket.CONNECTING - ) { + if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { ws.close(); } } catch (err) { logger.error( "[SOCKET]", `resetAll: failed to close socket ${url}`, - err, + err ); } } @@ -1495,7 +1471,7 @@ var SocketManager = class _SocketManager { logger.error( "[SOCKET]", `failed to construct WebSocket for ${url}:`, - err, + err ); this.triggerError(url, err instanceof Event ? err : String(err)); return; @@ -1597,23 +1573,23 @@ function renderFailedState() { "div", { class: "pdk_dashboard-page__outbound-section centered", - style: "height: 127px", + style: "height: 127px" }, - E("span", {}, [E("span", {}, _("Dashboard currently unavailable"))]), + E("span", {}, [E("span", {}, _("Dashboard currently unavailable"))]) ); } function renderLoadingState() { return E("div", { id: "dashboard-sections-grid-skeleton", class: "pdk_dashboard-page__outbound-section skeleton", - style: "height: 127px", + style: "height: 127px" }); } function renderDefaultState({ section, onChooseOutbound, onTestLatency, - latencyFetching, + latencyFetching }) { function testLatency() { if (section.withTagSelect) { @@ -1640,9 +1616,7 @@ function renderDefaultState({ "div", { class: `pdk_dashboard-page__outbound-grid__item ${outbound.selected ? "pdk_dashboard-page__outbound-grid__item--active" : ""} ${section.withTagSelect ? "pdk_dashboard-page__outbound-grid__item--selectable" : ""}`, - click: () => - section.withTagSelect && - onChooseOutbound(section.code, outbound.code), + click: () => section.withTagSelect && onChooseOutbound(section.code, outbound.code) }, [ E("b", {}, outbound.displayName), @@ -1650,15 +1624,15 @@ function renderDefaultState({ E( "div", { class: "pdk_dashboard-page__outbound-grid__item__type" }, - outbound.type, + outbound.type ), E( "div", { class: getLatencyClass() }, - outbound.latency ? `${outbound.latency}ms` : "N/A", - ), - ]), - ], + outbound.latency ? `${outbound.latency}ms` : "N/A" + ) + ]) + ] ); } return E("div", { class: "pdk_dashboard-page__outbound-section" }, [ @@ -1667,26 +1641,24 @@ function renderDefaultState({ E( "div", { - class: "pdk_dashboard-page__outbound-section__title-section__title", + class: "pdk_dashboard-page__outbound-section__title-section__title" }, - section.displayName, + section.displayName ), - latencyFetching - ? E("div", { class: "skeleton", style: "width: 99px; height: 28px" }) - : E( - "button", - { - class: "btn dashboard-sections-grid-item-test-latency", - click: () => testLatency(), - }, - _("Test latency"), - ), + latencyFetching ? E("div", { class: "skeleton", style: "width: 99px; height: 28px" }) : E( + "button", + { + class: "btn dashboard-sections-grid-item-test-latency", + click: () => testLatency() + }, + _("Test latency") + ) ]), E( "div", { class: "pdk_dashboard-page__outbound-grid" }, - section.outbounds.map((outbound) => renderOutbound(outbound)), - ), + section.outbounds.map((outbound) => renderOutbound(outbound)) + ) ]); } function renderSections(props) { @@ -1706,9 +1678,9 @@ function renderFailedState2() { { id: "", style: "height: 78px", - class: "pdk_dashboard-page__widgets-section__item centered", + class: "pdk_dashboard-page__widgets-section__item centered" }, - _("Currently unavailable"), + _("Currently unavailable") ); } function renderLoadingState2() { @@ -1717,9 +1689,9 @@ function renderLoadingState2() { { id: "", style: "height: 78px", - class: "pdk_dashboard-page__widgets-section__item skeleton", + class: "pdk_dashboard-page__widgets-section__item skeleton" }, - "", + "" ); } function renderDefaultState2({ title, items }) { @@ -1727,28 +1699,28 @@ function renderDefaultState2({ title, items }) { E( "b", { class: "pdk_dashboard-page__widgets-section__item__title" }, - title, + title ), - ...items.map((item) => - E( + ...items.map( + (item) => E( "div", { - class: `pdk_dashboard-page__widgets-section__item__row ${item?.attributes?.class || ""}`, + class: `pdk_dashboard-page__widgets-section__item__row ${item?.attributes?.class || ""}` }, [ E( "span", { class: "pdk_dashboard-page__widgets-section__item__row__key" }, - `${item.key}: `, + `${item.key}: ` ), E( "span", { class: "pdk_dashboard-page__widgets-section__item__row__value" }, - item.value, - ), - ], - ), - ), + item.value + ) + ] + ) + ) ]); } function renderWidget(props) { @@ -1767,7 +1739,7 @@ function render() { "div", { id: "dashboard-status", - class: "pdk_dashboard-page", + class: "pdk_dashboard-page" }, [ // Widgets section @@ -1775,23 +1747,23 @@ function render() { E( "div", { id: "dashboard-widget-traffic" }, - renderWidget({ loading: true, failed: false, title: "", items: [] }), + renderWidget({ loading: true, failed: false, title: "", items: [] }) ), E( "div", { id: "dashboard-widget-traffic-total" }, - renderWidget({ loading: true, failed: false, title: "", items: [] }), + renderWidget({ loading: true, failed: false, title: "", items: [] }) ), E( "div", { id: "dashboard-widget-system-info" }, - renderWidget({ loading: true, failed: false, title: "", items: [] }), + renderWidget({ loading: true, failed: false, title: "", items: [] }) ), E( "div", { id: "dashboard-widget-service-info" }, - renderWidget({ loading: true, failed: false, title: "", items: [] }), - ), + renderWidget({ loading: true, failed: false, title: "", items: [] }) + ) ]), // All outbounds E( @@ -1804,14 +1776,16 @@ function render() { code: "", displayName: "", outbounds: [], - withTagSelect: false, + withTagSelect: false }, - onTestLatency: () => {}, - onChooseOutbound: () => {}, - latencyFetching: false, - }), - ), - ], + onTestLatency: () => { + }, + onChooseOutbound: () => { + }, + latencyFetching: false + }) + ) + ] ); } @@ -1831,15 +1805,15 @@ function prettyBytes(n) { async function fetchServicesInfo() { const [podkop, singbox] = await Promise.all([ PodkopShellMethods.getStatus(), - PodkopShellMethods.getSingBoxStatus(), + PodkopShellMethods.getSingBoxStatus() ]); if (!podkop.success || !singbox.success) { store.set({ servicesInfoWidget: { loading: false, failed: true, - data: { singbox: 0, podkop: 0 }, - }, + data: { singbox: 0, podkop: 0 } + } }); } if (podkop.success && singbox.success) { @@ -1847,8 +1821,8 @@ async function fetchServicesInfo() { servicesInfoWidget: { loading: false, failed: false, - data: { singbox: singbox.data.running, podkop: podkop.data.enabled }, - }, + data: { singbox: singbox.data.running, podkop: podkop.data.enabled } + } }); } } @@ -1859,8 +1833,8 @@ async function fetchDashboardSections() { store.set({ sectionsWidget: { ...prev, - failed: false, - }, + failed: false + } }); const { data, success } = await CustomPodkopMethods.getDashboardSections(); if (!success) { @@ -1871,8 +1845,8 @@ async function fetchDashboardSections() { latencyFetching: false, loading: false, failed: !success, - data, - }, + data + } }); } async function connectToClashSockets() { @@ -1884,24 +1858,24 @@ async function connectToClashSockets() { bandwidthWidget: { loading: false, failed: false, - data: { up: parsedMsg.up, down: parsedMsg.down }, - }, + data: { up: parsedMsg.up, down: parsedMsg.down } + } }); }, (_err) => { logger.error( "[DASHBOARD]", "connectToClashSockets - traffic: failed to connect to", - getClashWsUrl(), + getClashWsUrl() ); store.set({ bandwidthWidget: { loading: false, failed: true, - data: { up: 0, down: 0 }, - }, + data: { up: 0, down: 0 } + } }); - }, + } ); socket.subscribe( `${getClashWsUrl()}/connections?token=`, @@ -1913,41 +1887,41 @@ async function connectToClashSockets() { failed: false, data: { downloadTotal: parsedMsg.downloadTotal, - uploadTotal: parsedMsg.uploadTotal, - }, + uploadTotal: parsedMsg.uploadTotal + } }, systemInfoWidget: { loading: false, failed: false, data: { connections: parsedMsg.connections?.length, - memory: parsedMsg.memory, - }, - }, + memory: parsedMsg.memory + } + } }); }, (_err) => { logger.error( "[DASHBOARD]", "connectToClashSockets - connections: failed to connect to", - getClashWsUrl(), + getClashWsUrl() ); store.set({ trafficTotalWidget: { loading: false, failed: true, - data: { downloadTotal: 0, uploadTotal: 0 }, + data: { downloadTotal: 0, uploadTotal: 0 } }, systemInfoWidget: { loading: false, failed: true, data: { connections: 0, - memory: 0, - }, - }, + memory: 0 + } + } }); - }, + } ); } async function handleChooseOutbound(selector, tag) { @@ -1958,32 +1932,32 @@ async function handleTestGroupLatency(tag) { store.set({ sectionsWidget: { ...store.get().sectionsWidget, - latencyFetching: true, - }, + latencyFetching: true + } }); await PodkopShellMethods.getClashApiGroupLatency(tag); await fetchDashboardSections(); store.set({ sectionsWidget: { ...store.get().sectionsWidget, - latencyFetching: false, - }, + latencyFetching: false + } }); } async function handleTestProxyLatency(tag) { store.set({ sectionsWidget: { ...store.get().sectionsWidget, - latencyFetching: true, - }, + latencyFetching: true + } }); await PodkopShellMethods.getClashApiProxyLatency(tag); await fetchDashboardSections(); store.set({ sectionsWidget: { ...store.get().sectionsWidget, - latencyFetching: false, - }, + latencyFetching: false + } }); } async function renderSectionsWidget() { @@ -1998,18 +1972,20 @@ async function renderSectionsWidget() { code: "", displayName: "", outbounds: [], - withTagSelect: false, + withTagSelect: false }, - onTestLatency: () => {}, - onChooseOutbound: () => {}, - latencyFetching: sectionsWidget.latencyFetching, + onTestLatency: () => { + }, + onChooseOutbound: () => { + }, + latencyFetching: sectionsWidget.latencyFetching }); return preserveScrollForPage(() => { container.replaceChildren(renderedWidget); }); } - const renderedWidgets = sectionsWidget.data.map((section) => - renderSections({ + const renderedWidgets = sectionsWidget.data.map( + (section) => renderSections({ loading: sectionsWidget.loading, failed: sectionsWidget.failed, section, @@ -2022,8 +1998,8 @@ async function renderSectionsWidget() { }, onChooseOutbound: (selector, tag) => { handleChooseOutbound(selector, tag); - }, - }), + } + }) ); return preserveScrollForPage(() => { container.replaceChildren(...renderedWidgets); @@ -2038,7 +2014,7 @@ async function renderBandwidthWidget() { loading: traffic.loading, failed: traffic.failed, title: "", - items: [], + items: [] }); return container.replaceChildren(renderedWidget2); } @@ -2048,8 +2024,8 @@ async function renderBandwidthWidget() { title: _("Traffic"), items: [ { key: _("Uplink"), value: `${prettyBytes(traffic.data.up)}/s` }, - { key: _("Downlink"), value: `${prettyBytes(traffic.data.down)}/s` }, - ], + { key: _("Downlink"), value: `${prettyBytes(traffic.data.down)}/s` } + ] }); container.replaceChildren(renderedWidget); } @@ -2062,7 +2038,7 @@ async function renderTrafficTotalWidget() { loading: trafficTotalWidget.loading, failed: trafficTotalWidget.failed, title: "", - items: [], + items: [] }); return container.replaceChildren(renderedWidget2); } @@ -2073,13 +2049,13 @@ async function renderTrafficTotalWidget() { items: [ { key: _("Uplink"), - value: String(prettyBytes(trafficTotalWidget.data.uploadTotal)), + value: String(prettyBytes(trafficTotalWidget.data.uploadTotal)) }, { key: _("Downlink"), - value: String(prettyBytes(trafficTotalWidget.data.downloadTotal)), - }, - ], + value: String(prettyBytes(trafficTotalWidget.data.downloadTotal)) + } + ] }); container.replaceChildren(renderedWidget); } @@ -2092,7 +2068,7 @@ async function renderSystemInfoWidget() { loading: systemInfoWidget.loading, failed: systemInfoWidget.failed, title: "", - items: [], + items: [] }); return container.replaceChildren(renderedWidget2); } @@ -2103,13 +2079,13 @@ async function renderSystemInfoWidget() { items: [ { key: _("Active Connections"), - value: String(systemInfoWidget.data.connections), + value: String(systemInfoWidget.data.connections) }, { key: _("Memory Usage"), - value: String(prettyBytes(systemInfoWidget.data.memory)), - }, - ], + value: String(prettyBytes(systemInfoWidget.data.memory)) + } + ] }); container.replaceChildren(renderedWidget); } @@ -2122,7 +2098,7 @@ async function renderServicesInfoWidget() { loading: servicesInfoWidget.loading, failed: servicesInfoWidget.failed, title: "", - items: [], + items: [] }); return container.replaceChildren(renderedWidget2); } @@ -2133,27 +2109,19 @@ async function renderServicesInfoWidget() { items: [ { key: _("Podkop"), - value: servicesInfoWidget.data.podkop - ? _("\u2714 Enabled") - : _("\u2718 Disabled"), + value: servicesInfoWidget.data.podkop ? _("\u2714 Enabled") : _("\u2718 Disabled"), attributes: { - class: servicesInfoWidget.data.podkop - ? "pdk_dashboard-page__widgets-section__item__row--success" - : "pdk_dashboard-page__widgets-section__item__row--error", - }, + class: servicesInfoWidget.data.podkop ? "pdk_dashboard-page__widgets-section__item__row--success" : "pdk_dashboard-page__widgets-section__item__row--error" + } }, { key: _("Sing-box"), - value: servicesInfoWidget.data.singbox - ? _("\u2714 Running") - : _("\u2718 Stopped"), + value: servicesInfoWidget.data.singbox ? _("\u2714 Running") : _("\u2718 Stopped"), attributes: { - class: servicesInfoWidget.data.singbox - ? "pdk_dashboard-page__widgets-section__item__row--success" - : "pdk_dashboard-page__widgets-section__item__row--error", - }, - }, - ], + class: servicesInfoWidget.data.singbox ? "pdk_dashboard-page__widgets-section__item__row--success" : "pdk_dashboard-page__widgets-section__item__row--error" + } + } + ] }); container.replaceChildren(renderedWidget); } @@ -2188,27 +2156,24 @@ function onPageUnmount() { "trafficTotalWidget", "systemInfoWidget", "servicesInfoWidget", - "sectionsWidget", + "sectionsWidget" ]); socket.resetAll(); } function registerLifecycleListeners() { store.subscribe((next, prev, diff) => { - if ( - diff.tabService && - next.tabService.current !== prev.tabService.current - ) { + if (diff.tabService && next.tabService.current !== prev.tabService.current) { logger.debug( "[DASHBOARD]", "active tab diff event, active tab:", - diff.tabService.current, + diff.tabService.current ); const isDashboardVisible = next.tabService.current === "dashboard"; if (isDashboardVisible) { logger.debug( "[DASHBOARD]", "registerLifecycleListeners", - "onPageMount", + "onPageMount" ); return onPageMount(); } @@ -2216,7 +2181,7 @@ function registerLifecycleListeners() { logger.debug( "[DASHBOARD]", "registerLifecycleListeners", - "onPageUnmount", + "onPageUnmount" ); return onPageUnmount(); } @@ -2356,7 +2321,7 @@ var styles = ` var DashboardTab = { render, initController, - styles, + styles }; // src/podkop/tabs/diagnostic/renderDiagnostic.ts @@ -2366,13 +2331,13 @@ function render2() { E("div", { id: "pdk_diagnostic-page-run-check" }), E("div", { class: "pdk_diagnostic-page__checks", - id: "pdk_diagnostic-page-checks", - }), + id: "pdk_diagnostic-page-checks" + }) ]), E("div", { class: "pdk_diagnostic-page__right-bar" }, [ E("div", { id: "pdk_diagnostic-page-actions" }), - E("div", { id: "pdk_diagnostic-page-system-info" }), - ]), + E("div", { id: "pdk_diagnostic-page-system-info" }) + ]) ]); } @@ -2382,11 +2347,11 @@ function updateCheckStore(check, minified) { const other = diagnosticsChecks.filter((item) => item.code !== check.code); const smallCheck = { ...check, - items: check.items.filter((item) => item.state !== "success"), + items: check.items.filter((item) => item.state !== "success") }; const targetCheck = minified ? smallCheck : check; store.set({ - diagnosticsChecks: [...other, targetCheck], + diagnosticsChecks: [...other, targetCheck] }); } @@ -2399,7 +2364,7 @@ async function runDnsCheck() { title, description: _("Checking dns, please wait"), state: "loading", - items: [], + items: [] }); const dnsChecks = await PodkopShellMethods.checkDNSAvailable(); if (!dnsChecks.success) { @@ -2409,21 +2374,13 @@ async function runDnsCheck() { title, description: _("Cannot receive DNS checks result"), state: "error", - items: [], + items: [] }); throw new Error("DNS checks failed"); } 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); + 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"; @@ -2440,29 +2397,32 @@ async function runDnsCheck() { description: _("DNS checks passed"), state: getStatus(), items: [ - ...insertIf(data.dns_type === "doh" || data.dns_type === "dot", [ - { - state: data.bootstrap_dns_status ? "success" : "error", - key: _("Bootsrap DNS"), - value: data.bootstrap_dns_server, - }, - ]), + ...insertIf( + data.dns_type === "doh" || data.dns_type === "dot", + [ + { + state: data.bootstrap_dns_status ? "success" : "error", + key: _("Bootsrap DNS"), + value: data.bootstrap_dns_server + } + ] + ), { state: data.dns_status ? "success" : "error", key: _("Main DNS"), - value: `${data.dns_server} [${data.dns_type}]`, + value: `${data.dns_server} [${data.dns_type}]` }, { state: data.dns_on_router ? "success" : "error", key: _("DNS on router"), - value: "", + value: "" }, { state: data.dhcp_config_status ? "success" : "error", key: _("DHCP has DNS server"), - value: "", - }, - ], + value: "" + } + ] }); if (!atLeastOneGood) { throw new Error("DNS checks failed"); @@ -2478,7 +2438,7 @@ async function runSingBoxCheck() { title, description: _("Checking sing-box, please wait"), state: "loading", - items: [], + items: [] }); const singBoxChecks = await PodkopShellMethods.checkSingBox(); if (!singBoxChecks.success) { @@ -2488,25 +2448,13 @@ async function runSingBoxCheck() { title, description: _("Cannot receive Sing-box checks result"), state: "error", - items: [], + items: [] }); throw new Error("Sing-box checks failed"); } 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); + 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"; @@ -2526,34 +2474,34 @@ async function runSingBoxCheck() { { state: data.sing_box_installed ? "success" : "error", key: _("Sing-box installed"), - value: "", + value: "" }, { state: data.sing_box_version_ok ? "success" : "error", key: _("Sing-box version >= 1.12.4"), - value: "", + value: "" }, { state: data.sing_box_service_exist ? "success" : "error", key: _("Sing-box service exist"), - value: "", + value: "" }, { state: data.sing_box_autostart_disabled ? "success" : "error", key: _("Sing-box autostart disabled"), - value: "", + value: "" }, { state: data.sing_box_process_running ? "success" : "error", key: _("Sing-box process running"), - value: "", + value: "" }, { state: data.sing_box_ports_listening ? "success" : "error", key: _("Sing-box listening ports"), - value: "", - }, - ], + value: "" + } + ] }); if (!atLeastOneGood || !data.sing_box_process_running) { throw new Error("Sing-box checks failed"); @@ -2569,7 +2517,7 @@ async function runNftCheck() { title, description: _("Checking nftables, please wait"), state: "loading", - items: [], + items: [] }); await RemoteFakeIPMethods.getFakeIpCheck(); await RemoteFakeIPMethods.getIpCheck(); @@ -2581,29 +2529,13 @@ async function runNftCheck() { title, description: _("Cannot receive nftables checks result"), state: "error", - items: [], + items: [] }); throw new Error("Nftables checks failed"); } 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) && - Boolean(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) || - Boolean(data.rules_other_mark_exist); + 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) && Boolean(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) || Boolean(data.rules_other_mark_exist); function getStatus() { if (allGood) { return "success"; @@ -2617,54 +2549,50 @@ async function runNftCheck() { order, code, title, - description: allGood - ? _("Nftables checks passed") - : _("Nftables checks partially passed"), + description: allGood ? _("Nftables checks passed") : _("Nftables checks partially passed"), state: getStatus(), items: [ { state: data.table_exist ? "success" : "error", key: _("Table exist"), - value: "", + value: "" }, { state: data.rules_mangle_exist ? "success" : "error", key: _("Rules mangle exist"), - value: "", + value: "" }, { state: data.rules_mangle_counters ? "success" : "error", key: _("Rules mangle counters"), - value: "", + value: "" }, { state: data.rules_mangle_output_exist ? "success" : "error", key: _("Rules mangle output exist"), - value: "", + value: "" }, { state: data.rules_mangle_output_counters ? "success" : "error", key: _("Rules mangle output counters"), - value: "", + value: "" }, { state: data.rules_proxy_exist ? "success" : "error", key: _("Rules proxy exist"), - value: "", + value: "" }, { state: data.rules_proxy_counters ? "success" : "error", key: _("Rules proxy counters"), - value: "", + value: "" }, { state: !data.rules_other_mark_exist ? "success" : "warning", - key: !data.rules_other_mark_exist - ? _("No other marking rules found") - : _("Additional marking rules found"), - value: "", - }, - ], + key: !data.rules_other_mark_exist ? _("No other marking rules found") : _("Additional marking rules found"), + value: "" + } + ] }); if (!atLeastOneGood) { throw new Error("Nftables checks failed"); @@ -2680,39 +2608,34 @@ async function runFakeIPCheck() { title, description: _("Checking FakeIP, please wait"), state: "loading", - items: [], + items: [] }); const routerFakeIPResponse = await PodkopShellMethods.checkFakeIP(); const checkFakeIPResponse = await RemoteFakeIPMethods.getFakeIpCheck(); const checkIPResponse = await RemoteFakeIPMethods.getIpCheck(); const checks = { router: routerFakeIPResponse.success && routerFakeIPResponse.data.fakeip, - browserFakeIP: - checkFakeIPResponse.success && checkFakeIPResponse.data.fakeip, - differentIP: - checkFakeIPResponse.success && - checkIPResponse.success && - checkFakeIPResponse.data.IP !== checkIPResponse.data.IP, + browserFakeIP: checkFakeIPResponse.success && checkFakeIPResponse.data.fakeip, + differentIP: checkFakeIPResponse.success && checkIPResponse.success && checkFakeIPResponse.data.IP !== checkIPResponse.data.IP }; const allGood = checks.router || checks.browserFakeIP || checks.differentIP; - const atLeastOneGood = - 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"), + description: _("FakeIP checks passed") }; } if (atLeastOneGood) { return { state: "warning", - description: _("FakeIP checks partially passed"), + description: _("FakeIP checks partially passed") }; } return { state: "error", - description: _("FakeIP checks failed"), + description: _("FakeIP checks failed") }; } const { state, description } = getMeta(); @@ -2725,28 +2648,22 @@ async function runFakeIPCheck() { items: [ { state: checks.router ? "success" : "warning", - key: checks.router - ? _("Router DNS is routed through sing-box") - : _("Router DNS is not routed through sing-box"), - value: "", + key: checks.router ? _("Router DNS is routed through sing-box") : _("Router DNS is not routed through sing-box"), + value: "" }, { state: checks.browserFakeIP ? "success" : "error", - key: checks.browserFakeIP - ? _("Browser is using FakeIP correctly") - : _("Browser is not using FakeIP"), - value: "", + key: checks.browserFakeIP ? _("Browser is using FakeIP correctly") : _("Browser is not using FakeIP"), + value: "" }, ...insertIf(checks.browserFakeIP, [ { state: checks.differentIP ? "success" : "error", - key: checks.differentIP - ? _("Proxy traffic is routed via FakeIP") - : _("Proxy traffic is not routed via FakeIP"), - value: "", - }, - ]), - ], + key: checks.differentIP ? _("Proxy traffic is routed via FakeIP") : _("Proxy traffic is not routed via FakeIP"), + value: "" + } + ]) + ] }); } @@ -2818,11 +2735,11 @@ function renderLoaderCircleIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-loader-circle rotate", + class: "lucide lucide-loader-circle rotate" }, [ svgEl("path", { - d: "M21 12a9 9 0 1 1-6.219-8.56", + d: "M21 12a9 9 0 1 1-6.219-8.56" }), svgEl("animateTransform", { attributeName: "transform", @@ -2831,9 +2748,9 @@ function renderLoaderCircleIcon24() { from: "0 12 12", to: "360 12 12", dur: "1s", - repeatCount: "indefinite", - }), - ], + repeatCount: "indefinite" + }) + ] ); } @@ -2852,27 +2769,27 @@ function renderCircleAlertIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-alert-icon lucide-circle-alert", + class: "lucide lucide-circle-alert-icon lucide-circle-alert" }, [ svgEl("circle", { cx: "12", cy: "12", - r: "10", + r: "10" }), svgEl("line", { x1: "12", y1: "8", x2: "12", - y2: "12", + y2: "12" }), svgEl("line", { x1: "12", y1: "16", x2: "12.01", - y2: "16", - }), - ], + y2: "16" + }) + ] ); } @@ -2891,18 +2808,18 @@ function renderCircleCheckIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-check-icon lucide-circle-check", + class: "lucide lucide-circle-check-icon lucide-circle-check" }, [ svgEl("circle", { cx: "12", cy: "12", - r: "10", + r: "10" }), svgEl("path", { - d: "M9 12l2 2 4-4", - }), - ], + d: "M9 12l2 2 4-4" + }) + ] ); } @@ -2921,21 +2838,21 @@ function renderCircleSlashIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-slash-icon lucide-circle-slash", + class: "lucide lucide-circle-slash-icon lucide-circle-slash" }, [ svgEl("circle", { cx: "12", cy: "12", - r: "10", + r: "10" }), svgEl("line", { x1: "9", y1: "15", x2: "15", - y2: "9", - }), - ], + y2: "9" + }) + ] ); } @@ -2954,21 +2871,21 @@ function renderCircleXIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-x-icon lucide-circle-x", + class: "lucide lucide-circle-x-icon lucide-circle-x" }, [ svgEl("circle", { cx: "12", cy: "12", - r: "10", + r: "10" }), svgEl("path", { - d: "M15 9L9 15", + d: "M15 9L9 15" }), svgEl("path", { - d: "M9 9L15 15", - }), - ], + d: "M9 9L15 15" + }) + ] ); } @@ -2985,13 +2902,13 @@ function renderCheckIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-check-icon lucide-check", + class: "lucide lucide-check-icon lucide-check" }, [ svgEl("path", { - d: "M20 6 9 17l-5-5", - }), - ], + d: "M20 6 9 17l-5-5" + }) + ] ); } @@ -3008,9 +2925,9 @@ function renderXIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-x-icon lucide-x", + class: "lucide lucide-x-icon lucide-x" }, - [svgEl("path", { d: "M18 6 6 18" }), svgEl("path", { d: "m6 6 12 12" })], + [svgEl("path", { d: "M18 6 6 18" }), svgEl("path", { d: "m6 6 12 12" })] ); } @@ -3027,15 +2944,15 @@ function renderTriangleAlertIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-triangle-alert-icon lucide-triangle-alert", + class: "lucide lucide-triangle-alert-icon lucide-triangle-alert" }, [ svgEl("path", { - d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3", + d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }), svgEl("path", { d: "M12 9v4" }), - svgEl("path", { d: "M12 17h.01" }), - ], + svgEl("path", { d: "M12 17h.01" }) + ] ); } @@ -3052,7 +2969,7 @@ function renderPauseIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-pause-icon lucide-pause", + class: "lucide lucide-pause-icon lucide-pause" }, [ svgEl("rect", { @@ -3060,16 +2977,16 @@ function renderPauseIcon24() { y: "3", width: "5", height: "18", - rx: "1", + rx: "1" }), svgEl("rect", { x: "5", y: "3", width: "5", height: "18", - rx: "1", - }), - ], + rx: "1" + }) + ] ); } @@ -3086,13 +3003,13 @@ function renderPlayIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-play-icon lucide-play", + class: "lucide lucide-play-icon lucide-play" }, [ svgEl("path", { - d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z", - }), - ], + d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z" + }) + ] ); } @@ -3109,16 +3026,16 @@ function renderRotateCcwIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-rotate-ccw-icon lucide-rotate-ccw", + class: "lucide lucide-rotate-ccw-icon lucide-rotate-ccw" }, [ svgEl("path", { - d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", + d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }), svgEl("path", { - d: "M3 3v5h5", - }), - ], + d: "M3 3v5h5" + }) + ] ); } @@ -3135,22 +3052,22 @@ function renderCircleStopIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-stop-icon lucide-circle-stop", + class: "lucide lucide-circle-stop-icon lucide-circle-stop" }, [ svgEl("circle", { cx: "12", cy: "12", - r: "10", + r: "10" }), svgEl("rect", { x: "9", y: "9", width: "6", height: "6", - rx: "1", - }), - ], + rx: "1" + }) + ] ); } @@ -3167,18 +3084,18 @@ function renderCirclePlayIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-play-icon lucide-circle-play", + class: "lucide lucide-circle-play-icon lucide-circle-play" }, [ svgEl("path", { - d: "M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z", + d: "M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z" }), svgEl("circle", { cx: "12", cy: "12", - r: "10", - }), - ], + r: "10" + }) + ] ); } @@ -3195,16 +3112,16 @@ function renderCircleCheckBigIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-circle-check-big-icon lucide-circle-check-big", + class: "lucide lucide-circle-check-big-icon lucide-circle-check-big" }, [ svgEl("path", { - d: "M21.801 10A10 10 0 1 1 17 3.335", + d: "M21.801 10A10 10 0 1 1 17 3.335" }), svgEl("path", { - d: "m9 11 3 3L22 4", - }), - ], + d: "m9 11 3 3L22 4" + }) + ] ); } @@ -3221,7 +3138,7 @@ function renderSquareChartGanttIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-square-chart-gantt-icon lucide-square-chart-gantt", + class: "lucide lucide-square-chart-gantt-icon lucide-square-chart-gantt" }, [ svgEl("rect", { @@ -3229,12 +3146,12 @@ function renderSquareChartGanttIcon24() { height: "18", x: "3", y: "3", - rx: "2", + rx: "2" }), svgEl("path", { d: "M9 8h7" }), svgEl("path", { d: "M8 12h6" }), - svgEl("path", { d: "M11 16h5" }), - ], + svgEl("path", { d: "M11 16h5" }) + ] ); } @@ -3251,7 +3168,7 @@ function renderCogIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-cog-icon lucide-cog", + class: "lucide lucide-cog-icon lucide-cog" }, [ svgEl("path", { d: "M11 10.27 7 3.34" }), @@ -3267,8 +3184,8 @@ function renderCogIcon24() { svgEl("path", { d: "m3.34 17 1.73-1" }), svgEl("path", { d: "m3.34 7 1.73 1" }), svgEl("circle", { cx: "12", cy: "12", r: "2" }), - svgEl("circle", { cx: "12", cy: "12", r: "8" }), - ], + svgEl("circle", { cx: "12", cy: "12", r: "8" }) + ] ); } @@ -3285,12 +3202,12 @@ function renderSearchIcon24() { "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", - class: "lucide lucide-search-icon lucide-search", + class: "lucide lucide-search-icon lucide-search" }, [ svgEl("path", { d: "m21 21-4.34-4.34" }), - svgEl("circle", { cx: "11", cy: "11", r: "8" }), - ], + svgEl("circle", { cx: "11", cy: "11", r: "8" }) + ] ); } @@ -3301,12 +3218,12 @@ function renderButton({ loading, onClick, text, - icon, + icon }) { const hasIcon = !!loading || !!icon; function getWrappedIcon() { const iconWrap = E("span", { - class: "pdk-partial-button__icon", + class: "pdk-partial-button__icon" }); if (loading) { iconWrap.appendChild(renderLoaderCircleIcon24()); @@ -3325,10 +3242,8 @@ function renderButton({ ...insertIf(Boolean(disabled), ["pdk-partial-button--disabled"]), ...insertIf(Boolean(loading), ["pdk-partial-button--loading"]), ...insertIf(Boolean(hasIcon), ["pdk-partial-button--with-icon"]), - ...classNames, - ] - .filter(Boolean) - .join(" "); + ...classNames + ].filter(Boolean).join(" "); } function getDisabled() { if (loading || disabled) { @@ -3339,7 +3254,7 @@ function renderButton({ return E( "button", { class: getClass(), disabled: getDisabled(), click: onClick }, - [...insertIf(hasIcon, [getWrappedIcon()]), E("span", {}, text)], + [...insertIf(hasIcon, [getWrappedIcon()]), E("span", {}, text)] ); } @@ -3389,23 +3304,22 @@ function renderModal(text, name) { renderButton({ classNames: ["cbi-button-apply"], text: _("Download"), - onClick: () => downloadAsTxt(text, name), + onClick: () => downloadAsTxt(text, name) }), renderButton({ classNames: ["cbi-button-apply"], text: _("Copy"), - onClick: () => - copyToClipboard(` \`\`\`${name} + onClick: () => copyToClipboard(` \`\`\`${name} ${text} - \`\`\``), + \`\`\``) }), renderButton({ classNames: ["cbi-button-remove"], text: _("Close"), - onClick: ui.hideModal, - }), - ]), - ]), + onClick: ui.hideModal + }) + ]) + ]) ); } @@ -3424,7 +3338,7 @@ function renderAvailableActions({ disable, globalCheck, viewLogs, - showSingBoxConfig, + showSingBoxConfig }) { return E("div", { class: "pdk_diagnostic-page__right-bar__actions" }, [ E("b", {}, "Available actions"), @@ -3435,8 +3349,8 @@ function renderAvailableActions({ icon: renderRotateCcwIcon24, text: _("Restart podkop"), loading: restart.loading, - disabled: restart.disabled, - }), + disabled: restart.disabled + }) ]), ...insertIf(stop.visible, [ renderButton({ @@ -3445,8 +3359,8 @@ function renderAvailableActions({ icon: renderCircleStopIcon24, text: _("Stop podkop"), loading: stop.loading, - disabled: stop.disabled, - }), + disabled: stop.disabled + }) ]), ...insertIf(start.visible, [ renderButton({ @@ -3455,8 +3369,8 @@ function renderAvailableActions({ icon: renderCirclePlayIcon24, text: _("Start podkop"), loading: start.loading, - disabled: start.disabled, - }), + disabled: start.disabled + }) ]), ...insertIf(disable.visible, [ renderButton({ @@ -3465,8 +3379,8 @@ function renderAvailableActions({ icon: renderPauseIcon24, text: _("Disable autostart"), loading: disable.loading, - disabled: disable.disabled, - }), + disabled: disable.disabled + }) ]), ...insertIf(enable.visible, [ renderButton({ @@ -3475,8 +3389,8 @@ function renderAvailableActions({ icon: renderPlayIcon24, text: _("Enable autostart"), loading: enable.loading, - disabled: enable.disabled, - }), + disabled: enable.disabled + }) ]), ...insertIf(globalCheck.visible, [ renderButton({ @@ -3484,8 +3398,8 @@ function renderAvailableActions({ icon: renderCircleCheckBigIcon24, text: _("Get global check"), loading: globalCheck.loading, - disabled: globalCheck.disabled, - }), + disabled: globalCheck.disabled + }) ]), ...insertIf(viewLogs.visible, [ renderButton({ @@ -3493,8 +3407,8 @@ function renderAvailableActions({ icon: renderSquareChartGanttIcon24, text: _("View logs"), loading: viewLogs.loading, - disabled: viewLogs.disabled, - }), + disabled: viewLogs.disabled + }) ]), ...insertIf(showSingBoxConfig.visible, [ renderButton({ @@ -3502,9 +3416,9 @@ function renderAvailableActions({ icon: renderCogIcon24, text: _("Show sing-box config"), loading: showSingBoxConfig.loading, - disabled: showSingBoxConfig.disabled, - }), - ]), + disabled: showSingBoxConfig.disabled + }) + ]) ]); } @@ -3516,7 +3430,7 @@ function renderCheckSummary(items) { const renderedItems = items.map((item) => { function getIcon() { const iconWrap = E("span", { - class: "pdk_diagnostic_alert__summary__item__icon", + class: "pdk_diagnostic_alert__summary__item__icon" }); if (item.state === "success") { iconWrap.appendChild(renderCheckIcon24()); @@ -3532,9 +3446,9 @@ function renderCheckSummary(items) { return E( "div", { - class: `pdk_diagnostic_alert__summary__item pdk_diagnostic_alert__summary__item--${item.state}`, + class: `pdk_diagnostic_alert__summary__item pdk_diagnostic_alert__summary__item--${item.state}` }, - [getIcon(), E("b", {}, item.key), E("div", {}, item.value)], + [getIcon(), E("b", {}, item.key), E("div", {}, item.value)] ); }); return E("div", { class: "pdk_diagnostic_alert__summary" }, renderedItems); @@ -3552,12 +3466,12 @@ function renderLoadingState3(props) { E( "div", { class: "pdk_diagnostic_alert__description" }, - props.description, - ), + props.description + ) ]), E("div", {}, ""), - renderCheckSummary(props.items), - ], + renderCheckSummary(props.items) + ] ); } function renderWarningState(props) { @@ -3573,12 +3487,12 @@ function renderWarningState(props) { E( "div", { class: "pdk_diagnostic_alert__description" }, - props.description, - ), + props.description + ) ]), E("div", {}, ""), - renderCheckSummary(props.items), - ], + renderCheckSummary(props.items) + ] ); } function renderErrorState(props) { @@ -3594,12 +3508,12 @@ function renderErrorState(props) { E( "div", { class: "pdk_diagnostic_alert__description" }, - props.description, - ), + props.description + ) ]), E("div", {}, ""), - renderCheckSummary(props.items), - ], + renderCheckSummary(props.items) + ] ); } function renderSuccessState(props) { @@ -3615,12 +3529,12 @@ function renderSuccessState(props) { E( "div", { class: "pdk_diagnostic_alert__description" }, - props.description, - ), + props.description + ) ]), E("div", {}, ""), - renderCheckSummary(props.items), - ], + renderCheckSummary(props.items) + ] ); } function renderSkippedState(props) { @@ -3636,12 +3550,12 @@ function renderSkippedState(props) { E( "div", { class: "pdk_diagnostic_alert__description" }, - props.description, - ), + props.description + ) ]), E("div", {}, ""), - renderCheckSummary(props.items), - ], + renderCheckSummary(props.items) + ] ); } function renderCheckSection(props) { @@ -3664,15 +3578,18 @@ function renderCheckSection(props) { } // src/podkop/tabs/diagnostic/partials/renderRunAction.ts -function renderRunAction({ loading, click }) { +function renderRunAction({ + loading, + click +}) { return E("div", { class: "pdk_diagnostic-page__run_check_wrapper" }, [ renderButton({ text: _("Run Diagnostic"), onClick: click, icon: renderSearchIcon24, loading, - classNames: ["cbi-button-apply"], - }), + classNames: ["cbi-button-apply"] + }) ]); } @@ -3682,20 +3599,18 @@ function renderSystemInfo({ items }) { E( "b", { class: "pdk_diagnostic-page__right-bar__system-info__title" }, - "System information", + "System information" ), ...items.map((item) => { const tagClass = [ "pdk_diagnostic-page__right-bar__system-info__row__tag", ...insertIf(item.tag?.kind === "warning", [ - "pdk_diagnostic-page__right-bar__system-info__row__tag--warning", + "pdk_diagnostic-page__right-bar__system-info__row__tag--warning" ]), ...insertIf(item.tag?.kind === "success", [ - "pdk_diagnostic-page__right-bar__system-info__row__tag--success", - ]), - ] - .filter(Boolean) - .join(" "); + "pdk_diagnostic-page__right-bar__system-info__row__tag--success" + ]) + ].filter(Boolean).join(" "); return E( "div", { class: "pdk_diagnostic-page__right-bar__system-info__row" }, @@ -3703,11 +3618,11 @@ function renderSystemInfo({ items }) { E("b", {}, item.key), E("div", {}, [ E("span", {}, item.value), - E("span", { class: tagClass }, item?.tag?.label), - ]), - ], + E("span", { class: tagClass }, item?.tag?.label) + ]) + ] ); - }), + }) ]); } @@ -3726,8 +3641,8 @@ async function fetchSystemInfo() { store.set({ diagnosticsSystemInfo: { loading: false, - ...systemInfo.data, - }, + ...systemInfo.data + } }); } else { store.set({ @@ -3738,19 +3653,17 @@ async function fetchSystemInfo() { luci_app_version: _("unknown"), sing_box_version: _("unknown"), openwrt_version: _("unknown"), - device_model: _("unknown"), - }, + device_model: _("unknown") + } }); } } function renderDiagnosticsChecks() { logger.debug("[DIAGNOSTIC]", "renderDiagnosticsChecks"); - const diagnosticsChecks = store - .get() - .diagnosticsChecks.sort((a, b) => a.order - b.order); + const diagnosticsChecks = store.get().diagnosticsChecks.sort((a, b) => a.order - b.order); const container = document.getElementById("pdk_diagnostic-page-checks"); - const renderedDiagnosticsChecks = diagnosticsChecks.map((check) => - renderCheckSection(check), + const renderedDiagnosticsChecks = diagnosticsChecks.map( + (check) => renderCheckSection(check) ); return preserveScrollForPage(() => { container.replaceChildren(...renderedDiagnosticsChecks); @@ -3762,7 +3675,7 @@ function renderDiagnosticRunActionWidget() { const container = document.getElementById("pdk_diagnostic-page-run-check"); const renderedAction = renderRunAction({ loading, - click: () => runChecks(), + click: () => runChecks() }); return preserveScrollForPage(() => { container.replaceChildren(renderedAction); @@ -3773,8 +3686,8 @@ async function handleRestart() { store.set({ diagnosticsActions: { ...diagnosticsActions, - restart: { loading: true }, - }, + restart: { loading: true } + } }); try { await PodkopShellMethods.restart(); @@ -3786,8 +3699,8 @@ async function handleRestart() { store.set({ diagnosticsActions: { ...diagnosticsActions, - restart: { loading: false }, - }, + restart: { loading: false } + } }); store.reset(["diagnosticsChecks"]); }, 5e3); @@ -3798,8 +3711,8 @@ async function handleStop() { store.set({ diagnosticsActions: { ...diagnosticsActions, - stop: { loading: true }, - }, + stop: { loading: true } + } }); try { await PodkopShellMethods.stop(); @@ -3810,8 +3723,8 @@ async function handleStop() { store.set({ diagnosticsActions: { ...diagnosticsActions, - stop: { loading: false }, - }, + stop: { loading: false } + } }); store.reset(["diagnosticsChecks"]); } @@ -3821,8 +3734,8 @@ async function handleStart() { store.set({ diagnosticsActions: { ...diagnosticsActions, - start: { loading: true }, - }, + start: { loading: true } + } }); try { await PodkopShellMethods.start(); @@ -3834,8 +3747,8 @@ async function handleStart() { store.set({ diagnosticsActions: { ...diagnosticsActions, - start: { loading: false }, - }, + start: { loading: false } + } }); store.reset(["diagnosticsChecks"]); }, 5e3); @@ -3846,8 +3759,8 @@ async function handleEnable() { store.set({ diagnosticsActions: { ...diagnosticsActions, - enable: { loading: true }, - }, + enable: { loading: true } + } }); try { await PodkopShellMethods.enable(); @@ -3858,8 +3771,8 @@ async function handleEnable() { store.set({ diagnosticsActions: { ...diagnosticsActions, - enable: { loading: false }, - }, + enable: { loading: false } + } }); } } @@ -3868,8 +3781,8 @@ async function handleDisable() { store.set({ diagnosticsActions: { ...diagnosticsActions, - disable: { loading: true }, - }, + disable: { loading: true } + } }); try { await PodkopShellMethods.disable(); @@ -3880,8 +3793,8 @@ async function handleDisable() { store.set({ diagnosticsActions: { ...diagnosticsActions, - disable: { loading: false }, - }, + disable: { loading: false } + } }); } } @@ -3890,15 +3803,15 @@ async function handleShowGlobalCheck() { store.set({ diagnosticsActions: { ...diagnosticsActions, - globalCheck: { loading: true }, - }, + globalCheck: { loading: true } + } }); try { const globalCheck = await PodkopShellMethods.globalCheck(); if (globalCheck.success) { ui.showModal( _("Global check"), - renderModal(globalCheck.data, "global_check"), + renderModal(globalCheck.data, "global_check") ); } } catch (e) { @@ -3907,8 +3820,8 @@ async function handleShowGlobalCheck() { store.set({ diagnosticsActions: { ...diagnosticsActions, - globalCheck: { loading: false }, - }, + globalCheck: { loading: false } + } }); } } @@ -3917,13 +3830,16 @@ async function handleViewLogs() { store.set({ diagnosticsActions: { ...diagnosticsActions, - viewLogs: { loading: true }, - }, + viewLogs: { loading: true } + } }); try { const viewLogs = await PodkopShellMethods.checkLogs(); if (viewLogs.success) { - ui.showModal(_("View logs"), renderModal(viewLogs.data, "view_logs")); + ui.showModal( + _("View logs"), + renderModal(viewLogs.data, "view_logs") + ); } } catch (e) { logger.error("[DIAGNOSTIC]", "handleViewLogs - e", e); @@ -3931,8 +3847,8 @@ async function handleViewLogs() { store.set({ diagnosticsActions: { ...diagnosticsActions, - viewLogs: { loading: false }, - }, + viewLogs: { loading: false } + } }); } } @@ -3941,15 +3857,15 @@ async function handleShowSingBoxConfig() { store.set({ diagnosticsActions: { ...diagnosticsActions, - showSingBoxConfig: { loading: true }, - }, + showSingBoxConfig: { loading: true } + } }); try { const showSingBoxConfig = await PodkopShellMethods.showSingBoxConfig(); if (showSingBoxConfig.success) { ui.showModal( _("Show sing-box config"), - renderModal(showSingBoxConfig.data, "show_sing_box_config"), + renderModal(showSingBoxConfig.data, "show_sing_box_config") ); } } catch (e) { @@ -3958,8 +3874,8 @@ async function handleShowSingBoxConfig() { store.set({ diagnosticsActions: { ...diagnosticsActions, - showSingBoxConfig: { loading: false }, - }, + showSingBoxConfig: { loading: false } + } }); } } @@ -3969,61 +3885,57 @@ function renderDiagnosticAvailableActionsWidget() { logger.debug("[DIAGNOSTIC]", "renderDiagnosticAvailableActionsWidget"); const podkopEnabled = Boolean(servicesInfoWidget.data.podkop); const singBoxRunning = Boolean(servicesInfoWidget.data.singbox); - const atLeastOneServiceCommandLoading = - servicesInfoWidget.loading || - diagnosticsActions.restart.loading || - diagnosticsActions.start.loading || - diagnosticsActions.stop.loading; + const atLeastOneServiceCommandLoading = servicesInfoWidget.loading || diagnosticsActions.restart.loading || diagnosticsActions.start.loading || diagnosticsActions.stop.loading; const container = document.getElementById("pdk_diagnostic-page-actions"); const renderedActions = renderAvailableActions({ restart: { loading: diagnosticsActions.restart.loading, visible: true, onClick: handleRestart, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, start: { loading: diagnosticsActions.start.loading, visible: !singBoxRunning, onClick: handleStart, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, stop: { loading: diagnosticsActions.stop.loading, visible: singBoxRunning, onClick: handleStop, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, enable: { loading: diagnosticsActions.enable.loading, visible: !podkopEnabled, onClick: handleEnable, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, disable: { loading: diagnosticsActions.disable.loading, visible: podkopEnabled, onClick: handleDisable, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, globalCheck: { loading: diagnosticsActions.globalCheck.loading, visible: true, onClick: handleShowGlobalCheck, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, viewLogs: { loading: diagnosticsActions.viewLogs.loading, visible: true, onClick: handleViewLogs, - disabled: atLeastOneServiceCommandLoading, + disabled: atLeastOneServiceCommandLoading }, showSingBoxConfig: { loading: diagnosticsActions.showSingBoxConfig.loading, visible: true, onClick: handleShowSingBoxConfig, - disabled: atLeastOneServiceCommandLoading, - }, + disabled: atLeastOneServiceCommandLoading + } }); return preserveScrollForPage(() => { container.replaceChildren(renderedActions); @@ -4037,16 +3949,16 @@ function renderDiagnosticSystemInfoWidget() { const loading = diagnosticsSystemInfo.loading; const unknown = diagnosticsSystemInfo.podkop_version === _("unknown"); const hasActualVersion = Boolean( - diagnosticsSystemInfo.podkop_latest_version, + diagnosticsSystemInfo.podkop_latest_version ); const version = normalizeCompiledVersion( - diagnosticsSystemInfo.podkop_version, + diagnosticsSystemInfo.podkop_version ); const isDevVersion = version === "dev"; if (loading || unknown || !hasActualVersion || isDevVersion) { return { key: "Podkop", - value: version, + value: version }; } if (version !== diagnosticsSystemInfo.podkop_latest_version) { @@ -4055,8 +3967,8 @@ function renderDiagnosticSystemInfoWidget() { value: version, tag: { label: _("Outdated"), - kind: "warning", - }, + kind: "warning" + } }; } return { @@ -4064,8 +3976,8 @@ function renderDiagnosticSystemInfoWidget() { value: version, tag: { label: _("Latest"), - kind: "success", - }, + kind: "success" + } }; } const renderedSystemInfo = renderSystemInfo({ @@ -4073,21 +3985,21 @@ function renderDiagnosticSystemInfoWidget() { getPodkopVersionRow(), { key: "Luci App", - value: normalizeCompiledVersion(diagnosticsSystemInfo.luci_app_version), + value: normalizeCompiledVersion(diagnosticsSystemInfo.luci_app_version) }, { key: "Sing-box", - value: diagnosticsSystemInfo.sing_box_version, + value: diagnosticsSystemInfo.sing_box_version }, { key: "OS", - value: diagnosticsSystemInfo.openwrt_version, + value: diagnosticsSystemInfo.openwrt_version }, { key: "Device", - value: diagnosticsSystemInfo.device_model, - }, - ], + value: diagnosticsSystemInfo.device_model + } + ] }); return preserveScrollForPage(() => { container.replaceChildren(renderedSystemInfo); @@ -4111,7 +4023,7 @@ async function runChecks() { try { store.set({ diagnosticsRunAction: { loading: true }, - diagnosticsChecks: loadingDiagnosticsChecksStore.diagnosticsChecks, + diagnosticsChecks: loadingDiagnosticsChecksStore.diagnosticsChecks }); await runDnsCheck(); await runSingBoxCheck(); @@ -4139,26 +4051,23 @@ function onPageUnmount2() { "diagnosticsActions", "diagnosticsSystemInfo", "diagnosticsChecks", - "diagnosticsRunAction", + "diagnosticsRunAction" ]); } function registerLifecycleListeners2() { store.subscribe((next, prev, diff) => { - if ( - diff.tabService && - next.tabService.current !== prev.tabService.current - ) { + if (diff.tabService && next.tabService.current !== prev.tabService.current) { logger.debug( "[DIAGNOSTIC]", "active tab diff event, active tab:", - diff.tabService.current, + diff.tabService.current ); const isDIAGNOSTICVisible = next.tabService.current === "diagnostic"; if (isDIAGNOSTICVisible) { logger.debug( "[DIAGNOSTIC]", "registerLifecycleListeners", - "onPageMount", + "onPageMount" ); return onPageMount2(); } @@ -4166,7 +4075,7 @@ function registerLifecycleListeners2() { logger.debug( "[DIAGNOSTIC]", "registerLifecycleListeners", - "onPageUnmount", + "onPageUnmount" ); return onPageUnmount2(); } @@ -4351,7 +4260,7 @@ var styles4 = ` var DiagnosticTab = { render: render2, initController: initController2, - styles: styles4, + styles: styles4 }; // src/styles.ts @@ -4472,17 +4381,12 @@ function injectGlobalStyles() { - `, + ` ); } // src/helpers/withTimeout.ts -async function withTimeout( - promise, - timeoutMs, - operationName, - timeoutMessage = _("Operation timed out"), -) { +async function withTimeout(promise, timeoutMs, operationName, timeoutMessage = _("Operation timed out")) { let timeoutId; const start = performance.now(); const timeoutPromise = new Promise((_2, reject) => { @@ -4501,13 +4405,13 @@ async function withTimeout( async function executeShellCommand({ command, args, - timeout = COMMAND_TIMEOUT, + timeout = COMMAND_TIMEOUT }) { try { return withTimeout( fs.exec(command, args), timeout, - [command, ...args].join(" "), + [command, ...args].join(" ") ); } catch (err) { const error = err; @@ -4557,7 +4461,7 @@ async function onMount(id) { }); observer.observe(document.body, { childList: true, - subtree: true, + subtree: true }); }); } @@ -4574,11 +4478,7 @@ function getClashUIUrl() { // src/helpers/splitProxyString.ts function splitProxyString(str) { - return str - .split("\n") - .map((line) => line.trim()) - .filter((line) => !line.startsWith("//")) - .filter(Boolean); + return str.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("//")).filter(Boolean); } // src/helpers/preserveScrollForPage.ts @@ -4597,9 +4497,7 @@ function svgEl(tag, attrs = {}, children = []) { for (const [k, v] of Object.entries(attrs)) { if (v != null) el.setAttribute(k, String(v)); } - (Array.isArray(children) ? children : [children]) - .filter(Boolean) - .forEach((ch) => el.appendChild(ch)); + (Array.isArray(children) ? children : [children]).filter(Boolean).forEach((ch) => el.appendChild(ch)); return el; } @@ -4668,5 +4566,5 @@ return baseclass.extend({ validateTrojanUrl, validateUrl, validateVlessUrl, - withTimeout, + withTimeout }); diff --git a/luci-app-podkop/po/ru/podkop.po b/luci-app-podkop/po/ru/podkop.po index 7cfb6bc..10dd5ae 100644 --- a/luci-app-podkop/po/ru/podkop.po +++ b/luci-app-podkop/po/ru/podkop.po @@ -1,15 +1,15 @@ -# Russian translations for PODKOP package. +# RU translations for PODKOP package. # Copyright (C) 2025 THE PODKOP'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# Automatically generated, 2025. +# divocat, 2025. # msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-07 16:55+0300\n" -"PO-Revision-Date: 2025-10-07 23:45+0300\n" -"Last-Translator: Automatically generated\n" +"POT-Creation-Date: 2025-10-21 21:31+0300\n" +"PO-Revision-Date: 2025-10-21 21:31+0300\n" +"Last-Translator: divocat\n" "Language-Team: none\n" "Language: ru\n" "MIME-Version: 1.0\n" @@ -17,269 +17,41 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgid "Basic Settings" -msgstr "Основные настройки" - -msgid "Connection Type" -msgstr "Тип подключения" - -msgid "Select between VPN and Proxy connection methods for traffic routing" -msgstr "Выберите между VPN и Proxy методами для маршрутизации трафика" - -msgid "Configuration Type" -msgstr "Тип конфигурации" - -msgid "Select how to configure the proxy" -msgstr "Выберите способ настройки прокси" - -msgid "Connection URL" -msgstr "URL подключения" - -msgid "Outbound Config" -msgstr "Конфигурация Outbound" - -msgid "URLTest" -msgstr "URLTest" - -msgid "Proxy Configuration URL" -msgstr "URL конфигурации прокси" - -msgid "Current config: " -msgstr "Текущая конфигурация: " - -msgid "Config without description" -msgstr "Конфигурация без описания" - -msgid "" -"Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup " -"configs" +msgid "Successfully copied!" msgstr "" -"Введите строку подключения, начинающуюся с vless:// или ss:// для настройки прокси. Добавляйте комментарии с // для " -"резервных конфигураций" -msgid "No active configuration found. One configuration is required." -msgstr "Активная конфигурация не найдена. Требуется хотя бы одна незакомментированная строка." - -msgid "Multiply active configurations found. Please leave one configuration." -msgstr "Найдено несколько активных конфигураций. Оставьте только одну." - -msgid "Invalid URL format:" -msgstr "Неверный формат URL:" - -msgid "Outbound Configuration" -msgstr "Конфигурация исходящего соединения" - -msgid "Enter complete outbound configuration in JSON format" -msgstr "Введите полную конфигурацию исходящего соединения в формате JSON" - -msgid "URLTest Proxy Links" -msgstr "Ссылки прокси для URLTest" - -msgid "Shadowsocks UDP over TCP" -msgstr "Shadowsocks UDP через TCP" - -msgid "Apply for SS2022" -msgstr "Применить для SS2022" - -msgid "Network Interface" -msgstr "Сетевой интерфейс" - -msgid "Select network interface for VPN connection" -msgstr "Выберите сетевой интерфейс для VPN подключения" - -msgid "Domain Resolver" -msgstr "Резолвер доменов" - -msgid "Enable built-in DNS resolver for domains handled by this section" -msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе" - -msgid "DNS Protocol Type" -msgstr "Тип протокола DNS" - -msgid "Select the DNS protocol type for the domain resolver" -msgstr "Выберите тип протокола DNS для резолвера доменов" - -msgid "DNS over HTTPS (DoH)" -msgstr "DNS через HTTPS (DoH)" - -msgid "DNS over TLS (DoT)" -msgstr "DNS через TLS (DoT)" - -msgid "UDP (Unprotected DNS)" -msgstr "UDP (Незащищённый DNS)" - -msgid "DNS Server" -msgstr "DNS-сервер" - -msgid "Select or enter DNS server address" -msgstr "Выберите или введите адрес DNS-сервера" - -msgid "Community Lists" -msgstr "Списки сообщества" - -msgid "Service List" -msgstr "Список сервисов" - -msgid "Select predefined service for routing" -msgstr "Выберите предустановленные сервисы для маршрутизации" - -msgid "Regional options cannot be used together" -msgstr "Нельзя использовать несколько региональных опций одновременно" - -#, javascript-format -msgid "Warning: %s cannot be used together with %s. Previous selections have been removed." -msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены." - -msgid "Russia inside restrictions" -msgstr "Ограничения Russia inside" - -#, javascript-format -msgid "" -"Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." +msgid "Failed to copy!" msgstr "" -"Внимание: «Russia inside» может использоваться только с %s. %s уже находится в «Russia inside» и был удалён из выбора." -msgid "User Domain List Type" -msgstr "Тип пользовательского списка доменов" +msgid "Operation timed out" +msgstr "Время ожидания истекло" -msgid "Select how to add your custom domains" -msgstr "Выберите способ добавления пользовательских доменов" +msgid "HTTP error" +msgstr "Ошибка HTTP" -msgid "Disabled" -msgstr "Отключено" - -msgid "Dynamic List" -msgstr "Динамический список" - -msgid "Text List" -msgstr "Текстовый список" - -msgid "User Domains" -msgstr "Пользовательские домены" - -msgid "Enter domain names without protocols (example: sub.example.com or example.com)" -msgstr "Введите доменные имена без протоколов (например: sub.example.com или example.com)" - -msgid "User Domains List" -msgstr "Список пользовательских доменов" - -msgid "Enter domain names separated by comma, space or newline. You can add comments after //" -msgstr "Введите домены через запятую, пробел или с новой строки. Можно добавлять комментарии после //" - -msgid "At least one valid domain must be specified. Comments-only content is not allowed." -msgstr "Необходимо указать хотя бы один действительный домен. Содержимое только из комментариев не допускается." - -msgid "Validation errors:" -msgstr "Ошибки валидации:" - -msgid "Local Domain Lists" -msgstr "Локальные списки доменов" - -msgid "Use the list from the router filesystem" -msgstr "Использовать список из файловой системы роутера" - -msgid "Local Domain List Paths" -msgstr "Пути к локальным спискам доменов" - -msgid "Enter the list file path" -msgstr "Введите путь к файлу списка" - -msgid "Remote Domain Lists" -msgstr "Удалённые списки доменов" - -msgid "Download and use domain lists from remote URLs" -msgstr "Загружать и использовать списки доменов с удалённых URL" - -msgid "Remote Domain URLs" -msgstr "URL удалённых доменов" - -msgid "Enter full URLs starting with http:// or https://" -msgstr "Введите полные URL, начинающиеся с http:// или https://" - -msgid "Local Subnet Lists" -msgstr "Локальные списки подсетей" - -msgid "Local Subnet List Paths" -msgstr "Пути к локальным спискам подсетей" - -msgid "User Subnet List Type" -msgstr "Тип пользовательского списка подсетей" - -msgid "Select how to add your custom subnets" -msgstr "Выберите способ добавления пользовательских подсетей" - -msgid "Text List (comma/space/newline separated)" -msgstr "Текстовый список (через запятую, пробел или новую строку)" - -msgid "User Subnets" -msgstr "Пользовательские подсети" - -msgid "Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses" -msgstr "Введите подсети в нотации CIDR (например: 103.21.244.0/22) или отдельные IP-адреса" - -msgid "User Subnets List" -msgstr "Список пользовательских подсетей" - -msgid "" -"Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments " -"after //" -msgstr "" -"Введите подсети в нотации CIDR или IP-адреса через запятую, пробел или новую строку. Можно добавлять комментарии " -"после //" - -msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." -msgstr "Необходимо указать хотя бы одну действительную подсеть или IP. Только комментарии недопустимы." - -msgid "Remote Subnet Lists" -msgstr "Удалённые списки подсетей" - -msgid "Download and use subnet lists from remote URLs" -msgstr "Загружать и использовать списки подсетей с удалённых URL" - -msgid "Remote Subnet URLs" -msgstr "URL удалённых подсетей" - -msgid "IP for full redirection" -msgstr "IP для полного перенаправления" - -msgid "Specify local IP addresses whose traffic will always use the configured route" -msgstr "Укажите локальные IP-адреса, трафик которых всегда будет использовать настроенный маршрут" - -msgid "Local IPs" -msgstr "Локальные IP-адреса" - -msgid "Enter valid IPv4 addresses" -msgstr "Введите действительные IPv4-адреса" - -msgid "Extra configurations" -msgstr "Дополнительные конфигурации" - -msgid "Add Section" -msgstr "Добавить раздел" - -msgid "Dashboard" -msgstr "Дашборд" - -msgid "Valid" -msgstr "Валидно" - -msgid "Invalid IP address" -msgstr "Неверный IP-адрес" - -msgid "Invalid domain address" -msgstr "Неверный домен" +msgid "Unknown error" +msgstr "Неизвестная ошибка" msgid "DNS server address cannot be empty" msgstr "Адрес DNS-сервера не может быть пустым" +msgid "Valid" +msgstr "Валидно" + msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" msgstr "Неверный формат DNS-сервера. Примеры: 8.8.8.8, dns.example.com или dns.example.com/nicedns для DoH" -msgid "URL must use one of the following protocols:" -msgstr "URL должен использовать один из следующих протоколов:" +msgid "Invalid domain address" +msgstr "Неверный домен" -msgid "Invalid URL format" -msgstr "Неверный формат URL" +msgid "Invalid IP address" +msgstr "Неверный IP-адрес" + +msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" +msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\"" + +msgid "Invalid JSON format" +msgstr "Неверный формат JSON" msgid "Path cannot be empty" msgstr "Путь не может быть пустым" @@ -287,14 +59,8 @@ msgstr "Путь не может быть пустым" msgid "Invalid path format. Path must start with \"/\" and contain valid characters" msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы" -msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" -msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y" - -msgid "IP address 0.0.0.0 is not allowed" -msgstr "IP-адрес 0.0.0.0 не допускается" - -msgid "CIDR must be between 0 and 32" -msgstr "CIDR должен быть между 0 и 32" +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" msgid "Invalid Shadowsocks URL: must start with ss://" msgstr "Неверный URL Shadowsocks: должен начинаться с ss://" @@ -326,47 +92,41 @@ msgstr "Неверный номер порта. Допустимо от 1 до 6 msgid "Invalid Shadowsocks URL: parsing failed" msgstr "Неверный URL Shadowsocks: ошибка разбора" -msgid "Invalid VLESS URL: must not contain spaces" -msgstr "Неверный URL VLESS: не должен содержать пробелов" +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" -msgid "Invalid VLESS URL: must start with vless://" -msgstr "Неверный URL VLESS: должен начинаться с vless://" +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" -msgid "Invalid VLESS URL: missing UUID" -msgstr "Неверный URL VLESS: отсутствует UUID" +msgid "Invalid SOCKS URL: missing username" +msgstr "" -msgid "Invalid VLESS URL: missing server" -msgstr "Неверный URL VLESS: отсутствует сервер" +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" -msgid "Invalid VLESS URL: missing port" -msgstr "Неверный URL VLESS: отсутствует порт" +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" -msgid "Invalid VLESS URL: invalid port number. Must be between 1 and 65535" -msgstr "Неверный URL VLESS: недопустимый порт (1–65535)" +msgid "Invalid SOCKS URL: missing port" +msgstr "" -msgid "Invalid VLESS URL: missing query parameters" -msgstr "Неверный URL VLESS: отсутствуют параметры запроса" +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" -msgid "Invalid VLESS URL: type must be one of tcp, raw, udp, grpc, http, ws" -msgstr "Неверный URL VLESS: тип должен быть tcp, raw, udp, grpc, http или ws" +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" -msgid "Invalid VLESS URL: security must be one of tls, reality, none" -msgstr "Неверный URL VLESS: параметр security должен быть tls, reality или none" +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" -msgid "Invalid VLESS URL: missing pbk parameter for reality security" -msgstr "Неверный URL VLESS: отсутствует параметр pbk для security=reality" +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y" -msgid "Invalid VLESS URL: missing fp parameter for reality security" -msgstr "Неверный URL VLESS: отсутствует параметр fp для security=reality" +msgid "IP address 0.0.0.0 is not allowed" +msgstr "IP-адрес 0.0.0.0 не допускается" -msgid "Invalid VLESS URL: parsing failed" -msgstr "Неверный URL VLESS: ошибка разбора" - -msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" -msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\"" - -msgid "Invalid JSON format" -msgstr "Неверный формат JSON" +msgid "CIDR must be between 0 and 32" +msgstr "CIDR должен быть между 0 и 32" msgid "Invalid Trojan URL: must start with trojan://" msgstr "Неверный URL Trojan: должен начинаться с trojan://" @@ -374,33 +134,30 @@ msgstr "Неверный URL Trojan: должен начинаться с trojan msgid "Invalid Trojan URL: must not contain spaces" msgstr "Неверный URL Trojan: не должен содержать пробелов" -msgid "Invalid Trojan URL: must contain username, hostname and port" -msgstr "Неверный URL Trojan: должен содержать имя пользователя, хост и порт" - msgid "Invalid Trojan URL: parsing failed" msgstr "Неверный URL Trojan: ошибка разбора" -msgid "URL must start with vless:// or ss:// or trojan://" -msgstr "URL должен начинаться с vless://, ss:// или trojan://" +msgid "URL must use one of the following protocols:" +msgstr "URL должен использовать один из следующих протоколов:" -msgid "Operation timed out" -msgstr "Время ожидания истекло" +msgid "Invalid URL format" +msgstr "Неверный формат URL" -msgid "HTTP error" -msgstr "Ошибка HTTP" +msgid "Invalid VLESS URL: parsing failed" +msgstr "Неверный URL VLESS: ошибка разбора" -msgid "Unknown error" -msgstr "Неизвестная ошибка" +msgid "Download" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Close" +msgstr "Закрыть" msgid "Fastest" msgstr "Самый быстрый" -msgid "Dashboard currently unavailable" -msgstr "Дашборд сейчас недоступен" - -msgid "Currently unavailable" -msgstr "Временно недоступно" - msgid "Traffic" msgstr "Трафик" @@ -443,164 +200,761 @@ msgstr "✔ Работает" msgid "✘ Stopped" msgstr "✘ Остановлен" -msgid "Copied!" -msgstr "Скопировано!" +msgid "Not running" +msgstr "" -msgid "Failed to copy: " -msgstr "Не удалось скопировать: " +msgid "Queued" +msgstr "" -msgid "Loading..." -msgstr "Загрузка..." - -msgid "Copy to Clipboard" -msgstr "Копировать в буфер" - -msgid "Close" -msgstr "Закрыть" - -msgid "No output" -msgstr "Нет вывода" - -msgid "FakeIP is working in browser!" -msgstr "FakeIP работает в браузере!" - -msgid "FakeIP is not working in browser" -msgstr "FakeIP не работает в браузере" - -msgid "Check DNS server on current device (PC, phone)" -msgstr "Проверьте DNS-сервер на текущем устройстве (ПК, телефон)" - -msgid "Its must be router!" -msgstr "Это должен быть роутер!" - -msgid "Proxy working correctly" -msgstr "Прокси работает корректно" - -msgid "Direct IP: " -msgstr "Прямой IP: " - -msgid "Proxy IP: " -msgstr "Прокси IP: " - -msgid "Proxy is not working - same IP for both domains" -msgstr "Прокси не работает — одинаковый IP для обоих доменов" - -msgid "IP: " -msgstr "IP: " - -msgid "Proxy check failed" -msgstr "Проверка прокси не удалась" - -msgid "Check failed: " -msgstr "Проверка не удалась: " - -msgid "timeout" -msgstr "таймаут" - -msgid "Error: " -msgstr "Ошибка: " - -msgid "Podkop Status" -msgstr "Статус Podkop" +msgid "unknown" +msgstr "" msgid "Global check" msgstr "Глобальная проверка" -msgid "Click here for all the info" -msgstr "Нажмите для просмотра всей информации" +msgid "View logs" +msgstr "" -msgid "Update Lists" -msgstr "Обновить списки" +msgid "Show sing-box config" +msgstr "" -msgid "Lists Update Results" -msgstr "Результаты обновления списков" +msgid "Outdated" +msgstr "" -msgid "Sing-box Status" -msgstr "Статус Sing-box" +msgid "Latest" +msgstr "" -msgid "Check NFT Rules" -msgstr "Проверить правила NFT" +msgid "Dashboard currently unavailable" +msgstr "Дашборд сейчас недоступен" -msgid "NFT Rules" -msgstr "Правила NFT" +msgid "Test latency" +msgstr "" -msgid "Check DNSMasq" -msgstr "Проверить DNSMasq" +msgid "Currently unavailable" +msgstr "Временно недоступно" -msgid "DNSMasq Configuration" -msgstr "Конфигурация DNSMasq" +msgid "DNS checks" +msgstr "" -msgid "FakeIP Status" -msgstr "Статус FakeIP" +msgid "Sing-box checks" +msgstr "" -msgid "DNS Status" -msgstr "Статус DNS" +msgid "Nftables checks" +msgstr "" -msgid "Main config" -msgstr "Основная конфигурация" +msgid "FakeIP checks" +msgstr "" -msgid "Version Information" -msgstr "Информация о версии" +msgid "Checking dns, please wait" +msgstr "" -msgid "Podkop: " -msgstr "Podkop: " +msgid "Cannot receive DNS checks result" +msgstr "" -msgid "LuCI App: " -msgstr "LuCI App: " +msgid "DNS checks passed" +msgstr "" -msgid "Sing-box: " -msgstr "Sing-box: " +msgid "Bootsrap DNS" +msgstr "" -msgid "OpenWrt Version: " -msgstr "Версия OpenWrt: " +msgid "Main DNS" +msgstr "" -msgid "Device Model: " -msgstr "Модель устройства: " +msgid "DNS on router" +msgstr "" -msgid "Unknown" -msgstr "Неизвестно" +msgid "DHCP has DNS server" +msgstr "" -msgid "works in browser" -msgstr "работает в браузере" +msgid "Checking FakeIP, please wait" +msgstr "" -msgid "does not work in browser" -msgstr "не работает в браузере" +msgid "FakeIP checks passed" +msgstr "" -msgid "works on router" -msgstr "работает на роутере" +msgid "FakeIP checks partially passed" +msgstr "" -msgid "does not work on router" -msgstr "не работает на роутере" +msgid "FakeIP checks failed" +msgstr "" -msgid "Config: " -msgstr "Конфигурация: " +msgid "Router DNS is routed through sing-box" +msgstr "" + +msgid "Router DNS is not routed through sing-box" +msgstr "" + +msgid "Browser is using FakeIP correctly" +msgstr "" + +msgid "Browser is not using FakeIP" +msgstr "" + +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +msgid "Checking nftables, please wait" +msgstr "" + +msgid "Cannot receive nftables checks result" +msgstr "" + +msgid "Nftables checks passed" +msgstr "" + +msgid "Nftables checks partially passed" +msgstr "" + +msgid "Table exist" +msgstr "" + +msgid "Rules mangle exist" +msgstr "" + +msgid "Rules mangle counters" +msgstr "" + +msgid "Rules mangle output exist" +msgstr "" + +msgid "Rules mangle output counters" +msgstr "" + +msgid "Rules proxy exist" +msgstr "" + +msgid "Rules proxy counters" +msgstr "" + +msgid "No other marking rules found" +msgstr "" + +msgid "Additional marking rules found" +msgstr "" + +msgid "Checking sing-box, please wait" +msgstr "" + +msgid "Cannot receive Sing-box checks result" +msgstr "" + +msgid "Sing-box checks passed" +msgstr "" + +msgid "Sing-box installed" +msgstr "" + +msgid "Sing-box version >= 1.12.4" +msgstr "" + +msgid "Sing-box service exist" +msgstr "" + +msgid "Sing-box autostart disabled" +msgstr "" + +msgid "Sing-box process running" +msgstr "" + +msgid "Sing-box listening ports" +msgstr "" + +msgid "Restart podkop" +msgstr "" + +msgid "Stop podkop" +msgstr "" + +msgid "Start podkop" +msgstr "" + +msgid "Disable autostart" +msgstr "" + +msgid "Enable autostart" +msgstr "" + +msgid "Get global check" +msgstr "" + +msgid "Not implement yet" +msgstr "" + +msgid "Run Diagnostic" +msgstr "" + +msgid "Valid" +msgstr "Валидно" + +msgid "Invalid IP address" +msgstr "Неверный IP-адрес" + +msgid "Invalid domain address" +msgstr "Неверный домен" + +msgid "DNS server address cannot be empty" +msgstr "Адрес DNS-сервера не может быть пустым" + +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "Неверный формат DNS-сервера. Примеры: 8.8.8.8, dns.example.com или dns.example.com/nicedns для DoH" + +msgid "URL must use one of the following protocols:" +msgstr "URL должен использовать один из следующих протоколов:" + +msgid "Invalid URL format" +msgstr "Неверный формат URL" + +msgid "Path cannot be empty" +msgstr "Путь не может быть пустым" + +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "Неверный формат. Используйте X.X.X.X или X.X.X.X/Y" + +msgid "IP address 0.0.0.0 is not allowed" +msgstr "IP-адрес 0.0.0.0 не допускается" + +msgid "CIDR must be between 0 and 32" +msgstr "CIDR должен быть между 0 и 32" + +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "Неверный URL Shadowsocks: должен начинаться с ss://" + +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "Неверный URL Shadowsocks: не должен содержать пробелов" + +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "Неверный URL Shadowsocks: отсутствуют учетные данные" + +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "Неверный URL Shadowsocks: декодированные данные должны содержать method:password" + +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "Неверный URL Shadowsocks: отсутствует адрес сервера" + +msgid "Invalid Shadowsocks URL: missing server" +msgstr "Неверный URL Shadowsocks: отсутствует сервер" + +msgid "Invalid Shadowsocks URL: missing port" +msgstr "Неверный URL Shadowsocks: отсутствует порт" + +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "Неверный номер порта. Допустимо от 1 до 65535" + +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "Неверный URL Shadowsocks: ошибка разбора" + +msgid "Invalid VLESS URL: parsing failed" +msgstr "Неверный URL VLESS: ошибка разбора" + +msgid "Invalid JSON format" +msgstr "Неверный формат JSON" + +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "Неверный URL Trojan: должен начинаться с trojan://" + +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "Неверный URL Trojan: не должен содержать пробелов" + +msgid "Invalid Trojan URL: parsing failed" +msgstr "Неверный URL Trojan: ошибка разбора" + +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +msgid "Fastest" +msgstr "Самый быстрый" + +msgid "HTTP error" +msgstr "Ошибка HTTP" + +msgid "Unknown error" +msgstr "Неизвестная ошибка" + +msgid "DNS checks" +msgstr "" + +msgid "Sing-box checks" +msgstr "" + +msgid "Nftables checks" +msgstr "" + +msgid "FakeIP checks" +msgstr "" + +msgid "Not running" +msgstr "" + +msgid "Queued" +msgstr "" + +msgid "Dashboard currently unavailable" +msgstr "Дашборд сейчас недоступен" + +msgid "Test latency" +msgstr "" + +msgid "Currently unavailable" +msgstr "Временно недоступно" + +msgid "Traffic" +msgstr "Трафик" + +msgid "Uplink" +msgstr "Исходящий" + +msgid "Downlink" +msgstr "Входящий" + +msgid "Traffic Total" +msgstr "Всего трафика" + +msgid "System info" +msgstr "Системная информация" + +msgid "Active Connections" +msgstr "Активные соединения" + +msgid "Memory Usage" +msgstr "Использование памяти" + +msgid "Services info" +msgstr "Информация о сервисах" + +msgid "Podkop" +msgstr "Podkop" + +msgid "\\u2714 Enabled" +msgstr "" + +msgid "\\u2718 Disabled" +msgstr "" + +msgid "Sing-box" +msgstr "Sing-box" + +msgid "\\u2714 Running" +msgstr "" + +msgid "\\u2718 Stopped" +msgstr "" + +msgid "Checking dns, please wait" +msgstr "" + +msgid "Cannot receive DNS checks result" +msgstr "" + +msgid "DNS checks passed" +msgstr "" + +msgid "Bootsrap DNS" +msgstr "" + +msgid "Main DNS" +msgstr "" + +msgid "DNS on router" +msgstr "" + +msgid "DHCP has DNS server" +msgstr "" + +msgid "Checking sing-box, please wait" +msgstr "" + +msgid "Cannot receive Sing-box checks result" +msgstr "" + +msgid "Sing-box checks passed" +msgstr "" + +msgid "Sing-box installed" +msgstr "" + +msgid "Sing-box version >= 1.12.4" +msgstr "" + +msgid "Sing-box service exist" +msgstr "" + +msgid "Sing-box autostart disabled" +msgstr "" + +msgid "Sing-box process running" +msgstr "" + +msgid "Sing-box listening ports" +msgstr "" + +msgid "Checking nftables, please wait" +msgstr "" + +msgid "Cannot receive nftables checks result" +msgstr "" + +msgid "Nftables checks passed" +msgstr "" + +msgid "Nftables checks partially passed" +msgstr "" + +msgid "Table exist" +msgstr "" + +msgid "Rules mangle exist" +msgstr "" + +msgid "Rules mangle counters" +msgstr "" + +msgid "Rules mangle output exist" +msgstr "" + +msgid "Rules mangle output counters" +msgstr "" + +msgid "Rules proxy exist" +msgstr "" + +msgid "Rules proxy counters" +msgstr "" + +msgid "No other marking rules found" +msgstr "" + +msgid "Additional marking rules found" +msgstr "" + +msgid "Checking FakeIP, please wait" +msgstr "" + +msgid "FakeIP checks passed" +msgstr "" + +msgid "FakeIP checks partially passed" +msgstr "" + +msgid "FakeIP checks failed" +msgstr "" + +msgid "Router DNS is routed through sing-box" +msgstr "" + +msgid "Router DNS is not routed through sing-box" +msgstr "" + +msgid "Browser is using FakeIP correctly" +msgstr "" + +msgid "Browser is not using FakeIP" +msgstr "" + +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +msgid "Successfully copied!" +msgstr "" + +msgid "Failed to copy!" +msgstr "" + +msgid "Download" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Close" +msgstr "Закрыть" + +msgid "Restart podkop" +msgstr "" + +msgid "Stop podkop" +msgstr "" + +msgid "Start podkop" +msgstr "" + +msgid "Disable autostart" +msgstr "" + +msgid "Enable autostart" +msgstr "" + +msgid "Get global check" +msgstr "" + +msgid "View logs" +msgstr "" + +msgid "Show sing-box config" +msgstr "" + +msgid "Not implement yet" +msgstr "" + +msgid "Run Diagnostic" +msgstr "" + +msgid "unknown" +msgstr "" + +msgid "Global check" +msgstr "Глобальная проверка" + +msgid "Outdated" +msgstr "" + +msgid "Latest" +msgstr "" + +msgid "Operation timed out" +msgstr "Время ожидания истекло" + +msgid "Podkop Settings" +msgstr "" + +msgid "Configuration for Podkop service" +msgstr "" + +msgid "Sections" +msgstr "" + +msgid "Settings" +msgstr "" msgid "Diagnostics" msgstr "Диагностика" -msgid "Additional Settings" -msgstr "Дополнительные настройки" +msgid "Dashboard" +msgstr "Дашборд" -msgid "Yacd enable" -msgstr "Включить YACD" +msgid "Connection Type" +msgstr "Тип подключения" -msgid "Exclude NTP" -msgstr "Исключить NTP" +msgid "Select between VPN and Proxy connection methods for traffic routing" +msgstr "Выберите между VPN и Proxy методами для маршрутизации трафика" -msgid "Allows you to exclude NTP protocol traffic from the tunnel" -msgstr "Позволяет исключить направление трафика NTP-протокола в туннель" +msgid "Configuration Type" +msgstr "Тип конфигурации" -msgid "QUIC disable" -msgstr "Отключить QUIC" +msgid "Select how to configure the proxy" +msgstr "Выберите способ настройки прокси" -msgid "For issues with the video stream" -msgstr "Для проблем с видеопотоком" +msgid "Connection URL" +msgstr "URL подключения" -msgid "List Update Frequency" -msgstr "Частота обновления списков" +msgid "Outbound Config" +msgstr "Конфигурация Outbound" -msgid "Select how often the lists will be updated" -msgstr "Выберите как часто будут обновляться списки" +msgid "URLTest" +msgstr "URLTest" + +msgid "Proxy Configuration URL" +msgstr "URL конфигурации прокси" + +msgid "Outbound Configuration" +msgstr "Конфигурация исходящего соединения" + +msgid "Enter complete outbound configuration in JSON format" +msgstr "Введите полную конфигурацию исходящего соединения в формате JSON" + +msgid "URLTest Proxy Links" +msgstr "Ссылки прокси для URLTest" + +msgid "UDP over TCP" +msgstr "" + +msgid "Applicable for SOCKS and Shadowsocks proxy" +msgstr "" + +msgid "Network Interface" +msgstr "Сетевой интерфейс" + +msgid "Select network interface for VPN connection" +msgstr "Выберите сетевой интерфейс для VPN подключения" + +msgid "Domain Resolver" +msgstr "Резолвер доменов" + +msgid "Enable built-in DNS resolver for domains handled by this section" +msgstr "Включить встроенный DNS-резолвер для доменов, обрабатываемых в этом разделе" + +msgid "DNS Protocol Type" +msgstr "Тип протокола DNS" + +msgid "Select the DNS protocol type for the domain resolver" +msgstr "Выберите тип протокола DNS для резолвера доменов" + +msgid "DNS over HTTPS (DoH)" +msgstr "DNS через HTTPS (DoH)" + +msgid "DNS over TLS (DoT)" +msgstr "DNS через TLS (DoT)" + +msgid "UDP (Unprotected DNS)" +msgstr "UDP (Незащищённый DNS)" + +msgid "DNS Server" +msgstr "DNS-сервер" + +msgid "Select or enter DNS server address" +msgstr "Выберите или введите адрес DNS-сервера" + +msgid "" +msgstr "" + +msgid "Community Lists" +msgstr "Списки сообщества" + +msgid "Select a predefined list for routing" +msgstr "" + +msgid "Regional options cannot be used together" +msgstr "Нельзя использовать несколько региональных опций одновременно" + +msgid "Warning: %s cannot be used together with %s. Previous selections have been removed." +msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены." + +msgid "Russia inside restrictions" +msgstr "Ограничения Russia inside" + +msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." +msgstr "" + +msgid "User Domain List Type" +msgstr "Тип пользовательского списка доменов" + +msgid "Select the list type for adding custom domains" +msgstr "" + +msgid "Disabled" +msgstr "Отключено" + +msgid "Dynamic List" +msgstr "Динамический список" + +msgid "Text List" +msgstr "Текстовый список" + +msgid "User Domains" +msgstr "Пользовательские домены" + +msgid "Enter domain names without protocols, e.g. example.com or sub.example.com" +msgstr "" + +msgid "User Domains List" +msgstr "Список пользовательских доменов" + +msgid "Enter domain names separated by commas, spaces, or newlines. You can add comments using //" +msgstr "" + +msgid "At least one valid domain must be specified. Comments-only content is not allowed." +msgstr "Необходимо указать хотя бы один действительный домен. Содержимое только из комментариев не допускается." + +msgid "${validation.value}: ${validation.message}" +msgstr "" + +msgid "Validation errors:" +msgstr "Ошибки валидации:" + +msgid "User Subnet List Type" +msgstr "Тип пользовательского списка подсетей" + +msgid "Select the list type for adding custom subnets" +msgstr "" + +msgid "Text List (comma/space/newline separated)" +msgstr "Текстовый список (через запятую, пробел или новую строку)" + +msgid "User Subnets" +msgstr "Пользовательские подсети" + +msgid "Enter subnets in CIDR notation (e.g. 103.21.244.0/22) or single IP addresses" +msgstr "" + +msgid "User Subnets List" +msgstr "Список пользовательских подсетей" + +msgid "Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //" +msgstr "" + +msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." +msgstr "Необходимо указать хотя бы одну действительную подсеть или IP. Только комментарии недопустимы." + +msgid "Local Domain Lists" +msgstr "Локальные списки доменов" + +msgid "Specify the path to the list file located on the router filesystem" +msgstr "" + +msgid "Local Subnet Lists" +msgstr "Локальные списки подсетей" + +msgid "Remote Domain Lists" +msgstr "Удалённые списки доменов" + +msgid "Specify remote URLs to download and use domain lists" +msgstr "" + +msgid "Remote Subnet Lists" +msgstr "Удалённые списки подсетей" + +msgid "Specify remote URLs to download and use subnet lists" +msgstr "" + +msgid "Fully Routed IPs" +msgstr "" + +msgid "Specify local IP addresses or subnets whose traffic will always be routed through the configured route" +msgstr "" + +msgid "Enable Mixed Proxy" +msgstr "" + +msgid "Enable the mixed proxy, allowing this section to route traffic through both HTTP and SOCKS proxies" +msgstr "" + +msgid "Mixed Proxy Port" +msgstr "" + +msgid "Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service" +msgstr "" msgid "Select DNS protocol to use" msgstr "Выберите протокол DNS" @@ -623,6 +977,78 @@ msgstr "Значение TTL не может быть пустым" msgid "TTL must be a positive number" msgstr "TTL должно быть положительным числом" +msgid "Source Network Interface" +msgstr "Сетевой интерфейс источника" + +msgid "Select the network interface from which the traffic will originate" +msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик" + +msgid "Enable Output Network Interface" +msgstr "" + +msgid "You can select Output Network Interface, by default autodetect" +msgstr "" + +msgid "Output Network Interface" +msgstr "" + +msgid "Select the network interface to which the traffic will originate" +msgstr "" + +msgid "Interface Monitoring" +msgstr "" + +msgid "Interface monitoring for Bad WAN" +msgstr "" + +msgid "Monitored Interfaces" +msgstr "" + +msgid "Select the WAN interfaces to be monitored" +msgstr "Выберите WAN интерфейсы для мониторинга" + +msgid "Interface Monitoring Delay" +msgstr "Задержка при мониторинге интерфейсов" + +msgid "Delay in milliseconds before reloading podkop after interface UP" +msgstr "Задержка в миллисекундах перед перезагрузкой podkop после поднятия интерфейса" + +msgid "Delay value cannot be empty" +msgstr "Значение задержки не может быть пустым" + +msgid "Enable YACD" +msgstr "" + +msgid "Disable QUIC" +msgstr "" + +msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming" +msgstr "" + +msgid "List Update Frequency" +msgstr "Частота обновления списков" + +msgid "Select how often the domain or subnet lists are updated automatically" +msgstr "" + +msgid "Download Lists via Proxy/VPN" +msgstr "" + +msgid "Downloading all lists via main Proxy/VPN" +msgstr "Загрузка всех списков через основной прокси/VPN" + +msgid "Download Lists via specific proxy section" +msgstr "" + +msgid "Downloading all lists via specific Proxy/VPN" +msgstr "" + +msgid "Dont Touch My DHCP!" +msgstr "" + +msgid "Podkop will not modify your DHCP configuration" +msgstr "" + msgid "Config File Path" msgstr "Путь к файлу конфигурации" @@ -647,53 +1073,14 @@ msgstr "Путь должен заканчиваться на cache.db" msgid "Path must contain at least one directory (like /tmp/cache.db)" msgstr "Путь должен содержать хотя бы одну директорию (например /tmp/cache.db)" -msgid "Source Network Interface" -msgstr "Сетевой интерфейс источника" +msgid "Exclude NTP" +msgstr "Исключить NTP" -msgid "Select the network interface from which the traffic will originate" -msgstr "Выберите сетевой интерфейс, с которого будет исходить трафик" +msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN" +msgstr "" -msgid "Interface monitoring" -msgstr "Мониторинг интерфейсов" +msgid "Routing Excluded IPs" +msgstr "" -msgid "Interface monitoring for bad WAN" -msgstr "Мониторинг интерфейсов для плохого WAN" - -msgid "Interface for monitoring" -msgstr "Интерфейс для мониторинга" - -msgid "Select the WAN interfaces to be monitored" -msgstr "Выберите WAN интерфейсы для мониторинга" - -msgid "Interface Monitoring Delay" -msgstr "Задержка при мониторинге интерфейсов" - -msgid "Delay in milliseconds before reloading podkop after interface UP" -msgstr "Задержка в миллисекундах перед перезагрузкой podkop после поднятия интерфейса" - -msgid "Delay value cannot be empty" -msgstr "Значение задержки не может быть пустым" - -msgid "Dont touch my DHCP!" -msgstr "Не трогать мой DHCP!" - -msgid "Podkop will not change the DHCP config" -msgstr "Podkop не будет изменять конфигурацию DHCP" - -msgid "Proxy download of lists" -msgstr "Загрузка списков через прокси" - -msgid "Downloading all lists via main Proxy/VPN" -msgstr "Загрузка всех списков через основной прокси/VPN" - -msgid "IP for exclusion" -msgstr "IP для исключения" - -msgid "Specify local IP addresses that will never use the configured route" -msgstr "Укажите локальные IP-адреса, которые никогда не будут использовать настроенный маршрут" - -msgid "Mixed enable" -msgstr "Включить смешанный режим" - -msgid "Browser port: 2080" -msgstr "Порт браузера: 2080" +msgid "Specify a local IP address to be excluded from routing" +msgstr "" diff --git a/luci-app-podkop/po/templates/podkop.pot b/luci-app-podkop/po/templates/podkop.pot index 778c412..64f11d4 100644 --- a/luci-app-podkop/po/templates/podkop.pot +++ b/luci-app-podkop/po/templates/podkop.pot @@ -1,954 +1,1517 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# Copyright (C) 2025 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PODKOP package. -# FIRST AUTHOR , YEAR. -# +# divocat , 2025. #, fuzzy msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-07 16:55+0300\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" +"POT-Creation-Date: 2025-10-21 18:31+0300\n" +"PO-Revision-Date: 2025-10-21 18:31+0300\n" +"Last-Translator: divocat \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: htdocs/luci-static/resources/view/podkop/configSection.js:12 -msgid "Basic Settings" +#: src/helpers/copyToClipboard.ts:10 +msgid "Successfully copied!" msgstr "" -#: htdocs/luci-static/resources/view/podkop/configSection.js:18 -msgid "Connection Type" +#: src/helpers/copyToClipboard.ts:12 +msgid "Failed to copy!" msgstr "" -#: htdocs/luci-static/resources/view/podkop/configSection.js:19 -msgid "Select between VPN and Proxy connection methods for traffic routing" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:30 -msgid "Configuration Type" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:31 -msgid "Select how to configure the proxy" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:33 -msgid "Connection URL" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:34 -msgid "Outbound Config" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:35 -msgid "URLTest" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:44 -msgid "Proxy Configuration URL" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:81 -msgid "Current config: " -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:88 -#: htdocs/luci-static/resources/view/podkop/configSection.js:96 -#: htdocs/luci-static/resources/view/podkop/configSection.js:106 -msgid "Config without description" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:115 -msgid "" -"Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup " -"configs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:139 -msgid "No active configuration found. One configuration is required." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:145 -msgid "Multiply active configurations found. Please leave one configuration." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:157 -msgid "Invalid URL format:" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:165 -msgid "Outbound Configuration" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:166 -msgid "Enter complete outbound configuration in JSON format" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:190 -msgid "URLTest Proxy Links" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:214 -msgid "Shadowsocks UDP over TCP" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:215 -msgid "Apply for SS2022" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:226 -msgid "Network Interface" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:227 -msgid "Select network interface for VPN connection" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:274 -msgid "Domain Resolver" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:275 -msgid "Enable built-in DNS resolver for domains handled by this section" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:286 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:61 -msgid "DNS Protocol Type" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:287 -msgid "Select the DNS protocol type for the domain resolver" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:289 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:64 -msgid "DNS over HTTPS (DoH)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:290 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:65 -msgid "DNS over TLS (DoT)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:291 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:66 -msgid "UDP (Unprotected DNS)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:301 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:75 -msgid "DNS Server" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:302 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:76 -msgid "Select or enter DNS server address" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:325 -msgid "Community Lists" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:335 -msgid "Service List" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:336 -msgid "Select predefined service for routing" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:372 -msgid "Regional options cannot be used together" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:375 -#, javascript-format -msgid "Warning: %s cannot be used together with %s. Previous selections have been removed." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:391 -msgid "Russia inside restrictions" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:394 -#, javascript-format -msgid "" -"Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:427 -msgid "User Domain List Type" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:428 -msgid "Select how to add your custom domains" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:430 -#: htdocs/luci-static/resources/view/podkop/configSection.js:625 -msgid "Disabled" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:431 -#: htdocs/luci-static/resources/view/podkop/configSection.js:626 -msgid "Dynamic List" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:432 -msgid "Text List" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:441 -msgid "User Domains" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:443 -msgid "Enter domain names without protocols (example: sub.example.com or example.com)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:469 -msgid "User Domains List" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:471 -msgid "Enter domain names separated by comma, space or newline. You can add comments after //" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:490 -msgid "At least one valid domain must be specified. Comments-only content is not allowed." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:501 -#: htdocs/luci-static/resources/view/podkop/configSection.js:696 -msgid "Validation errors:" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:511 -msgid "Local Domain Lists" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:512 -#: htdocs/luci-static/resources/view/podkop/configSection.js:586 -msgid "Use the list from the router filesystem" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:522 -msgid "Local Domain List Paths" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:523 -#: htdocs/luci-static/resources/view/podkop/configSection.js:597 -msgid "Enter the list file path" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:548 -msgid "Remote Domain Lists" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:549 -msgid "Download and use domain lists from remote URLs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:559 -msgid "Remote Domain URLs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:560 -#: htdocs/luci-static/resources/view/podkop/configSection.js:718 -msgid "Enter full URLs starting with http:// or https://" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:585 -msgid "Local Subnet Lists" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:596 -msgid "Local Subnet List Paths" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:622 -msgid "User Subnet List Type" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:623 -msgid "Select how to add your custom subnets" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:627 -msgid "Text List (comma/space/newline separated)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:636 -msgid "User Subnets" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:638 -msgid "Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:664 -msgid "User Subnets List" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:666 -msgid "" -"Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments " -"after //" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:685 -msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:706 -msgid "Remote Subnet Lists" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:707 -msgid "Download and use subnet lists from remote URLs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:717 -msgid "Remote Subnet URLs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:743 -msgid "IP for full redirection" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:745 -msgid "Specify local IP addresses whose traffic will always use the configured route" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:756 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:326 -msgid "Local IPs" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/configSection.js:757 -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:327 -msgid "Enter valid IPv4 addresses" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/podkop.js:64 -msgid "Extra configurations" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/podkop.js:68 -msgid "Add Section" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/dashboardTab.js:11 -msgid "Dashboard" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:11 htdocs/luci-static/resources/view/podkop/main.js:28 -#: htdocs/luci-static/resources/view/podkop/main.js:37 htdocs/luci-static/resources/view/podkop/main.js:40 -#: htdocs/luci-static/resources/view/podkop/main.js:60 htdocs/luci-static/resources/view/podkop/main.js:115 -#: htdocs/luci-static/resources/view/podkop/main.js:204 htdocs/luci-static/resources/view/podkop/main.js:295 -#: htdocs/luci-static/resources/view/podkop/main.js:313 htdocs/luci-static/resources/view/podkop/main.js:346 -msgid "Valid" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:13 -msgid "Invalid IP address" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:20 htdocs/luci-static/resources/view/podkop/main.js:26 -msgid "Invalid domain address" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:34 -msgid "DNS server address cannot be empty" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:45 -msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:57 -msgid "URL must use one of the following protocols:" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:62 -msgid "Invalid URL format" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:71 -msgid "Path cannot be empty" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:84 -msgid "Invalid path format. Path must start with \"/\" and contain valid characters" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:95 -msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:100 -msgid "IP address 0.0.0.0 is not allowed" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:111 -msgid "CIDR must be between 0 and 32" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:132 -msgid "Invalid Shadowsocks URL: must start with ss://" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:139 -msgid "Invalid Shadowsocks URL: must not contain spaces" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:147 -msgid "Invalid Shadowsocks URL: missing credentials" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:156 -msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:165 -msgid "Invalid Shadowsocks URL: missing method and password separator \":\"" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:174 -msgid "Invalid Shadowsocks URL: missing server address" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:181 -msgid "Invalid Shadowsocks URL: missing server" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:188 -msgid "Invalid Shadowsocks URL: missing port" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:195 -msgid "Invalid port number. Must be between 1 and 65535" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:201 -msgid "Invalid Shadowsocks URL: parsing failed" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:214 -msgid "Invalid VLESS URL: must not contain spaces" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:220 -msgid "Invalid VLESS URL: must start with vless://" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:224 -msgid "Invalid VLESS URL: missing UUID" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:227 -msgid "Invalid VLESS URL: missing server" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:230 -msgid "Invalid VLESS URL: missing port" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:236 -msgid "Invalid VLESS URL: invalid port number. Must be between 1 and 65535" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:243 -msgid "Invalid VLESS URL: missing query parameters" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:263 -msgid "Invalid VLESS URL: type must be one of tcp, raw, udp, grpc, http, ws" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:273 -msgid "Invalid VLESS URL: security must be one of tls, reality, none" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:282 -msgid "Invalid VLESS URL: missing pbk parameter for reality security" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:290 -msgid "Invalid VLESS URL: missing fp parameter for reality security" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:297 -msgid "Invalid VLESS URL: parsing failed" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:309 -msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:315 -msgid "Invalid JSON format" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:324 -msgid "Invalid Trojan URL: must start with trojan://" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:330 -msgid "Invalid Trojan URL: must not contain spaces" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:339 -msgid "Invalid Trojan URL: must contain username, hostname and port" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:344 -msgid "Invalid Trojan URL: parsing failed" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:362 -msgid "URL must start with vless:// or ss:// or trojan://" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/main.js:568 +#: src/helpers/withTimeout.ts:7 msgid "Operation timed out" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:775 +#: src/podkop/api.ts:27 msgid "HTTP error" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:786 +#: src/podkop/api.ts:40 msgid "Unknown error" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:951 -msgid "Fastest" +#: src/validators/validateDns.ts:7 +msgid "DNS server address cannot be empty" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1222 -msgid "Dashboard currently unavailable" +#: src/validators/validateDns.ts:11 +#: src/validators/validateDns.ts:15 +#: src/validators/validateDomain.ts:13 +#: src/validators/validateDomain.ts:30 +#: src/validators/validateIp.ts:8 +#: src/validators/validateOutboundJson.ts:17 +#: 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 +msgid "Valid" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1326 -msgid "Currently unavailable" +#: src/validators/validateDns.ts:20 +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1721 -msgid "Traffic" +#: src/validators/validateDomain.ts:18 +#: src/validators/validateDomain.ts:27 +msgid "Invalid domain address" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1723 htdocs/luci-static/resources/view/podkop/main.js:1748 -msgid "Uplink" +#: src/validators/validateIp.ts:11 +msgid "Invalid IP address" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1724 htdocs/luci-static/resources/view/podkop/main.js:1752 -msgid "Downlink" +#: src/validators/validateOutboundJson.ts:11 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:327 +msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1745 -msgid "Traffic Total" +#: src/validators/validateOutboundJson.ts:19 +msgid "Invalid JSON format" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1775 -msgid "System info" +#: src/validators/validatePath.ts:7 +msgid "Path cannot be empty" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1778 -msgid "Active Connections" +#: src/validators/validatePath.ts:22 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:90 +msgid "Invalid path format. Path must start with \"/\" and contain valid characters" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1782 -msgid "Memory Usage" +#: src/validators/validateProxyUrl.ts:27 +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1805 -msgid "Services info" +#: src/validators/validateShadowsocksUrl.ts:8 +msgid "Invalid Shadowsocks URL: must start with ss://" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1808 htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1139 -msgid "Podkop" +#: src/validators/validateShadowsocksUrl.ts:16 +msgid "Invalid Shadowsocks URL: must not contain spaces" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1809 -msgid "✔ Enabled" +#: src/validators/validateShadowsocksUrl.ts:27 +msgid "Invalid Shadowsocks URL: missing credentials" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1809 -msgid "✘ Disabled" +#: src/validators/validateShadowsocksUrl.ts:37 +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1815 -msgid "Sing-box" +#: src/validators/validateShadowsocksUrl.ts:46 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:171 +msgid "Invalid Shadowsocks URL: missing method and password separator \":\"" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1816 -msgid "✔ Running" +#: src/validators/validateShadowsocksUrl.ts:58 +msgid "Invalid Shadowsocks URL: missing server address" msgstr "" -#: htdocs/luci-static/resources/view/podkop/main.js:1816 -msgid "✘ Stopped" +#: src/validators/validateShadowsocksUrl.ts:67 +msgid "Invalid Shadowsocks URL: missing server" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:137 -msgid "Copied!" +#: src/validators/validateShadowsocksUrl.ts:76 +msgid "Invalid Shadowsocks URL: missing port" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:143 -msgid "Failed to copy: " +#: src/validators/validateShadowsocksUrl.ts:85 +msgid "Invalid port number. Must be between 1 and 65535" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:327 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:542 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:759 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:762 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:765 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:768 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:771 -msgid "Loading..." +#: src/validators/validateShadowsocksUrl.ts:91 +msgid "Invalid Shadowsocks URL: parsing failed" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:351 -msgid "Copy to Clipboard" +#: src/validators/validateSocksUrl.ts:10 +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:359 +#: src/validators/validateSocksUrl.ts:19 +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +#: src/validators/validateSocksUrl.ts:34 +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +#: src/validators/validateSocksUrl.ts:42 +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +#: src/validators/validateSocksUrl.ts:51 +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +#: src/validators/validateSocksUrl.ts:56 +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +#: src/validators/validateSocksUrl.ts:63 +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +#: src/validators/validateSocksUrl.ts:73 +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +#: src/validators/validateSocksUrl.ts:77 +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +#: src/validators/validateSubnet.ts:11 +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "" + +#: src/validators/validateSubnet.ts:18 +msgid "IP address 0.0.0.0 is not allowed" +msgstr "" + +#: src/validators/validateSubnet.ts:33 +msgid "CIDR must be between 0 and 32" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:8 +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:15 +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "" + +#: src/validators/validateTrojanUrl.ts:56 +msgid "Invalid Trojan URL: parsing failed" +msgstr "" + +#: src/validators/validateUrl.ts:13 +msgid "URL must use one of the following protocols:" +msgstr "" + +#: src/validators/validateUrl.ts:18 +msgid "Invalid URL format" +msgstr "" + +#: src/validators/validateVlessUrl.ts:109 +msgid "Invalid VLESS URL: parsing failed" +msgstr "" + +#: src/partials/modal/renderModal.ts:15 +msgid "Download" +msgstr "" + +#: src/partials/modal/renderModal.ts:20 +msgid "Copy" +msgstr "" + +#: src/partials/modal/renderModal.ts:26 msgid "Close" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:380 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:483 -msgid "No output" +#: src/podkop/methods/custom/getDashboardSections.ts:117 +msgid "Fastest" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:398 -msgid "FakeIP is working in browser!" +#: src/podkop/tabs/dashboard/initController.ts:235 +msgid "Traffic" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:401 -msgid "FakeIP is not working in browser" +#: src/podkop/tabs/dashboard/initController.ts:237 +#: src/podkop/tabs/dashboard/initController.ts:268 +msgid "Uplink" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:403 -msgid "Check DNS server on current device (PC, phone)" +#: src/podkop/tabs/dashboard/initController.ts:238 +#: src/podkop/tabs/dashboard/initController.ts:272 +msgid "Downlink" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:404 -msgid "Its must be router!" +#: src/podkop/tabs/dashboard/initController.ts:265 +msgid "Traffic Total" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:426 -msgid "Proxy working correctly" +#: src/podkop/tabs/dashboard/initController.ts:301 +msgid "System info" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:428 -msgid "Direct IP: " +#: src/podkop/tabs/dashboard/initController.ts:304 +msgid "Active Connections" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:430 -msgid "Proxy IP: " +#: src/podkop/tabs/dashboard/initController.ts:308 +msgid "Memory Usage" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:434 -msgid "Proxy is not working - same IP for both domains" +#: src/podkop/tabs/dashboard/initController.ts:337 +msgid "Services info" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:437 -msgid "IP: " +#: src/podkop/tabs/dashboard/initController.ts:340 +msgid "Podkop" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:440 -msgid "Proxy check failed" +#: src/podkop/tabs/dashboard/initController.ts:342 +msgid "✔ Enabled" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:448 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:459 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:470 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:477 -msgid "Check failed: " +#: src/podkop/tabs/dashboard/initController.ts:343 +msgid "✘ Disabled" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:450 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:461 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:471 -msgid "timeout" +#: src/podkop/tabs/dashboard/initController.ts:351 +msgid "Sing-box" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:488 -msgid "Error: " +#: src/podkop/tabs/dashboard/initController.ts:353 +msgid "✔ Running" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:571 -msgid "Podkop Status" +#: src/podkop/tabs/dashboard/initController.ts:354 +msgid "✘ Stopped" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:604 +#: 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 +msgid "Not running" +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 "" + +#: 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 +msgid "unknown" +msgstr "" + +#: src/podkop/tabs/diagnostic/initController.ts:218 msgid "Global check" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:606 -msgid "Click here for all the info" +#: src/podkop/tabs/diagnostic/initController.ts:248 +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107 +msgid "View logs" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:614 -msgid "Update Lists" +#: src/podkop/tabs/diagnostic/initController.ts:278 +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116 +msgid "Show sing-box config" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:616 -msgid "Lists Update Results" +#: src/podkop/tabs/diagnostic/initController.ts:394 +msgid "Outdated" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:633 -msgid "Sing-box Status" +#: src/podkop/tabs/diagnostic/initController.ts:404 +msgid "Latest" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:660 -msgid "Check NFT Rules" +#: src/podkop/tabs/dashboard/partials/renderSections.ts:19 +msgid "Dashboard currently unavailable" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:662 -msgid "NFT Rules" +#: src/podkop/tabs/dashboard/partials/renderSections.ts:108 +msgid "Test latency" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:665 -msgid "Check DNSMasq" +#: src/podkop/tabs/dashboard/partials/renderWidget.ts:22 +msgid "Currently unavailable" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:667 -msgid "DNSMasq Configuration" +#: src/podkop/tabs/diagnostic/checks/contstants.ts:14 +msgid "DNS checks" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:684 -msgid "FakeIP Status" +#: src/podkop/tabs/diagnostic/checks/contstants.ts:19 +msgid "Sing-box checks" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:711 -msgid "DNS Status" +#: src/podkop/tabs/diagnostic/checks/contstants.ts:24 +msgid "Nftables checks" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:728 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1096 -msgid "Main config" +#: src/podkop/tabs/diagnostic/checks/contstants.ts:29 +msgid "FakeIP checks" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:748 -msgid "Version Information" +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:14 +msgid "Checking dns, please wait" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:758 -msgid "Podkop: " +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:26 +msgid "Cannot receive DNS checks result" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:761 -msgid "LuCI App: " +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:64 +msgid "DNS checks passed" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:764 -msgid "Sing-box: " +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:72 +msgid "Bootsrap DNS" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:767 -msgid "OpenWrt Version: " +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:79 +msgid "Main DNS" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:770 -msgid "Device Model: " +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:84 +msgid "DNS on router" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:916 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:929 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:943 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:962 -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:964 -msgid "Unknown" +#: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:89 +msgid "DHCP has DNS server" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:988 -msgid "works in browser" +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:14 +msgid "Checking FakeIP, please wait" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:989 -msgid "does not work in browser" +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:44 +msgid "FakeIP checks passed" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1014 -msgid "works on router" +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:51 +msgid "FakeIP checks partially passed" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1015 -msgid "does not work on router" +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:57 +msgid "FakeIP checks failed" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1110 -msgid "Config: " +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:73 +msgid "Router DNS is routed through sing-box" msgstr "" -#: htdocs/luci-static/resources/view/podkop/diagnosticTab.js:1127 +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:74 +msgid "Router DNS is not routed through sing-box" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:80 +msgid "Browser is using FakeIP correctly" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:81 +msgid "Browser is not using FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:88 +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:89 +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:12 +msgid "Checking nftables, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:27 +msgid "Cannot receive nftables checks result" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:74 +msgid "Nftables checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:75 +msgid "Nftables checks partially passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:80 +msgid "Table exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:85 +msgid "Rules mangle exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:90 +msgid "Rules mangle counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:95 +msgid "Rules mangle output exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:100 +msgid "Rules mangle output counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:105 +msgid "Rules proxy exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:110 +msgid "Rules proxy counters" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:116 +msgid "No other marking rules found" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:117 +msgid "Additional marking rules found" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:12 +msgid "Checking sing-box, please wait" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:24 +msgid "Cannot receive Sing-box checks result" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:66 +msgid "Sing-box checks passed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:71 +msgid "Sing-box installed" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:76 +msgid "Sing-box version >= 1.12.4" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:81 +msgid "Sing-box service exist" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:86 +msgid "Sing-box autostart disabled" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:91 +msgid "Sing-box process running" +msgstr "" + +#: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:96 +msgid "Sing-box listening ports" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:49 +msgid "Restart podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:59 +msgid "Stop podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:69 +msgid "Start podkop" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:79 +msgid "Disable autostart" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:89 +msgid "Enable autostart" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:98 +msgid "Get global check" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderCheckSection.ts:189 +msgid "Not implement yet" +msgstr "" + +#: src/podkop/tabs/diagnostic/partials/renderRunAction.ts:15 +msgid "Run Diagnostic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:12 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:23 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:35 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:44 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:47 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:67 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:85 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:122 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:211 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:314 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:332 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:383 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:449 +msgid "Valid" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:14 +msgid "Invalid IP address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:27 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:33 +msgid "Invalid domain address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:41 +msgid "DNS server address cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:51 +msgid "Invalid DNS server format. Examples: 8.8.8.8 or dns.example.com or dns.example.com/nicedns for DoH" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:64 +msgid "URL must use one of the following protocols:" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:69 +msgid "Invalid URL format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:78 +msgid "Path cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:102 +msgid "Invalid format. Use X.X.X.X or X.X.X.X/Y" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:107 +msgid "IP address 0.0.0.0 is not allowed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:118 +msgid "CIDR must be between 0 and 32" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:139 +msgid "Invalid Shadowsocks URL: must start with ss://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:146 +msgid "Invalid Shadowsocks URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:154 +msgid "Invalid Shadowsocks URL: missing credentials" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:162 +msgid "Invalid Shadowsocks URL: decoded credentials must contain method:password" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:181 +msgid "Invalid Shadowsocks URL: missing server address" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:188 +msgid "Invalid Shadowsocks URL: missing server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:195 +msgid "Invalid Shadowsocks URL: missing port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:202 +msgid "Invalid port number. Must be between 1 and 65535" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:208 +msgid "Invalid Shadowsocks URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:316 +msgid "Invalid VLESS URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:334 +msgid "Invalid JSON format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:344 +msgid "Invalid Trojan URL: must start with trojan://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:350 +msgid "Invalid Trojan URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:381 +msgid "Invalid Trojan URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:392 +msgid "Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:400 +msgid "Invalid SOCKS URL: must not contain spaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:411 +msgid "Invalid SOCKS URL: missing username" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:418 +msgid "Invalid SOCKS URL: missing host and port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:425 +msgid "Invalid SOCKS URL: missing hostname or IP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:429 +msgid "Invalid SOCKS URL: missing port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:435 +msgid "Invalid SOCKS URL: invalid port number" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:443 +msgid "Invalid SOCKS URL: invalid host format" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:447 +msgid "Invalid SOCKS URL: parsing failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:468 +msgid "URL must start with vless://, ss://, trojan://, or socks4/5://" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:692 +msgid "Fastest" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:864 +msgid "HTTP error" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:875 +msgid "Unknown error" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:985 +msgid "DNS checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:990 +msgid "Sing-box checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:995 +msgid "Nftables checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1000 +msgid "FakeIP checks" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1048 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1056 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1064 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1072 +msgid "Not running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1084 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1092 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1100 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1108 +msgid "Queued" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1578 +msgid "Dashboard currently unavailable" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1654 +msgid "Test latency" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:1683 +msgid "Currently unavailable" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2024 +msgid "Traffic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2026 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2051 +msgid "Uplink" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2027 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2055 +msgid "Downlink" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2048 +msgid "Traffic Total" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2078 +msgid "System info" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2081 +msgid "Active Connections" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2085 +msgid "Memory Usage" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2108 +msgid "Services info" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2111 +msgid "Podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112 +msgid "\\u2714 Enabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2112 +msgid "\\u2718 Disabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2118 +msgid "Sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119 +msgid "\\u2714 Running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2119 +msgid "\\u2718 Stopped" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2365 +msgid "Checking dns, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2375 +msgid "Cannot receive DNS checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2397 +msgid "DNS checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2405 +msgid "Bootsrap DNS" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2412 +msgid "Main DNS" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2417 +msgid "DNS on router" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2422 +msgid "DHCP has DNS server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2439 +msgid "Checking sing-box, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2449 +msgid "Cannot receive Sing-box checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2471 +msgid "Sing-box checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2476 +msgid "Sing-box installed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2481 +msgid "Sing-box version >= 1.12.4" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2486 +msgid "Sing-box service exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2491 +msgid "Sing-box autostart disabled" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2496 +msgid "Sing-box process running" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2501 +msgid "Sing-box listening ports" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2518 +msgid "Checking nftables, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2530 +msgid "Cannot receive nftables checks result" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552 +msgid "Nftables checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2552 +msgid "Nftables checks partially passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2557 +msgid "Table exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2562 +msgid "Rules mangle exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2567 +msgid "Rules mangle counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2572 +msgid "Rules mangle output exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2577 +msgid "Rules mangle output counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2582 +msgid "Rules proxy exist" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2587 +msgid "Rules proxy counters" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592 +msgid "No other marking rules found" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2592 +msgid "Additional marking rules found" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2609 +msgid "Checking FakeIP, please wait" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2627 +msgid "FakeIP checks passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2633 +msgid "FakeIP checks partially passed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2638 +msgid "FakeIP checks failed" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651 +msgid "Router DNS is routed through sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2651 +msgid "Router DNS is not routed through sing-box" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656 +msgid "Browser is using FakeIP correctly" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2656 +msgid "Browser is not using FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662 +msgid "Proxy traffic is routed via FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:2662 +msgid "Proxy traffic is not routed via FakeIP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3288 +msgid "Successfully copied!" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3290 +msgid "Failed to copy!" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3306 +msgid "Download" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3311 +msgid "Copy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3318 +msgid "Close" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3350 +msgid "Restart podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3360 +msgid "Stop podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3370 +msgid "Start podkop" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3380 +msgid "Disable autostart" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3390 +msgid "Enable autostart" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3399 +msgid "Get global check" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3408 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3840 +msgid "View logs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3417 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3867 +msgid "Show sing-box config" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3577 +msgid "Not implement yet" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3587 +msgid "Run Diagnostic" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3651 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3652 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3653 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3654 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3655 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3656 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3950 +msgid "unknown" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3813 +msgid "Global check" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3969 +msgid "Outdated" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:3978 +msgid "Latest" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js:4389 +msgid "Operation timed out" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:26 +msgid "Podkop Settings" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:27 +msgid "Configuration for Podkop service" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36 +msgid "Sections" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:49 +msgid "Settings" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:65 msgid "Diagnostics" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:8 -msgid "Additional Settings" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:80 +msgid "Dashboard" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:14 -msgid "Yacd enable" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:12 +msgid "Connection Type" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:25 -msgid "Exclude NTP" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:13 +msgid "Select between VPN and Proxy connection methods for traffic routing" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:26 -msgid "Allows you to exclude NTP protocol traffic from the tunnel" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:22 +msgid "Configuration Type" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:36 -msgid "QUIC disable" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:23 +msgid "Select how to configure the proxy" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:37 -msgid "For issues with the video stream" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:25 +msgid "Connection URL" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:47 -msgid "List Update Frequency" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:26 +msgid "Outbound Config" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:48 -msgid "Select how often the lists will be updated" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:27 +msgid "URLTest" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:62 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:34 +msgid "Proxy Configuration URL" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64 +msgid "Outbound Configuration" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65 +msgid "Enter complete outbound configuration in JSON format" +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:110 +msgid "UDP over TCP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:111 +msgid "Applicable for SOCKS and Shadowsocks proxy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:120 +msgid "Network Interface" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:121 +msgid "Select network interface for VPN connection" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:166 +msgid "Domain Resolver" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:167 +msgid "Enable built-in DNS resolver for domains handled by this section" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:176 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:12 +msgid "DNS Protocol Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:177 +msgid "Select the DNS protocol type for the domain resolver" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:179 +#: ../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/settings.js:16 +msgid "DNS over TLS (DoT)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:181 +#: ../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:189 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:24 +msgid "DNS Server" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:190 +#: ../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/section.js:193 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:217 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:28 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:51 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:254 +msgid "" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:211 +msgid "Community Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:212 +msgid "Select a predefined list for routing" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:245 +msgid "Regional options cannot be used together" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:247 +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:264 +msgid "Russia inside restrictions" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:266 +msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection." +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:299 +msgid "User Domain List Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:300 +msgid "Select the list type for adding custom domains" +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 +msgid "Disabled" +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 +msgid "Dynamic List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:304 +msgid "Text List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:311 +msgid "User Domains" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:312 +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:337 +msgid "User Domains List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:338 +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:356 +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:368 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:447 +msgid "${validation.value}: ${validation.message}" +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 +msgid "Validation errors:" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:379 +msgid "User Subnet List Type" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:380 +msgid "Select the list type for adding custom subnets" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:384 +msgid "Text List (comma/space/newline separated)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:391 +msgid "User Subnets" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:392 +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/section.js:417 +msgid "User Subnets List" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:418 +msgid "Enter subnets in CIDR notation or single IP addresses, separated by commas, spaces, or newlines. \" + \"You can add comments using //" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:437 +msgid "At least one valid subnet or IP must be specified. Comments-only content is not allowed." +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:458 +msgid "Local Domain 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 +msgid "Specify the path to the list file located on the router filesystem" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:481 +msgid "Local Subnet Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:504 +msgid "Remote Domain Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:505 +msgid "Specify remote URLs to download and use domain lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:527 +msgid "Remote Subnet Lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:528 +msgid "Specify remote URLs to download and use subnet lists" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:550 +msgid "Fully Routed IPs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:551 +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:575 +msgid "Enable Mixed Proxy" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:576 +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/section.js:586 +msgid "Mixed Proxy Port" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:587 +msgid "Specify the port number on which the mixed proxy will run for this section. \" + \"Make sure the selected port is not used by another service" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:13 msgid "Select DNS protocol to use" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:98 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:45 msgid "Bootstrap DNS server" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:100 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:46 msgid "The DNS server used to look up the IP address of an upstream DNS server" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:123 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:68 msgid "DNS Rewrite TTL" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:124 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:69 msgid "Time in seconds for DNS record caching (default: 60)" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:131 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:75 msgid "TTL value cannot be empty" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:136 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:80 msgid "TTL must be a positive number" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:146 -msgid "Config File Path" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:148 -msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:161 -msgid "Cache File Path" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:163 -msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:176 -msgid "Cache file path cannot be empty" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:180 -msgid "Path must be absolute (start with /)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:184 -msgid "Path must end with cache.db" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:189 -msgid "Path must contain at least one directory (like /tmp/cache.db)" -msgstr "" - -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:199 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:89 msgid "Source Network Interface" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:200 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:90 msgid "Select the network interface from which the traffic will originate" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:238 -msgid "Interface monitoring" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:126 +msgid "Enable Output Network Interface" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:239 -msgid "Interface monitoring for bad WAN" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127 +msgid "You can select Output Network Interface, by default autodetect" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:249 -msgid "Interface for monitoring" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:135 +msgid "Output Network Interface" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:250 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:136 +msgid "Select the network interface to which the traffic will originate" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:182 +msgid "Interface Monitoring" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:183 +msgid "Interface monitoring for Bad WAN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:191 +msgid "Monitored Interfaces" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:192 msgid "Select the WAN interfaces to be monitored" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:274 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:214 msgid "Interface Monitoring Delay" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:275 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:215 msgid "Delay in milliseconds before reloading podkop after interface UP" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:283 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:222 msgid "Delay value cannot be empty" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:292 -msgid "Dont touch my DHCP!" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:230 +msgid "Enable YACD" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:293 -msgid "Podkop will not change the DHCP config" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:239 +msgid "Disable QUIC" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:303 -msgid "Proxy download of lists" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:240 +msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:304 +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:250 +msgid "List Update Frequency" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:251 +msgid "Select how often the domain or subnet lists are updated automatically" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:262 +msgid "Download Lists via Proxy/VPN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:263 msgid "Downloading all lists via main Proxy/VPN" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:315 -msgid "IP for exclusion" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:271 +msgid "Download Lists via specific proxy section" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:316 -msgid "Specify local IP addresses that will never use the configured route" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:272 +msgid "Downloading all lists via specific Proxy/VPN" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:352 -msgid "Mixed enable" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:300 +msgid "Dont Touch My DHCP!" msgstr "" -#: htdocs/luci-static/resources/view/podkop/additionalTab.js:353 -msgid "Browser port: 2080" +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:301 +msgid "Podkop will not modify your DHCP configuration" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:309 +msgid "Config File Path" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:310 +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/settings.js:322 +msgid "Cache File Path" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:323 +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:336 +msgid "Cache file path cannot be empty" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:340 +msgid "Path must be absolute (start with /)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:344 +msgid "Path must end with cache.db" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349 +msgid "Path must contain at least one directory (like /tmp/cache.db)" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:358 +msgid "Exclude NTP" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:359 +msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:369 +msgid "Routing Excluded IPs" +msgstr "" + +#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370 +msgid "Specify a local IP address to be excluded from routing" msgstr ""