From 3d9edb1c3785f59bc74f65e26d464ecd468c745c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Sep 2026 09:28:31 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=9E=20Sync=202026-09-30=2009:28:31?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-app-adguardhome/.upstream_meta | 2 +- luci-app-adguardhome/po/pt/adguardhome.po | 168 +++++++ luci-app-adguardhome/po/pt_BR/adguardhome.po | 168 +++++++ luci-app-fwlive/Makefile | 2 +- .../resources/view/status/fwlive.js | 4 + luci-app-fwlive/po/de/luci-app-fwlive.po | 297 ++++++------ luci-app-fwlive/po/ru/luci-app-fwlive.po | 297 ++++++------ .../po/templates/luci-app-fwlive.pot | 279 +++++------ luci-app-fwlive/po/zh_Hans/luci-app-fwlive.po | 301 ++++++------ .../root/usr/libexec/fwlive-logging.sh | 180 +++++-- luci-app-homeproxy-pro/Makefile | 2 +- luci-app-homeproxy-pro/README.md | 32 ++ .../homeproxy-pro/scripts/generator/client.uc | 14 + .../scripts/generator/context.uc | 18 + .../homeproxy-pro/scripts/generator/dns.uc | 6 +- .../homeproxy-pro/scripts/generator/route.uc | 98 +++- .../scripts/runtime/china_ip_ruleset.uc | 147 ++++++ .../homeproxy-pro/scripts/runtime/service.sh | 35 +- .../homeproxy-pro/scripts/update_resources.sh | 17 + luci-app-homeproxy-pro/tests/README.md | 1 + .../tests/fixtures/runtime/trace.golden.txt | 1 + luci-app-homeproxy-pro/tests/ucode/run.sh | 8 + .../tests/ucode/test_china_ip_ruleset.sh | 154 ++++++ .../tests/ucode/test_dns_proxy_list.sh | 72 +++ .../tests/ucode/test_generators.sh | 41 ++ luci-app-qosify/po/cs/qosify.po | 451 ++++++++++------- luci-app-qosify/po/de/qosify.po | 16 +- luci-app-qosify/po/es/qosify.po | 441 ++++++++++------- luci-app-qosify/po/ko/qosify.po | 68 +-- luci-app-qosify/po/pl/qosify.po | 456 +++++++++++------- luci-app-qosify/po/pt/qosify.po | 21 +- luci-app-qosify/po/pt_BR/qosify.po | 16 +- luci-app-qosify/po/ru/qosify.po | 16 +- luci-app-qosify/po/zh_Hans/qosify.po | 429 ++++++++-------- luci-app-sfp-info/Makefile | 2 +- luci-app-sfp-info/po/pt/sfp-info.po | 9 +- luci-app-substore/CHANGELOG.md | 93 ++++ luci-app-substore/Makefile | 4 +- luci-app-substore/README.en.md | 19 +- luci-app-substore/README.md | 15 +- luci-app-substore/docs/INSTALL.md | 6 +- .../lib/lua/luci/view/substore/local_form.htm | 3 +- .../lib/lua/luci/view/substore/node_edit.htm | 3 +- .../root/usr/share/substore/core.lua | 42 +- .../root/usr/share/substore/node.lua | 5 + .../usr/share/substore/output_clash_meta.lua | 50 +- .../usr/share/substore/output_formats.lua | 24 +- .../usr/share/substore/output_singbox.lua | 63 ++- .../root/usr/share/substore/output_uri.lua | 10 +- .../share/substore/output_wireguard_conf.lua | 6 +- .../root/usr/share/substore/parser.lua | 175 ++++++- .../usr/share/substore/parser_clash_yaml.lua | 94 +++- .../usr/share/substore/parser_json_config.lua | 5 +- .../root/usr/share/substore/util.lua | 66 ++- .../resources/substore/nodeform.js | 11 +- .../tests/data_integrity_test.lua | 132 +++++ .../tests/output_clash_meta_test.lua | 24 + .../tests/output_formats_test.lua | 48 ++ .../tests/output_full_config_test.lua | 42 +- .../tests/parser_clash_yaml_test.lua | 76 +++ .../tests/protocol_coverage_test.lua | 332 +++++++++++++ luci-app-substore/tests/run_tests.lua | 24 + .../tests/wireguard_conf_test.lua | 17 + luci-app-trafficctl/Makefile | 4 +- .../resources/view/trafficctl/status.js | 8 +- .../root/usr/local/bin/trafficctl-block.sh | 24 +- .../root/usr/local/bin/trafficctl-device.sh | 10 +- .../root/usr/local/bin/trafficctl-fw.sh | 204 +++++++- .../usr/local/bin/trafficctl-ratelimit.sh | 17 +- .../root/usr/local/bin/trafficctl-summary.sh | 15 +- luci-app-wwand/Makefile | 6 +- luci-mod-dashboard/po/cs/dashboard.po | 107 ++-- luci-mod-dashboard/po/es/dashboard.po | 107 ++-- luci-mod-dashboard/po/pl/dashboard.po | 107 ++-- luci-mod-dashboard/po/pt/dashboard.po | 16 +- luci-mod-dashboard/po/pt_BR/dashboard.po | 16 +- luci-mod-dashboard/po/zh_Hans/dashboard.po | 104 ++-- wwand/Makefile | 6 +- 78 files changed, 4594 insertions(+), 1815 deletions(-) create mode 100644 luci-app-adguardhome/po/pt/adguardhome.po create mode 100644 luci-app-adguardhome/po/pt_BR/adguardhome.po create mode 100644 luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc create mode 100644 luci-app-homeproxy-pro/tests/ucode/test_china_ip_ruleset.sh create mode 100644 luci-app-substore/tests/data_integrity_test.lua create mode 100644 luci-app-substore/tests/protocol_coverage_test.lua diff --git a/luci-app-adguardhome/.upstream_meta b/luci-app-adguardhome/.upstream_meta index cfffae49d..e6afc2515 100644 --- a/luci-app-adguardhome/.upstream_meta +++ b/luci-app-adguardhome/.upstream_meta @@ -1,2 +1,2 @@ -c3d5b719f5337ceefa8b5b1f6c1d7b96965a3812 +80de46ce77221bee421a3c19f7d9d0190ee1b7cd e192c5983e50169ed984d48b094798869a0a780b diff --git a/luci-app-adguardhome/po/pt/adguardhome.po b/luci-app-adguardhome/po/pt/adguardhome.po new file mode 100644 index 000000000..fbfe9500c --- /dev/null +++ b/luci-app-adguardhome/po/pt/adguardhome.po @@ -0,0 +1,168 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: pt\n" +"Content-Transfer-Encoding: 8bit\n" +"Last-Translator: Pavel Borecki \n" +"Language-Team: Portuguese \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"PO-Revision-Date: 2026-09-29 12:10+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:244 +msgid "" +"A soft memory cap for the Go runtime, allowing the garbage collector to run " +"more frequently as usage approaches the limit to prevent Out-of-Memory (OOM) " +"kills." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:113 +#: applications/luci-app-adguardhome/root/usr/share/luci/menu.d/luci-app-adguardhome.json:3 +msgid "AdGuard Home" +msgstr "AdGuard Home" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:137 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:199 +msgid "Advanced Settings" +msgstr "Configurações avançadas" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:146 +msgid "Configuration file" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:89 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:147 +msgid "" +"Configuration file must be stored in its own directory, and not in '/etc'." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:159 +msgid "Directory where filters, logs, and statistics are stored." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:132 +msgid "File System Access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:133 +msgid "" +"Files and directories that AdGuard Home should have read-only or read-write " +"access to." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:129 +msgid "General Settings" +msgstr "Configurações gerais" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:138 +msgid "" +"Go environment variables that tune garbage collector and memory management." +msgstr "" + +#: applications/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json:3 +msgid "Grant permissions for the AdGuard Home LuCI app" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:181 +msgid "Group the service runs under." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:149 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:161 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:171 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:181 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:217 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:232 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:247 +msgid "If empty, defaults to" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:139 +msgid "Modify at your own risk." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:24 +msgid "Not running" +msgstr "Não em execução" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:148 +msgid "Parent directory will be owned by the service user." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:83 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:99 +msgid "Path must be absolute." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:86 +msgid "Path must not end with a slash." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:207 +msgid "Read-only access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:208 +msgid "Read-write access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:23 +msgid "Running" +msgstr "A executar" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:122 +msgid "Service Status" +msgstr "Estado do Serviço" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:180 +msgid "Service group" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:170 +msgid "Service user" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:230 +msgid "" +"The maximum number of operating system threads that can execute user-level " +"Go code simultaneously." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:215 +msgid "" +"Tunes the garbage collector's aggressiveness by setting the percentage of " +"heap growth allowed before the next collection cycle triggers." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:171 +msgid "User the service runs under." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:191 +msgid "Verbose logging" +msgstr "Registo de eventos verboso" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:119 +msgid "Version" +msgstr "Versão" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:160 +msgid "Will be owned by the service user." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:158 +msgid "Working directory" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:247 +msgid "unset" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:217 +msgid "unset and 100" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:232 +msgid "unset and matching the number of CPUs" +msgstr "" diff --git a/luci-app-adguardhome/po/pt_BR/adguardhome.po b/luci-app-adguardhome/po/pt_BR/adguardhome.po new file mode 100644 index 000000000..8f1e416a7 --- /dev/null +++ b/luci-app-adguardhome/po/pt_BR/adguardhome.po @@ -0,0 +1,168 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: pt_BR\n" +"Content-Transfer-Encoding: 8bit\n" +"Last-Translator: Pavel Borecki \n" +"Language-Team: Portuguese (Brazil) \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"PO-Revision-Date: 2026-09-29 13:09+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:244 +msgid "" +"A soft memory cap for the Go runtime, allowing the garbage collector to run " +"more frequently as usage approaches the limit to prevent Out-of-Memory (OOM) " +"kills." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:113 +#: applications/luci-app-adguardhome/root/usr/share/luci/menu.d/luci-app-adguardhome.json:3 +msgid "AdGuard Home" +msgstr "AdGuard Home" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:137 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:199 +msgid "Advanced Settings" +msgstr "Configurações avançadas" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:146 +msgid "Configuration file" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:89 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:147 +msgid "" +"Configuration file must be stored in its own directory, and not in '/etc'." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:159 +msgid "Directory where filters, logs, and statistics are stored." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:132 +msgid "File System Access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:133 +msgid "" +"Files and directories that AdGuard Home should have read-only or read-write " +"access to." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:129 +msgid "General Settings" +msgstr "Configurações gerais" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:138 +msgid "" +"Go environment variables that tune garbage collector and memory management." +msgstr "" + +#: applications/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json:3 +msgid "Grant permissions for the AdGuard Home LuCI app" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:181 +msgid "Group the service runs under." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:149 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:161 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:171 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:181 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:217 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:232 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:247 +msgid "If empty, defaults to" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:139 +msgid "Modify at your own risk." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:24 +msgid "Not running" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:148 +msgid "Parent directory will be owned by the service user." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:83 +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:99 +msgid "Path must be absolute." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:86 +msgid "Path must not end with a slash." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:207 +msgid "Read-only access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:208 +msgid "Read-write access" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:23 +msgid "Running" +msgstr "Em execução" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:122 +msgid "Service Status" +msgstr "Condição do Serviço" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:180 +msgid "Service group" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:170 +msgid "Service user" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:230 +msgid "" +"The maximum number of operating system threads that can execute user-level " +"Go code simultaneously." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:215 +msgid "" +"Tunes the garbage collector's aggressiveness by setting the percentage of " +"heap growth allowed before the next collection cycle triggers." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:171 +msgid "User the service runs under." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:191 +msgid "Verbose logging" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:119 +msgid "Version" +msgstr "Versão" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:160 +msgid "Will be owned by the service user." +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:158 +msgid "Working directory" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:247 +msgid "unset" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:217 +msgid "unset and 100" +msgstr "" + +#: applications/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js:232 +msgid "unset and matching the number of CPUs" +msgstr "" diff --git a/luci-app-fwlive/Makefile b/luci-app-fwlive/Makefile index 03e762c37..d3969ef0b 100644 --- a/luci-app-fwlive/Makefile +++ b/luci-app-fwlive/Makefile @@ -12,7 +12,7 @@ LUCI_DEPENDS:=+luci-base +logd +jsonfilter +coreutils-timeout LUCI_PKGARCH:=all PKG_VERSION:=0.1.47 -PKG_RELEASE:=50 +PKG_RELEASE:=51 # Reproducible build: honor SOURCE_DATE_EPOCH from the build environment (set by docker-sdk.sh / CI). ifdef SOURCE_DATE_EPOCH diff --git a/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js b/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js index 0aa30600b..19c89a4ef 100644 --- a/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js +++ b/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js @@ -886,6 +886,8 @@ return view.extend({ return _('No WAN zone found; cannot toggle logging without one.'); if (res && res.error === 'lock_failed') return _('Could not acquire the logging lock.'); + if (res && res.error === 'rollback_tracking_failed') + return _('Could not track the logging change safely; logging was not changed.'); if (res && res.error === 'baseline_snapshot_failed') return _('Could not snapshot the current logging state.'); if (res && res.error === 'firewall_reload_failed') @@ -927,6 +929,8 @@ return view.extend({ return _('No WAN zone found; cannot toggle logging without one.'); if (res && res.error === 'lock_failed') return _('Could not acquire the logging lock.'); + if (res && res.error === 'rollback_tracking_failed') + return _('Could not track the logging change safely; logging was not changed.'); if (res && res.error === 'firewall_reload_failed') return _('The firewall did not reload; saved and live logging may differ.'); if (res && res.error === 'uci_set_failed') diff --git a/luci-app-fwlive/po/de/luci-app-fwlive.po b/luci-app-fwlive/po/de/luci-app-fwlive.po index 3b0d28aa2..c8a4aacea 100644 --- a/luci-app-fwlive/po/de/luci-app-fwlive.po +++ b/luci-app-fwlive/po/de/luci-app-fwlive.po @@ -12,16 +12,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1639 msgid "%d matching · %d/%d stored" msgstr "%d Treffer · %d/%d gespeichert" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1429 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1433 msgid "%s · requested up to %d raw lines · %d firewall messages returned" msgstr "" "%s · bis zu %d Rohzeilen angefordert · %d Firewall-Meldungen zurückgegeben" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1419 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1423 msgid "" "%s · requested up to %d raw lines · server limited fetch to %d · %d firewall " "messages returned" @@ -29,11 +29,11 @@ msgstr "" "%s · bis zu %d Rohzeilen angefordert · Server begrenzte Abruf auf %d · %d " "Firewall-Meldungen zurückgegeben" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:502 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:543 msgid "%s: %s" msgstr "%s: %s" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1641 msgid "0 matching · %d/%d stored" msgstr "0 Treffer · %d/%d gespeichert" @@ -41,17 +41,17 @@ msgstr "0 Treffer · %d/%d gespeichert" msgid "Accessible (teal/orange)" msgstr "Barrierefrei (teal/orange)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:362 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:403 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:37 msgid "Action" msgstr "Aktion" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:945 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:949 msgid "Administrator access is required to disable logging." msgstr "" "Zum Deaktivieren der Protokollierung sind Administratorrechte erforderlich." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:914 msgid "Administrator access is required to enable logging." msgstr "" "Zum Aktivieren der Protokollierung sind Administratorrechte erforderlich." @@ -60,19 +60,19 @@ msgstr "" msgid "Allow/deny rules, LAN logging, or anything else." msgstr "Allow/Deny-Regeln, LAN-Protokollierung oder irgendetwas anderes." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1829 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1833 msgid "Also seen" msgstr "Weitere" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:883 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:924 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:926 msgid "Another change is staged for the firewall; apply or revert it first." msgstr "" "Eine andere Änderung an der Firewall ist vorgemerkt; zuerst anwenden oder " "verwerfen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:901 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:940 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 msgid "" "Another change overwrote WAN logging after it was saved; check the current " "state." @@ -80,16 +80,16 @@ msgstr "" "Eine andere Änderung hat die WAN-Protokollierung nach dem Speichern " "überschrieben; prüfen Sie den aktuellen Zustand." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2638 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 msgid "Any action" msgstr "Beliebige Aktion" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1822 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1826 msgid "Any protocol" msgstr "Beliebiges Protokoll" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1470 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1474 msgid "Auto" msgstr "Auto" @@ -111,7 +111,7 @@ msgstr "Änderungen:" msgid "Classic (green/red)" msgstr "Klassisch (grün/rot)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2369 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2373 msgid "Classic uses green/red; Accessible uses teal/orange" msgstr "Klassisch verwendet grün/rot; Barrierefrei verwendet teal/orange" @@ -119,7 +119,7 @@ msgstr "Klassisch verwendet grün/rot; Barrierefrei verwendet teal/orange" msgid "Clear all" msgstr "Alle löschen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2710 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2714 msgid "" "Click a cell to filter · ≠ on a chip to exclude · Ctrl+click a rule for " "firewall settings · in Simple view, click a row for the full message" @@ -128,7 +128,7 @@ msgstr "" "auf eine Regel für Firewall-Einstellungen · in der Einfachen Ansicht Zeile " "anklicken für die vollständige Meldung" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2441 msgid "" "Click a row (Time or other non-link cells) to see the full log line (Simple " "view)." @@ -140,7 +140,7 @@ msgstr "" msgid "Click a row for the full message" msgstr "Zeile anklicken für die vollständige Meldung" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2442 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2446 msgid "" "Click an IP, action, or protocol to filter; use the Protocol menu (or ≠ on a " "chip) to exclude." @@ -148,29 +148,29 @@ msgstr "" "Klicken Sie auf eine IP, Aktion oder ein Protokoll, um zu filtern; nutzen " "Sie das Protokoll-Menü (oder ≠ auf einem Chip) zum Ausschließen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1823 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 msgid "Common" msgstr "Häufig" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1654 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1658 msgid "Connection lost — retrying…" msgstr "Verbindung verloren — neuer Versuch…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:888 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 msgid "Could not acquire the logging lock." msgstr "Die Protokollierungssperre konnte nicht erworben werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:939 msgid "Could not clear the WAN zone log option." msgstr "Die WAN-Zonen-Log-Option konnte nicht gelöscht werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:942 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:946 msgid "Could not disable logging." msgstr "Protokollierung konnte nicht deaktiviert werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:905 msgid "Could not enable logging." msgstr "Protokollierung konnte nicht aktiviert werden." @@ -184,21 +184,26 @@ msgstr "" "Protokollstatus konnte nicht aktualisiert werden; zeige den zuletzt " "bekannten Zustand." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:900 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:941 msgid "Could not save the firewall configuration." msgstr "Die Firewall-Konfiguration konnte nicht gespeichert werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 msgid "Could not snapshot the current logging state." msgstr "Der aktuelle Protokollierungszustand konnte nicht gesichert werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:933 +msgid "Could not track the logging change safely; logging was not changed." +msgstr "Die Änderung der Protokollierung konnte nicht sicher nachverfolgt werden; die Protokollierung wurde nicht geändert." + +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 msgid "Could not write the WAN zone log option." msgstr "Die WAN-Zonen-Log-Option konnte nicht geschrieben werden." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2665 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2669 msgid "Custom protocol (prefix ! to exclude). Overrides the menu when set." msgstr "" "Eigenes Protokoll (! zum Ausschließen). Überschreibt das Menü, wenn gesetzt." @@ -207,34 +212,34 @@ msgstr "" msgid "DPort" msgstr "Ziel-Port" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 msgid "Degraded — sampling" msgstr "Eingeschränkt — Stichproben" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1445 msgid "Degraded — sampling (slow poll RTT; cadence reduced)." msgstr "" "Eingeschränkt — Stichproben (langsame Poll-Roundtrip-Zeit; Frequenz " "reduziert)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:366 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:407 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:45 msgid "Destination" msgstr "Ziel" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2695 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2699 msgid "Destination IP contains (! to exclude)" msgstr "Ziel-IP enthält (! zum Ausschließen)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:368 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:409 msgid "Destination port" msgstr "Ziel-Port" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2700 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2704 msgid "Destination port (! to exclude)" msgstr "Ziel-Port (! zum Ausschließen)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2553 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2557 msgid "Detail" msgstr "Detail" @@ -246,15 +251,15 @@ msgstr "Richtung" msgid "Disabling…" msgstr "Wird deaktiviert…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1268 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 msgid "Display limited to %d rows on this device" msgstr "Anzeige auf %d Zeilen auf diesem Gerät begrenzt" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2310 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2314 msgid "Display options" msgstr "Anzeigeoptionen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 msgid "Display options on the bar set Limit, row tint, palette, and hostnames." msgstr "" "Anzeigeoptionen in der Leiste setzen Limit, Zeilenfärbung, Palette und " @@ -282,7 +287,7 @@ msgstr "" msgid "Enable logging" msgstr "Protokollierung aktivieren" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2398 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 msgid "" "Enable logging turns on WAN zone drop/reject logging only (same as Network → " "Firewall). It does not add rules or log normal LAN browsing." @@ -296,7 +301,7 @@ msgstr "" msgid "Enabling…" msgstr "Wird aktiviert…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1836 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 msgid "Exclude" msgstr "Ausschließen" @@ -304,11 +309,11 @@ msgstr "Ausschließen" msgid "Exclude instead" msgstr "Stattdessen ausschließen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2324 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2328 msgid "Fetch budget" msgstr "Abrufbudget" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2410 msgid "" "Fetch budget controls raw log lines per poll. Auto derives from Limit; " "Manual selects a bounded maximum." @@ -328,7 +333,7 @@ msgstr "" "Logs nach Regel filtern (Hinweis: %s). Strg+Klick öffnet die Firewall-" "Einstellungen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2480 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2484 #: openwrt-feed/luci-app-fwlive/root/usr/share/luci/menu.d/luci-app-fwlive.json:3 msgid "Firewall Live View" msgstr "Firewall-Live-Ansicht" @@ -341,7 +346,7 @@ msgstr "Flags" msgid "Flow" msgstr "Fluss" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2416 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2420 msgid "" "For a responsive table on a weak device, keep Limit at 250 rows or below. " "The weak-device cap affects rendered rows; the buffer can still retain more." @@ -358,15 +363,15 @@ msgstr "Weitergeleitet" msgid "Grant access to firewall live log view" msgstr "Zugriff auf die Live-Ansicht der Firewall-Protokolle gewähren" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2389 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 msgid "Help" msgstr "Hilfe" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 msgid "Hide rows" msgstr "Zeilen ausblenden" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1603 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1607 msgid "" "High event rate — table refresh is throttled to protect the browser. The " "buffer still updates; refresh will resume automatically." @@ -375,11 +380,11 @@ msgstr "" "Browser zu schonen. Der Puffer wird weiter aktualisiert; die Anzeige wird " "automatisch fortgesetzt." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1452 msgid "Hostname resolve paused while the router is under load." msgstr "Hostnamenauflösung pausiert, solange der Router ausgelastet ist." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1831 msgid "ICMPv6" msgstr "ICMPv6" @@ -387,7 +392,7 @@ msgstr "ICMPv6" msgid "IN" msgstr "EINGANG" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2453 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2457 msgid "" "If Row tint looks missing, the active LuCI theme may omit success/error or " "info/warn CSS variables; fwlive falls back to local colors (air-gapped, no " @@ -421,16 +426,16 @@ msgstr "" "Installieren Sie kmod-nf-log und kmod-nf-log6 mit dem Befehl für Ihre " "OpenWrt-Version und laden Sie dann die Firewall neu." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1653 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1657 msgid "Installation is incomplete. Reinstall luci-app-fwlive." msgstr "Installation unvollständig. Installieren Sie luci-app-fwlive neu." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:404 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:39 msgid "Interface" msgstr "Schnittstelle" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2680 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2684 msgid "Interface (prefix ! to exclude)" msgstr "Schnittstelle (! voranstellen zum Ausschließen)" @@ -447,7 +452,7 @@ msgstr "Kernel-Logmodule fehlen" msgid "Len" msgstr "Länge" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2313 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2317 msgid "Limit" msgstr "Limit" @@ -461,16 +466,16 @@ msgstr "" msgid "Logging is off on this router" msgstr "Protokollierung ist auf diesem Router deaktiviert" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1471 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1475 msgid "Manual" msgstr "Manuell" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2342 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2346 msgid "Manual still uses server protection and poll cadence" msgstr "Manuell nutzt weiterhin Serverschutz und Abfrageintervall" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2411 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2415 msgid "" "Manual still uses server protection and poll cadence; it changes the fetch " "budget, not the polling interval." @@ -482,18 +487,18 @@ msgstr "" msgid "Manual test (System → Terminal):" msgstr "Manueller Test (System → Terminal):" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2336 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2340 msgid "Maximum raw lines" msgstr "Maximale Rohzeilen" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:51 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:344 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2565 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2572 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2569 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2576 msgid "Message" msgstr "Nachricht" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2675 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2679 msgid "More filters" msgstr "Weitere Filter" @@ -513,7 +518,7 @@ msgid "No WAN zone found" msgstr "Keine WAN-Zone gefunden" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:886 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:927 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 msgid "No WAN zone found; cannot toggle logging without one." msgstr "" "Keine WAN-Zone gefunden; Protokollierung kann ohne eine solche nicht " @@ -531,7 +536,7 @@ msgstr "Nichts ändert sich, bis Sie auf Aktivieren klicken." msgid "OUT" msgstr "AUSGANG" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2595 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2599 msgid "One line" msgstr "Einzeilig" @@ -561,29 +566,29 @@ msgstr "" msgid "Outbound" msgstr "Ausgehend" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2367 msgid "Palette" msgstr "Palette" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2519 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2523 msgid "Pause" msgstr "Pause" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 msgid "Paused" msgstr "Pausiert" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:364 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:405 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:43 msgid "Proto" msgstr "Protokoll" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2656 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2660 msgid "Protocol — common values" msgstr "Protokoll — häufige Werte" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 msgid "Quick search" msgstr "Schnellsuche" @@ -591,15 +596,15 @@ msgstr "Schnellsuche" msgid "Remove filter" msgstr "Filter entfernen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 msgid "Resume" msgstr "Fortsetzen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2353 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2357 msgid "Row tint" msgstr "Zeileneinfärbung" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2447 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2451 msgid "" "Row tint shows pass/deny row backgrounds when checked. Choose Classic (green/" "red, default) or Accessible (teal/orange). Action text stays colored either " @@ -609,7 +614,7 @@ msgstr "" "Klassisch (grün/rot, Standard) oder Barrierefrei (teal/orange). Aktionstext " "bleibt in beiden Fällen farbig." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2503 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2507 msgid "" "Row tint used a local color fallback because the active LuCI theme did not " "apply pass/deny backgrounds." @@ -637,81 +642,81 @@ msgstr "Regel-Labels nicht verfügbar — temporäre Datei fehlgeschlagen" msgid "SPort" msgstr "Quell-Port" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:361 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:402 msgid "Search" msgstr "Suche" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1439 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1443 msgid "Server adaptive protection is disabled." msgstr "Adaptiver Serverschutz ist deaktiviert." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 msgid "Server protection state is unknown." msgstr "Serverschutz-Status unbekannt." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1444 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 msgid "Server shedding — at most %d log lines per poll." msgstr "Server reduziert — höchstens %d Protokollzeilen pro Abfrage." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1446 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1450 msgid "Server truncated this poll (adaptive cap)." msgstr "Server hat diese Abfrage gekürzt (adaptives Limit)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2380 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2384 msgid "Show hostnames" msgstr "Hostnamen anzeigen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2351 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2355 msgid "Show pass/deny row background colors" msgstr "Pass/Deny-Zeilenhintergrundfarben anzeigen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2618 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2622 msgid "Show rows" msgstr "Zeilen anzeigen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1505 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 msgid "Showing a compact summary of the top of the shown sample." msgstr "Eine kompakte Zusammenfassung des Anfangs der angezeigten Stichprobe." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2542 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2546 msgid "Simple" msgstr "Einfach" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:365 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:406 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:44 msgid "Source" msgstr "Quelle" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2685 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2689 msgid "Source IP contains (! to exclude)" msgstr "Quell-IP enthält (! zum Ausschließen)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:367 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:408 msgid "Source port" msgstr "Quell-Port" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2690 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2694 msgid "Source port (! to exclude)" msgstr "Quell-Port (! zum Ausschließen)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1507 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 msgid "Summary data is unavailable; show rows to inspect the sample." msgstr "" "Zusammenfassungsdaten nicht verfügbar; Zeilen anzeigen, um die Stichprobe zu " "prüfen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2609 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2613 msgid "Summary mode" msgstr "Zusammenfassungsmodus" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1513 msgid "Summary was bounded before all categories could be included." msgstr "" "Die Zusammenfassung wurde begrenzt, bevor alle Kategorien aufgenommen werden " "konnten." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2421 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2425 msgid "" "Switching tabs pauses polling; returning performs one catch-up poll. " "Hostnames are off by default because lookups add work." @@ -720,14 +725,14 @@ msgstr "" "eine einmalige Aufholabfrage. Hostnamen sind standardmäßig deaktiviert, da " "Auflösungen zusätzliche Arbeit verursachen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 msgid "The firewall did not reload; saved and live logging may differ." msgstr "" "Die Firewall wurde nicht neu geladen; gespeicherte und aktive " "Protokollierung können voneinander abweichen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2431 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2435 msgid "" "The rate shown for WAN logging is the firewall zone log_limit. OpenWrt " "defaults to 10/minute when no explicit limit is configured; fwlive does not " @@ -737,7 +742,7 @@ msgstr "" "Standard ist 10/Minute ohne explizites Limit; fwlive setzt diese Grenze " "nicht." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2426 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2430 msgid "" "The router log ring may evict older events before fwlive reads them. fwlive " "cannot recover evicted entries or change forwarding behavior." @@ -746,7 +751,7 @@ msgstr "" "fwlive sie liest. fwlive kann verdrängte Einträge nicht wiederherstellen und " "ändert das Weiterleitungsverhalten nicht." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2397 msgid "" "The table updates automatically when your firewall logs traffic. Use Pause " "if it moves too fast." @@ -754,7 +759,7 @@ msgstr "" "Die Tabelle aktualisiert sich automatisch, wenn Ihre Firewall Verkehr " "protokolliert. Pause nutzen, wenn es zu schnell wird." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2506 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2510 msgid "Theme tint fallback" msgstr "Theme-Farb-Fallback" @@ -773,15 +778,15 @@ msgstr "" msgid "Time" msgstr "Zeit" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1514 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1518 msgid "Top drops" msgstr "Häufigste Drops" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1517 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1521 msgid "Top rules" msgstr "Häufigste Regeln" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1515 msgid "Top talkers" msgstr "Häufigste Absender" @@ -811,17 +816,17 @@ msgstr "" msgid "Undo:" msgstr "Rückgängig:" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2450 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2454 msgid "Use Detail for all columns (flags, length, raw message)." msgstr "" "Verwenden Sie „Detail“ für alle Spalten (Flags, Länge, rohe Nachricht)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2524 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2530 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2528 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2534 msgid "View" msgstr "Ansicht" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:948 msgid "WAN drop/reject logging is off." msgstr "WAN-Drop/Reject-Protokollierung ist aus." @@ -833,7 +838,7 @@ msgstr "" "WAN-Drop/Reject-Protokollierung ist an. Blockierter eingehender WAN-Verkehr " "erscheint hier. Normales LAN-Surfen nicht." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:908 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 msgid "" "WAN drop/reject logging is on. Blocked inbound traffic should appear here as " "it happens — not normal LAN browsing." @@ -841,7 +846,7 @@ msgstr "" "WAN-Drop/Reject-Protokollierung ist an. Blockierter eingehender Verkehr " "sollte hier in Echtzeit erscheinen — nicht normales LAN-Surfen." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 msgid "WAN logging is already enabled." msgstr "WAN-Protokollierung ist bereits aktiviert." @@ -870,25 +875,25 @@ msgstr "WAN-Protokollierung nicht verfügbar: keine WAN-Zone" msgid "Waiting for firewall events" msgstr "Warte auf Firewall-Ereignisse" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2494 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2498 msgid "Watching" msgstr "Beobachtet" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2584 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2588 msgid "Wrap" msgstr "Umbrechen" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:71 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2640 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 msgid "block" msgstr "blockiert" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1259 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 msgid "buffer filling" msgstr "Puffer füllt sich" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1267 msgid "buffer full" msgstr "Puffer voll" @@ -905,7 +910,7 @@ msgid "does not contain" msgstr "enthält nicht" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:72 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2641 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 msgid "drop" msgstr "verworfen" @@ -913,16 +918,16 @@ msgstr "verworfen" msgid "is" msgstr "ist" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1258 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1262 msgid "loading buffer" msgstr "Lade Puffer" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1633 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 msgid "loading…" msgstr "lädt…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1487 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1496 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1491 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1500 msgid "none" msgstr "keine" @@ -930,94 +935,94 @@ msgstr "keine" msgid "not" msgstr "nicht" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1848 msgid "not AH" msgstr "nicht AH" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1847 msgid "not ESP" msgstr "nicht ESP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1846 msgid "not GRE" msgstr "nicht GRE" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1839 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 msgid "not ICMP" msgstr "nicht ICMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 msgid "not ICMPv6" msgstr "nicht ICMPv6" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 msgid "not IGMP" msgstr "nicht IGMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1849 msgid "not SCTP" msgstr "nicht SCTP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1837 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 msgid "not TCP" msgstr "nicht TCP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1838 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 msgid "not UDP" msgstr "nicht UDP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2650 msgid "not block" msgstr "nicht blockieren" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2649 msgid "not drop" msgstr "nicht verwerfen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 msgid "not pass" msgstr "nicht erlauben" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2651 msgid "not reject" msgstr "nicht zurückweisen" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2652 msgid "not unknown" msgstr "nicht unbekannt" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2663 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2667 msgid "or type…" msgstr "oder tippen…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:70 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 msgid "pass" msgstr "erlaubt" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:73 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 msgid "reject" msgstr "abgelehnt" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1265 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1269 msgid "render paused (high rate)" msgstr "Rendering pausiert (hohe Rate)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1274 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1278 msgid "resolve paused (load)" msgstr "Auflösung pausiert (Last)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1280 msgid "scroll frozen — scroll to top to follow live" msgstr "Scrollen eingefroren — nach oben scrollen für Live-Ansicht" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1273 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1277 msgid "truncated" msgstr "gekürzt" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:62 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 msgid "unknown" msgstr "unbekannt" diff --git a/luci-app-fwlive/po/ru/luci-app-fwlive.po b/luci-app-fwlive/po/ru/luci-app-fwlive.po index e97007f8d..176f6de74 100644 --- a/luci-app-fwlive/po/ru/luci-app-fwlive.po +++ b/luci-app-fwlive/po/ru/luci-app-fwlive.po @@ -13,15 +13,15 @@ msgstr "" "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" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1639 msgid "%d matching · %d/%d stored" msgstr "%d совпад. · сохранено %d/%d" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1429 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1433 msgid "%s · requested up to %d raw lines · %d firewall messages returned" msgstr "%s · запрошено до %d сырых строк · возвращено %d сообщений firewall" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1419 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1423 msgid "" "%s · requested up to %d raw lines · server limited fetch to %d · %d firewall " "messages returned" @@ -29,11 +29,11 @@ msgstr "" "%s · запрошено до %d сырых строк · сервер ограничил выборку до %d · " "возвращено %d сообщений firewall" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:502 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:543 msgid "%s: %s" msgstr "%s: %s" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1641 msgid "0 matching · %d/%d stored" msgstr "0 совпад. · сохранено %d/%d" @@ -41,16 +41,16 @@ msgstr "0 совпад. · сохранено %d/%d" msgid "Accessible (teal/orange)" msgstr "Доступный (бирюзовый/оранжевый)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:362 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:403 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:37 msgid "Action" msgstr "Действие" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:945 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:949 msgid "Administrator access is required to disable logging." msgstr "Для отключения журналирования требуются права администратора." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:914 msgid "Administrator access is required to enable logging." msgstr "Для включения журналирования требуются права администратора." @@ -58,19 +58,19 @@ msgstr "Для включения журналирования требуютс msgid "Allow/deny rules, LAN logging, or anything else." msgstr "Правила allow/deny, журналирование LAN и любые другие настройки." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1829 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1833 msgid "Also seen" msgstr "Также встречаются" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:883 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:924 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:926 msgid "Another change is staged for the firewall; apply or revert it first." msgstr "" "В брандмауэре уже есть другое незафиксированное изменение; сначала примените " "или отмените его." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:901 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:940 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 msgid "" "Another change overwrote WAN logging after it was saved; check the current " "state." @@ -78,16 +78,16 @@ msgstr "" "Другое изменение перезаписало журналирование WAN после сохранения; проверьте " "текущее состояние." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2638 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 msgid "Any action" msgstr "Любое действие" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1822 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1826 msgid "Any protocol" msgstr "Любой протокол" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1470 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1474 msgid "Auto" msgstr "Авто" @@ -108,7 +108,7 @@ msgstr "Изменения:" msgid "Classic (green/red)" msgstr "Классический (зелёный/красный)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2369 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2373 msgid "Classic uses green/red; Accessible uses teal/orange" msgstr "Классический — зелёный/красный; доступный — бирюзовый/оранжевый" @@ -116,7 +116,7 @@ msgstr "Классический — зелёный/красный; доступ msgid "Clear all" msgstr "Очистить всё" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2710 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2714 msgid "" "Click a cell to filter · ≠ on a chip to exclude · Ctrl+click a rule for " "firewall settings · in Simple view, click a row for the full message" @@ -125,7 +125,7 @@ msgstr "" "правилу для настроек МЭ · в Простом виде щёлкните строку для полного " "сообщения" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2441 msgid "" "Click a row (Time or other non-link cells) to see the full log line (Simple " "view)." @@ -137,7 +137,7 @@ msgstr "" msgid "Click a row for the full message" msgstr "Щёлкните строку для полного сообщения" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2442 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2446 msgid "" "Click an IP, action, or protocol to filter; use the Protocol menu (or ≠ on a " "chip) to exclude." @@ -145,29 +145,29 @@ msgstr "" "Щёлкните по IP, действию или протоколу для фильтрации; для исключения " "используйте меню «Протокол» (или ≠ на чипе)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1823 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 msgid "Common" msgstr "Частые" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1654 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1658 msgid "Connection lost — retrying…" msgstr "Соединение потеряно — повторная попытка…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:888 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 msgid "Could not acquire the logging lock." msgstr "Не удалось получить блокировку журналирования." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:939 msgid "Could not clear the WAN zone log option." msgstr "Не удалось очистить параметр журнала зоны WAN." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:942 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:946 msgid "Could not disable logging." msgstr "Не удалось отключить журналирование." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:905 msgid "Could not enable logging." msgstr "Не удалось включить журналирование." @@ -181,21 +181,26 @@ msgstr "" "Не удалось обновить состояние журналирования; показан последний известный " "статус." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:900 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:941 msgid "Could not save the firewall configuration." msgstr "Не удалось сохранить конфигурацию межсетевого экрана." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 msgid "Could not snapshot the current logging state." msgstr "Не удалось сохранить снимок текущего состояния журналирования." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:933 +msgid "Could not track the logging change safely; logging was not changed." +msgstr "Не удалось безопасно отследить изменение журналирования; журналирование не изменено." + +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 msgid "Could not write the WAN zone log option." msgstr "Не удалось записать параметр журнала зоны WAN." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2665 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2669 msgid "Custom protocol (prefix ! to exclude). Overrides the menu when set." msgstr "Свой протокол (! для исключения). Переопределяет меню, если задан." @@ -203,32 +208,32 @@ msgstr "Свой протокол (! для исключения). Переоп msgid "DPort" msgstr "Порт назн." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 msgid "Degraded — sampling" msgstr "Упрощённый режим — выборка" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1445 msgid "Degraded — sampling (slow poll RTT; cadence reduced)." msgstr "Упрощённый режим — выборка (медленный RTT опроса; интервал увеличен)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:366 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:407 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:45 msgid "Destination" msgstr "Назначение" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2695 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2699 msgid "Destination IP contains (! to exclude)" msgstr "IP назначения содержит (! для исключения)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:368 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:409 msgid "Destination port" msgstr "Порт назначения" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2700 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2704 msgid "Destination port (! to exclude)" msgstr "Порт назначения (! для исключения)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2553 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2557 msgid "Detail" msgstr "Подробно" @@ -240,15 +245,15 @@ msgstr "Напр." msgid "Disabling…" msgstr "Отключение…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1268 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 msgid "Display limited to %d rows on this device" msgstr "На этом устройстве отображение ограничено %d строками" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2310 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2314 msgid "Display options" msgstr "Параметры отображения" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 msgid "Display options on the bar set Limit, row tint, palette, and hostnames." msgstr "" "Параметры отображения на панели задают лимит, окраску строк, палитру и имена " @@ -276,7 +281,7 @@ msgstr "" msgid "Enable logging" msgstr "Включить журнал" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2398 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 msgid "" "Enable logging turns on WAN zone drop/reject logging only (same as Network → " "Firewall). It does not add rules or log normal LAN browsing." @@ -290,7 +295,7 @@ msgstr "" msgid "Enabling…" msgstr "Включение…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1836 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 msgid "Exclude" msgstr "Исключить" @@ -298,11 +303,11 @@ msgstr "Исключить" msgid "Exclude instead" msgstr "Исключить вместо этого" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2324 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2328 msgid "Fetch budget" msgstr "Бюджет выборки" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2410 msgid "" "Fetch budget controls raw log lines per poll. Auto derives from Limit; " "Manual selects a bounded maximum." @@ -322,7 +327,7 @@ msgstr "" "Фильтр журналов по правилу (подсказка: %s). Ctrl+клик открывает настройки " "файрвола." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2480 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2484 #: openwrt-feed/luci-app-fwlive/root/usr/share/luci/menu.d/luci-app-fwlive.json:3 msgid "Firewall Live View" msgstr "Просмотр файрвола в реальном времени" @@ -335,7 +340,7 @@ msgstr "Флаги" msgid "Flow" msgstr "Поток" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2416 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2420 msgid "" "For a responsive table on a weak device, keep Limit at 250 rows or below. " "The weak-device cap affects rendered rows; the buffer can still retain more." @@ -352,15 +357,15 @@ msgstr "Транзитный" msgid "Grant access to firewall live log view" msgstr "Предоставить доступ к живому просмотру журнала межсетевого экрана" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2389 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 msgid "Help" msgstr "Справка" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 msgid "Hide rows" msgstr "Скрыть строки" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1603 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1607 msgid "" "High event rate — table refresh is throttled to protect the browser. The " "buffer still updates; refresh will resume automatically." @@ -368,11 +373,11 @@ msgstr "" "Высокая частота событий — обновление таблицы ограничено для защиты браузера. " "Буфер продолжает обновляться; отображение возобновится автоматически." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1452 msgid "Hostname resolve paused while the router is under load." msgstr "Разрешение имён приостановлено из-за нагрузки на маршрутизатор." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1831 msgid "ICMPv6" msgstr "ICMPv6" @@ -380,7 +385,7 @@ msgstr "ICMPv6" msgid "IN" msgstr "ВХОД" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2453 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2457 msgid "" "If Row tint looks missing, the active LuCI theme may omit success/error or " "info/warn CSS variables; fwlive falls back to local colors (air-gapped, no " @@ -414,16 +419,16 @@ msgstr "" "Установите kmod-nf-log и kmod-nf-log6 командой для вашей версии OpenWrt, " "затем перезагрузите файрвол." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1653 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1657 msgid "Installation is incomplete. Reinstall luci-app-fwlive." msgstr "Установка не завершена. Переустановите luci-app-fwlive." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:404 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:39 msgid "Interface" msgstr "Интерфейс" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2680 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2684 msgid "Interface (prefix ! to exclude)" msgstr "Интерфейс (! в начале для исключения)" @@ -440,7 +445,7 @@ msgstr "Отсутствуют модули журналирования ядр msgid "Len" msgstr "Длина" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2313 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2317 msgid "Limit" msgstr "Лимит" @@ -454,16 +459,16 @@ msgstr "" msgid "Logging is off on this router" msgstr "Журналирование на этом роутере отключено" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1471 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1475 msgid "Manual" msgstr "Вручную" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2342 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2346 msgid "Manual still uses server protection and poll cadence" msgstr "«Вручную» по-прежнему использует защиту сервера и частоту опроса" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2411 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2415 msgid "" "Manual still uses server protection and poll cadence; it changes the fetch " "budget, not the polling interval." @@ -475,18 +480,18 @@ msgstr "" msgid "Manual test (System → Terminal):" msgstr "Ручной тест (Система → Терминал):" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2336 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2340 msgid "Maximum raw lines" msgstr "Максимум сырых строк" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:51 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:344 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2565 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2572 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2569 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2576 msgid "Message" msgstr "Сообщение" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2675 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2679 msgid "More filters" msgstr "Больше фильтров" @@ -506,7 +511,7 @@ msgid "No WAN zone found" msgstr "WAN-зона не найдена" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:886 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:927 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 msgid "No WAN zone found; cannot toggle logging without one." msgstr "WAN-зона не найдена; без неё нельзя переключить журналирование." @@ -522,7 +527,7 @@ msgstr "Ничего не изменится, пока вы не нажмёте msgid "OUT" msgstr "ВЫХОД" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2595 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2599 msgid "One line" msgstr "Одна строка" @@ -552,29 +557,29 @@ msgstr "" msgid "Outbound" msgstr "Исходящий" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2367 msgid "Palette" msgstr "Палитра" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2519 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2523 msgid "Pause" msgstr "Пауза" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 msgid "Paused" msgstr "Пауза" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:364 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:405 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:43 msgid "Proto" msgstr "Протокол" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2656 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2660 msgid "Protocol — common values" msgstr "Протокол — частые значения" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 msgid "Quick search" msgstr "Быстрый поиск" @@ -582,15 +587,15 @@ msgstr "Быстрый поиск" msgid "Remove filter" msgstr "Удалить фильтр" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 msgid "Resume" msgstr "Продолжить" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2353 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2357 msgid "Row tint" msgstr "Цвет строк" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2447 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2451 msgid "" "Row tint shows pass/deny row backgrounds when checked. Choose Classic (green/" "red, default) or Accessible (teal/orange). Action text stays colored either " @@ -600,7 +605,7 @@ msgstr "" "классический (зелёный/красный, по умолчанию) или доступный (бирюзовый/" "оранжевый). Цвет текста действия сохраняется в любом случае." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2503 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2507 msgid "" "Row tint used a local color fallback because the active LuCI theme did not " "apply pass/deny backgrounds." @@ -628,77 +633,77 @@ msgstr "Метки правил недоступны — ошибка време msgid "SPort" msgstr "Порт ист." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:361 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:402 msgid "Search" msgstr "Поиск" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1439 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1443 msgid "Server adaptive protection is disabled." msgstr "Адаптивная защита сервера отключена." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 msgid "Server protection state is unknown." msgstr "Состояние защиты сервера неизвестно." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1444 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 msgid "Server shedding — at most %d log lines per poll." msgstr "Сервер ограничивает выдачу — не более %d строк журнала за опрос." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1446 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1450 msgid "Server truncated this poll (adaptive cap)." msgstr "Сервер сократил этот опрос (адаптивный предел)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2380 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2384 msgid "Show hostnames" msgstr "Показывать имена узлов" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2351 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2355 msgid "Show pass/deny row background colors" msgstr "Показывать цвета фона строк pass/deny" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2618 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2622 msgid "Show rows" msgstr "Показать строки" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1505 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 msgid "Showing a compact summary of the top of the shown sample." msgstr "Показана краткая сводка верхней части отображаемой выборки." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2542 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2546 msgid "Simple" msgstr "Простой" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:365 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:406 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:44 msgid "Source" msgstr "Источник" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2685 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2689 msgid "Source IP contains (! to exclude)" msgstr "IP источника содержит (! для исключения)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:367 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:408 msgid "Source port" msgstr "Порт источника" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2690 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2694 msgid "Source port (! to exclude)" msgstr "Порт источника (! для исключения)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1507 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 msgid "Summary data is unavailable; show rows to inspect the sample." msgstr "Данные сводки недоступны; покажите строки для проверки выборки." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2609 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2613 msgid "Summary mode" msgstr "Режим сводки" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1513 msgid "Summary was bounded before all categories could be included." msgstr "Сводка ограничена до включения всех категорий." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2421 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2425 msgid "" "Switching tabs pauses polling; returning performs one catch-up poll. " "Hostnames are off by default because lookups add work." @@ -707,14 +712,14 @@ msgstr "" "один догоняющий опрос. Имена хостов по умолчанию отключены, поскольку их " "разрешение создаёт дополнительную нагрузку." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 msgid "The firewall did not reload; saved and live logging may differ." msgstr "" "Брандмауэр не перезагрузился; сохранённые и активные настройки " "журналирования могут различаться." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2431 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2435 msgid "" "The rate shown for WAN logging is the firewall zone log_limit. OpenWrt " "defaults to 10/minute when no explicit limit is configured; fwlive does not " @@ -723,7 +728,7 @@ msgstr "" "Показанная частота WAN-журнала — log_limit зоны. По умолчанию OpenWrt: 10/" "мин без явного лимита; fwlive сам лимит не задаёт." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2426 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2430 msgid "" "The router log ring may evict older events before fwlive reads them. fwlive " "cannot recover evicted entries or change forwarding behavior." @@ -732,7 +737,7 @@ msgstr "" "fwlive их прочитает. fwlive не может восстановить вытесненные записи и не " "изменяет пересылку." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2397 msgid "" "The table updates automatically when your firewall logs traffic. Use Pause " "if it moves too fast." @@ -740,7 +745,7 @@ msgstr "" "Таблица обновляется автоматически, когда файрвол пишет в журнал. Используйте " "Паузу, если слишком быстро." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2506 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2510 msgid "Theme tint fallback" msgstr "Запасной цвет темы" @@ -759,15 +764,15 @@ msgstr "" msgid "Time" msgstr "Время" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1514 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1518 msgid "Top drops" msgstr "Частые сбросы" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1517 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1521 msgid "Top rules" msgstr "Частые правила" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1515 msgid "Top talkers" msgstr "Частые источники" @@ -796,17 +801,17 @@ msgstr "" msgid "Undo:" msgstr "Отмена:" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2450 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2454 msgid "Use Detail for all columns (flags, length, raw message)." msgstr "" "Используйте «Подробно» для всех столбцов (флаги, длина, исходное сообщение)." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2524 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2530 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2528 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2534 msgid "View" msgstr "Вид" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:948 msgid "WAN drop/reject logging is off." msgstr "Журналирование drop/reject для WAN отключено." @@ -818,7 +823,7 @@ msgstr "" "Журналирование drop/reject для WAN включено. Заблокированный входящий WAN-" "трафик будет отображаться здесь. Обычный LAN-трафик — нет." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:908 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 msgid "" "WAN drop/reject logging is on. Blocked inbound traffic should appear here as " "it happens — not normal LAN browsing." @@ -827,7 +832,7 @@ msgstr "" "должен появляться здесь по мере поступления — обычный LAN-трафик не " "отображается." -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 msgid "WAN logging is already enabled." msgstr "WAN-журналирование уже включено." @@ -856,25 +861,25 @@ msgstr "WAN-журналирование недоступно: нет зоны W msgid "Waiting for firewall events" msgstr "Ожидание событий межсетевого экрана" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2494 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2498 msgid "Watching" msgstr "Наблюдение" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2584 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2588 msgid "Wrap" msgstr "Перенос" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:71 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2640 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 msgid "block" msgstr "заблокирован" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1259 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 msgid "buffer filling" msgstr "буфер заполняется" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1267 msgid "buffer full" msgstr "буфер заполнен" @@ -891,7 +896,7 @@ msgid "does not contain" msgstr "не содержит" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:72 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2641 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 msgid "drop" msgstr "отброшен" @@ -899,16 +904,16 @@ msgstr "отброшен" msgid "is" msgstr "есть" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1258 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1262 msgid "loading buffer" msgstr "загрузка буфера" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1633 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 msgid "loading…" msgstr "загрузка…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1487 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1496 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1491 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1500 msgid "none" msgstr "нет" @@ -916,95 +921,95 @@ msgstr "нет" msgid "not" msgstr "не" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1848 msgid "not AH" msgstr "не AH" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1847 msgid "not ESP" msgstr "не ESP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1846 msgid "not GRE" msgstr "не GRE" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1839 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 msgid "not ICMP" msgstr "не ICMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 msgid "not ICMPv6" msgstr "не ICMPv6" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 msgid "not IGMP" msgstr "не IGMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1849 msgid "not SCTP" msgstr "не SCTP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1837 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 msgid "not TCP" msgstr "не TCP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1838 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 msgid "not UDP" msgstr "не UDP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2650 msgid "not block" msgstr "не блокировать" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2649 msgid "not drop" msgstr "не отбрасывать" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 msgid "not pass" msgstr "не пропускать" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2651 msgid "not reject" msgstr "не отклонять" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2652 msgid "not unknown" msgstr "не неизвестно" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2663 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2667 msgid "or type…" msgstr "или введите…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:70 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 msgid "pass" msgstr "разрешён" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:73 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 msgid "reject" msgstr "отклонён" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1265 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1269 msgid "render paused (high rate)" msgstr "рендеринг приостановлен (высокая частота)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1274 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1278 msgid "resolve paused (load)" msgstr "Разрешение приостановлено (нагрузка)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1280 msgid "scroll frozen — scroll to top to follow live" msgstr "" "прокрутка заморожена — прокрутите вверх, чтобы следить в реальном времени" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1273 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1277 msgid "truncated" msgstr "обрезано" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:62 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 msgid "unknown" msgstr "неизвестно" diff --git a/luci-app-fwlive/po/templates/luci-app-fwlive.pot b/luci-app-fwlive/po/templates/luci-app-fwlive.pot index 72321da45..1e7a51bdc 100644 --- a/luci-app-fwlive/po/templates/luci-app-fwlive.pot +++ b/luci-app-fwlive/po/templates/luci-app-fwlive.pot @@ -1,15 +1,15 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1639 msgid "%d matching · %d/%d stored" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1429 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1433 msgid "%s · requested up to %d raw lines · %d firewall messages returned" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1419 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1423 msgid "" "%s · requested up to %d raw lines · server limited fetch to %d · %d firewall " "messages returned" @@ -19,7 +19,7 @@ msgstr "" msgid "%s: %s" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1641 msgid "0 matching · %d/%d stored" msgstr "" @@ -32,11 +32,11 @@ msgstr "" msgid "Action" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:945 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:949 msgid "Administrator access is required to disable logging." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:914 msgid "Administrator access is required to enable logging." msgstr "" @@ -44,32 +44,32 @@ msgstr "" msgid "Allow/deny rules, LAN logging, or anything else." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1829 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1833 msgid "Also seen" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:883 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:924 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:926 msgid "Another change is staged for the firewall; apply or revert it first." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:901 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:940 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 msgid "" "Another change overwrote WAN logging after it was saved; check the current " "state." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2638 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 msgid "Any action" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1822 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1826 msgid "Any protocol" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1470 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1474 msgid "Auto" msgstr "" @@ -89,7 +89,7 @@ msgstr "" msgid "Classic (green/red)" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2369 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2373 msgid "Classic uses green/red; Accessible uses teal/orange" msgstr "" @@ -97,13 +97,13 @@ msgstr "" msgid "Clear all" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2710 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2714 msgid "" "Click a cell to filter · ≠ on a chip to exclude · Ctrl+click a rule for " "firewall settings · in Simple view, click a row for the full message" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2441 msgid "" "Click a row (Time or other non-link cells) to see the full log line (Simple " "view)." @@ -113,35 +113,35 @@ msgstr "" msgid "Click a row for the full message" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2442 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2446 msgid "" "Click an IP, action, or protocol to filter; use the Protocol menu (or ≠ on a " "chip) to exclude." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1823 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 msgid "Common" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1654 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1658 msgid "Connection lost — retrying…" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:888 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 msgid "Could not acquire the logging lock." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:939 msgid "Could not clear the WAN zone log option." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:942 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:946 msgid "Could not disable logging." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:905 msgid "Could not enable logging." msgstr "" @@ -153,21 +153,26 @@ msgstr "" msgid "Could not refresh logging status; showing the last known state." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:900 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:941 msgid "Could not save the firewall configuration." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 msgid "Could not snapshot the current logging state." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:933 +msgid "Could not track the logging change safely; logging was not changed." +msgstr "" + +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 msgid "Could not write the WAN zone log option." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2665 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2669 msgid "Custom protocol (prefix ! to exclude). Overrides the menu when set." msgstr "" @@ -175,11 +180,11 @@ msgstr "" msgid "DPort" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 msgid "Degraded — sampling" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1445 msgid "Degraded — sampling (slow poll RTT; cadence reduced)." msgstr "" @@ -188,7 +193,7 @@ msgstr "" msgid "Destination" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2695 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2699 msgid "Destination IP contains (! to exclude)" msgstr "" @@ -196,11 +201,11 @@ msgstr "" msgid "Destination port" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2700 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2704 msgid "Destination port (! to exclude)" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2553 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2557 msgid "Detail" msgstr "" @@ -212,15 +217,15 @@ msgstr "" msgid "Disabling…" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1268 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 msgid "Display limited to %d rows on this device" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2310 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2314 msgid "Display options" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 msgid "Display options on the bar set Limit, row tint, palette, and hostnames." msgstr "" @@ -244,7 +249,7 @@ msgstr "" msgid "Enable logging" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2398 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 msgid "" "Enable logging turns on WAN zone drop/reject logging only (same as Network → " "Firewall). It does not add rules or log normal LAN browsing." @@ -255,7 +260,7 @@ msgstr "" msgid "Enabling…" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1836 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 msgid "Exclude" msgstr "" @@ -263,11 +268,11 @@ msgstr "" msgid "Exclude instead" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2324 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2328 msgid "Fetch budget" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2410 msgid "" "Fetch budget controls raw log lines per poll. Auto derives from Limit; " "Manual selects a bounded maximum." @@ -283,7 +288,7 @@ msgstr "" msgid "Filter logs by rule (hint: %s). Ctrl+click to open firewall settings." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2480 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2484 #: openwrt-feed/luci-app-fwlive/root/usr/share/luci/menu.d/luci-app-fwlive.json:3 msgid "Firewall Live View" msgstr "" @@ -296,7 +301,7 @@ msgstr "" msgid "Flow" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2416 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2420 msgid "" "For a responsive table on a weak device, keep Limit at 250 rows or below. " "The weak-device cap affects rendered rows; the buffer can still retain more." @@ -310,25 +315,25 @@ msgstr "" msgid "Grant access to firewall live log view" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2389 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 msgid "Help" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 msgid "Hide rows" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1603 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1607 msgid "" "High event rate — table refresh is throttled to protect the browser. The " "buffer still updates; refresh will resume automatically." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1452 msgid "Hostname resolve paused while the router is under load." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1831 msgid "ICMPv6" msgstr "" @@ -336,7 +341,7 @@ msgstr "" msgid "IN" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2453 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2457 msgid "" "If Row tint looks missing, the active LuCI theme may omit success/error or " "info/warn CSS variables; fwlive falls back to local colors (air-gapped, no " @@ -363,7 +368,7 @@ msgid "" "release, then reload the firewall." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1653 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1657 msgid "Installation is incomplete. Reinstall luci-app-fwlive." msgstr "" @@ -372,7 +377,7 @@ msgstr "" msgid "Interface" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2680 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2684 msgid "Interface (prefix ! to exclude)" msgstr "" @@ -389,7 +394,7 @@ msgstr "" msgid "Len" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2313 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2317 msgid "Limit" msgstr "" @@ -401,16 +406,16 @@ msgstr "" msgid "Logging is off on this router" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1471 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1475 msgid "Manual" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2342 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2346 msgid "Manual still uses server protection and poll cadence" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2411 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2415 msgid "" "Manual still uses server protection and poll cadence; it changes the fetch " "budget, not the polling interval." @@ -420,18 +425,18 @@ msgstr "" msgid "Manual test (System → Terminal):" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2336 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2340 msgid "Maximum raw lines" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:51 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:344 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2565 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2572 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2569 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2576 msgid "Message" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2675 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2679 msgid "More filters" msgstr "" @@ -449,7 +454,7 @@ msgid "No WAN zone found" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:886 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:927 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 msgid "No WAN zone found; cannot toggle logging without one." msgstr "" @@ -465,7 +470,7 @@ msgstr "" msgid "OUT" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2595 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2599 msgid "One line" msgstr "" @@ -492,16 +497,16 @@ msgstr "" msgid "Outbound" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2367 msgid "Palette" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2519 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2523 msgid "Pause" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 msgid "Paused" msgstr "" @@ -510,11 +515,11 @@ msgstr "" msgid "Proto" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2656 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2660 msgid "Protocol — common values" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 msgid "Quick search" msgstr "" @@ -522,22 +527,22 @@ msgstr "" msgid "Remove filter" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 msgid "Resume" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2353 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2357 msgid "Row tint" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2447 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2451 msgid "" "Row tint shows pass/deny row backgrounds when checked. Choose Classic (green/" "red, default) or Accessible (teal/orange). Action text stays colored either " "way." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2503 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2507 msgid "" "Row tint used a local color fallback because the active LuCI theme did not " "apply pass/deny backgrounds." @@ -567,40 +572,40 @@ msgstr "" msgid "Search" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1439 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1443 msgid "Server adaptive protection is disabled." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 msgid "Server protection state is unknown." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1444 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 msgid "Server shedding — at most %d log lines per poll." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1446 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1450 msgid "Server truncated this poll (adaptive cap)." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2380 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2384 msgid "Show hostnames" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2351 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2355 msgid "Show pass/deny row background colors" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2618 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2622 msgid "Show rows" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1505 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 msgid "Showing a compact summary of the top of the shown sample." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2542 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2546 msgid "Simple" msgstr "" @@ -609,7 +614,7 @@ msgstr "" msgid "Source" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2685 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2689 msgid "Source IP contains (! to exclude)" msgstr "" @@ -617,53 +622,53 @@ msgstr "" msgid "Source port" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2690 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2694 msgid "Source port (! to exclude)" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1507 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 msgid "Summary data is unavailable; show rows to inspect the sample." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2609 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2613 msgid "Summary mode" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1513 msgid "Summary was bounded before all categories could be included." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2421 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2425 msgid "" "Switching tabs pauses polling; returning performs one catch-up poll. " "Hostnames are off by default because lookups add work." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 msgid "The firewall did not reload; saved and live logging may differ." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2431 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2435 msgid "" "The rate shown for WAN logging is the firewall zone log_limit. OpenWrt " "defaults to 10/minute when no explicit limit is configured; fwlive does not " "impose this cap." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2426 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2430 msgid "" "The router log ring may evict older events before fwlive reads them. fwlive " "cannot recover evicted entries or change forwarding behavior." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2397 msgid "" "The table updates automatically when your firewall logs traffic. Use Pause " "if it moves too fast." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2506 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2510 msgid "Theme tint fallback" msgstr "" @@ -680,15 +685,15 @@ msgstr "" msgid "Time" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1514 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1518 msgid "Top drops" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1517 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1521 msgid "Top rules" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1515 msgid "Top talkers" msgstr "" @@ -711,16 +716,16 @@ msgstr "" msgid "Undo:" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2450 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2454 msgid "Use Detail for all columns (flags, length, raw message)." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2524 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2530 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2528 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2534 msgid "View" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:948 msgid "WAN drop/reject logging is off." msgstr "" @@ -730,13 +735,13 @@ msgid "" "here. Normal LAN browsing will not." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:908 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 msgid "" "WAN drop/reject logging is on. Blocked inbound traffic should appear here as " "it happens — not normal LAN browsing." msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 msgid "WAN logging is already enabled." msgstr "" @@ -765,25 +770,25 @@ msgstr "" msgid "Waiting for firewall events" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2494 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2498 msgid "Watching" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2584 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2588 msgid "Wrap" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:71 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2640 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 msgid "block" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1259 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 msgid "buffer filling" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1267 msgid "buffer full" msgstr "" @@ -800,7 +805,7 @@ msgid "does not contain" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:72 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2641 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 msgid "drop" msgstr "" @@ -808,16 +813,16 @@ msgstr "" msgid "is" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1258 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1262 msgid "loading buffer" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1633 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 msgid "loading…" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1487 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1496 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1491 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1500 msgid "none" msgstr "" @@ -825,94 +830,94 @@ msgstr "" msgid "not" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1848 msgid "not AH" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1847 msgid "not ESP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1846 msgid "not GRE" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1839 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 msgid "not ICMP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 msgid "not ICMPv6" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 msgid "not IGMP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1849 msgid "not SCTP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1837 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 msgid "not TCP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1838 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 msgid "not UDP" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2650 msgid "not block" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2649 msgid "not drop" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 msgid "not pass" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2651 msgid "not reject" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2652 msgid "not unknown" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2663 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2667 msgid "or type…" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:70 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 msgid "pass" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:73 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 msgid "reject" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1265 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1269 msgid "render paused (high rate)" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1274 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1278 msgid "resolve paused (load)" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1280 msgid "scroll frozen — scroll to top to follow live" msgstr "" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1273 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1277 msgid "truncated" msgstr "" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:62 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 msgid "unknown" msgstr "" diff --git a/luci-app-fwlive/po/zh_Hans/luci-app-fwlive.po b/luci-app-fwlive/po/zh_Hans/luci-app-fwlive.po index 1e79dc02d..95f24d3c1 100644 --- a/luci-app-fwlive/po/zh_Hans/luci-app-fwlive.po +++ b/luci-app-fwlive/po/zh_Hans/luci-app-fwlive.po @@ -12,26 +12,26 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1639 msgid "%d matching · %d/%d stored" msgstr "%d 条匹配 · 已存 %d/%d" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1429 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1433 msgid "%s · requested up to %d raw lines · %d firewall messages returned" msgstr "%s · 请求最多 %d 行原始日志 · 返回 %d 条防火墙消息" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1419 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1423 msgid "" "%s · requested up to %d raw lines · server limited fetch to %d · %d firewall " "messages returned" msgstr "" "%s · 请求最多 %d 行原始日志 · 服务器将抓取限制为 %d · 返回 %d 条防火墙消息" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:502 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:543 msgid "%s: %s" msgstr "%s: %s" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1641 msgid "0 matching · %d/%d stored" msgstr "0 条匹配 · 已存 %d/%d" @@ -39,16 +39,16 @@ msgstr "0 条匹配 · 已存 %d/%d" msgid "Accessible (teal/orange)" msgstr "无障碍(青绿/橙色)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:362 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:403 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:37 msgid "Action" msgstr "动作" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:945 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:949 msgid "Administrator access is required to disable logging." msgstr "需要管理员权限才能禁用日志记录。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:914 msgid "Administrator access is required to enable logging." msgstr "需要管理员权限才能启用日志记录。" @@ -56,32 +56,32 @@ msgstr "需要管理员权限才能启用日志记录。" msgid "Allow/deny rules, LAN logging, or anything else." msgstr "允许/拒绝规则、LAN 日志记录或任何其他设置。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1829 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1833 msgid "Also seen" msgstr "其他常见" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:883 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:924 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:926 msgid "Another change is staged for the firewall; apply or revert it first." msgstr "防火墙另有未提交的更改;请先应用或还原。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:901 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:940 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 msgid "" "Another change overwrote WAN logging after it was saved; check the current " "state." msgstr "保存后另有更改覆盖了 WAN 日志设置;请检查当前状态。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2638 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 msgid "Any action" msgstr "所有动作" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1822 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1826 msgid "Any protocol" msgstr "任意协议" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1470 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1474 msgid "Auto" msgstr "自动" @@ -101,7 +101,7 @@ msgstr "变更:" msgid "Classic (green/red)" msgstr "经典(绿/红)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2369 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2373 msgid "Classic uses green/red; Accessible uses teal/orange" msgstr "经典使用绿/红;无障碍使用青绿/橙色" @@ -109,7 +109,7 @@ msgstr "经典使用绿/红;无障碍使用青绿/橙色" msgid "Clear all" msgstr "全部清除" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2710 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2714 msgid "" "Click a cell to filter · ≠ on a chip to exclude · Ctrl+click a rule for " "firewall settings · in Simple view, click a row for the full message" @@ -117,7 +117,7 @@ msgstr "" "点击单元格筛选 · 芯片上的 ≠ 排除 · Ctrl+点击规则打开防火墙设置 · 在简单视图中" "点击行查看完整消息" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2441 msgid "" "Click a row (Time or other non-link cells) to see the full log line (Simple " "view)." @@ -127,36 +127,36 @@ msgstr "点击一行(时间或其他非链接单元格)可查看完整日志 msgid "Click a row for the full message" msgstr "点击行可查看完整消息" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2442 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2446 msgid "" "Click an IP, action, or protocol to filter; use the Protocol menu (or ≠ on a " "chip) to exclude." msgstr "" "点击 IP、动作或协议进行筛选;使用协议菜单(或筛选标签上的 ≠)进行排除。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1823 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 msgid "Common" msgstr "常用" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1654 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1658 msgid "Connection lost — retrying…" msgstr "连接已断开 — 正在重试…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:888 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 msgid "Could not acquire the logging lock." msgstr "无法获取日志记录锁。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:939 msgid "Could not clear the WAN zone log option." msgstr "无法清除 WAN 区域日志选项。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:942 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:946 msgid "Could not disable logging." msgstr "无法禁用日志记录。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:903 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:905 msgid "Could not enable logging." msgstr "无法启用日志记录。" @@ -168,21 +168,26 @@ msgstr "无法加载日志状态。" msgid "Could not refresh logging status; showing the last known state." msgstr "无法刷新日志状态;显示上次已知状态。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:898 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:900 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:941 msgid "Could not save the firewall configuration." msgstr "无法保存防火墙配置。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 msgid "Could not snapshot the current logging state." msgstr "无法快照当前日志记录状态。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:890 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:933 +msgid "Could not track the logging change safely; logging was not changed." +msgstr "无法安全跟踪日志记录的更改;日志记录未更改。" + +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:896 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:937 msgid "Could not write the WAN zone log option." msgstr "无法写入 WAN 区域日志选项。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2665 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2669 msgid "Custom protocol (prefix ! to exclude). Overrides the menu when set." msgstr "自定义协议(! 排除)。有内容时覆盖菜单。" @@ -190,32 +195,32 @@ msgstr "自定义协议(! 排除)。有内容时覆盖菜单。" msgid "DPort" msgstr "目的端口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 msgid "Degraded — sampling" msgstr "降级 — 抽样" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1445 msgid "Degraded — sampling (slow poll RTT; cadence reduced)." msgstr "降级 — 抽样(轮询 RTT 较慢;已降低频率)。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:366 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:407 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:45 msgid "Destination" msgstr "目的地址" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2695 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2699 msgid "Destination IP contains (! to exclude)" msgstr "目的 IP 包含(! 表示排除)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:368 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:409 msgid "Destination port" msgstr "目标端口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2700 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2704 msgid "Destination port (! to exclude)" msgstr "目的端口(! 表示排除)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2553 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2557 msgid "Detail" msgstr "详细" @@ -227,15 +232,15 @@ msgstr "方向" msgid "Disabling…" msgstr "正在禁用…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1268 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1272 msgid "Display limited to %d rows on this device" msgstr "此设备上的显示限制为 %d 行" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2310 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2314 msgid "Display options" msgstr "显示选项" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 msgid "Display options on the bar set Limit, row tint, palette, and hostnames." msgstr "栏上的显示选项可设置行数限制、行着色、调色板和主机名。" @@ -259,7 +264,7 @@ msgstr "启用 WAN 区域的丢弃/拒绝日志记录(同 网络 → 防火墙 msgid "Enable logging" msgstr "启用日志" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2398 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2402 msgid "" "Enable logging turns on WAN zone drop/reject logging only (same as Network → " "Firewall). It does not add rules or log normal LAN browsing." @@ -272,7 +277,7 @@ msgstr "" msgid "Enabling…" msgstr "正在启用…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1836 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 msgid "Exclude" msgstr "排除" @@ -280,11 +285,11 @@ msgstr "排除" msgid "Exclude instead" msgstr "改为排除" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2324 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2328 msgid "Fetch budget" msgstr "抓取配额" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2406 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2410 msgid "" "Fetch budget controls raw log lines per poll. Auto derives from Limit; " "Manual selects a bounded maximum." @@ -302,7 +307,7 @@ msgstr "按 %s 筛选" msgid "Filter logs by rule (hint: %s). Ctrl+click to open firewall settings." msgstr "按规则筛选日志(提示:%s)。Ctrl+点击可打开防火墙设置。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2480 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2484 #: openwrt-feed/luci-app-fwlive/root/usr/share/luci/menu.d/luci-app-fwlive.json:3 msgid "Firewall Live View" msgstr "防火墙实时视图" @@ -315,7 +320,7 @@ msgstr "标志" msgid "Flow" msgstr "流向" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2416 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2420 msgid "" "For a responsive table on a weak device, keep Limit at 250 rows or below. " "The weak-device cap affects rendered rows; the buffer can still retain more." @@ -331,26 +336,26 @@ msgstr "已转发" msgid "Grant access to firewall live log view" msgstr "授予防火墙实时日志视图的访问权限" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2389 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 msgid "Help" msgstr "帮助" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 msgid "Hide rows" msgstr "隐藏行" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1603 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1607 msgid "" "High event rate — table refresh is throttled to protect the browser. The " "buffer still updates; refresh will resume automatically." msgstr "" "事件速率过高 — 已限制表格刷新以保护浏览器。缓冲区仍在更新;刷新将自动恢复。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1452 msgid "Hostname resolve paused while the router is under load." msgstr "路由器负载较高,已暂停主机名解析。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1827 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1831 msgid "ICMPv6" msgstr "ICMPv6" @@ -358,7 +363,7 @@ msgstr "ICMPv6" msgid "IN" msgstr "IN" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2453 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2457 msgid "" "If Row tint looks missing, the active LuCI theme may omit success/error or " "info/warn CSS variables; fwlive falls back to local colors (air-gapped, no " @@ -388,19 +393,19 @@ msgid "" "Install kmod-nf-log and kmod-nf-log6 with the command for your OpenWrt " "release, then reload the firewall." msgstr "" -"请使用适用于您 OpenWrt 版本的命令安装 kmod-nf-log 和 kmod-nf-log6," -"然后重新加载防火墙。" +"请使用适用于您 OpenWrt 版本的命令安装 kmod-nf-log 和 kmod-nf-log6,然后重新加" +"载防火墙。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1653 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1657 msgid "Installation is incomplete. Reinstall luci-app-fwlive." msgstr "安装不完整。请重新安装 luci-app-fwlive。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:404 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:39 msgid "Interface" msgstr "接口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2680 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2684 msgid "Interface (prefix ! to exclude)" msgstr "接口(前缀 ! 表示排除)" @@ -417,7 +422,7 @@ msgstr "缺少内核日志模块" msgid "Len" msgstr "长度" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2313 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2317 msgid "Limit" msgstr "行数限制" @@ -429,16 +434,16 @@ msgstr "实时视图可能不完整 — 已注册旧版 iptables 表" msgid "Logging is off on this router" msgstr "此路由器的日志记录已关闭" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1410 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1471 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1414 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1475 msgid "Manual" msgstr "手动" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2342 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2346 msgid "Manual still uses server protection and poll cadence" msgstr "手动模式仍受服务器保护和轮询节奏约束" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2411 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2415 msgid "" "Manual still uses server protection and poll cadence; it changes the fetch " "budget, not the polling interval." @@ -449,18 +454,18 @@ msgstr "" msgid "Manual test (System → Terminal):" msgstr "手动测试(系统 → 终端):" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2336 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2340 msgid "Maximum raw lines" msgstr "最大原始行数" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:51 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:344 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2565 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2572 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2569 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2576 msgid "Message" msgstr "消息" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2675 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2679 msgid "More filters" msgstr "更多筛选" @@ -479,7 +484,7 @@ msgid "No WAN zone found" msgstr "未找到 WAN 区域" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:886 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:927 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:929 msgid "No WAN zone found; cannot toggle logging without one." msgstr "未找到 WAN 区域;没有它无法切换日志记录。" @@ -495,7 +500,7 @@ msgstr "点击「启用」之前不会有任何更改。" msgid "OUT" msgstr "出接口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2595 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2599 msgid "One line" msgstr "单行" @@ -524,29 +529,29 @@ msgstr "" msgid "Outbound" msgstr "出站" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2363 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2367 msgid "Palette" msgstr "配色" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2519 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2523 msgid "Pause" msgstr "暂停" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 msgid "Paused" msgstr "已暂停" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:364 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:405 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:43 msgid "Proto" msgstr "协议" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2656 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2660 msgid "Protocol — common values" msgstr "协议 — 常用值" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2635 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 msgid "Quick search" msgstr "快速搜索" @@ -554,15 +559,15 @@ msgstr "快速搜索" msgid "Remove filter" msgstr "移除筛选" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1702 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1706 msgid "Resume" msgstr "继续" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2353 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2357 msgid "Row tint" msgstr "行着色" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2447 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2451 msgid "" "Row tint shows pass/deny row backgrounds when checked. Choose Classic (green/" "red, default) or Accessible (teal/orange). Action text stays colored either " @@ -571,7 +576,7 @@ msgstr "" "勾选后行着色显示放行/拒绝行背景。可选经典(绿/红,默认)或无障碍(青绿/橙)。" "操作文本在两种模式下均保持着色。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2503 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2507 msgid "" "Row tint used a local color fallback because the active LuCI theme did not " "apply pass/deny backgrounds." @@ -597,77 +602,77 @@ msgstr "规则标签不可用 — 临时文件创建失败" msgid "SPort" msgstr "源端口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:361 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:402 msgid "Search" msgstr "搜索" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1439 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1443 msgid "Server adaptive protection is disabled." msgstr "服务器自适应保护已禁用。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1437 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1441 msgid "Server protection state is unknown." msgstr "服务器保护状态未知。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1444 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1448 msgid "Server shedding — at most %d log lines per poll." msgstr "服务器正在削减 — 每次轮询最多 %d 行日志。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1446 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1450 msgid "Server truncated this poll (adaptive cap)." msgstr "服务器已截断本次轮询(自适应上限)。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2380 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2384 msgid "Show hostnames" msgstr "显示主机名" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2351 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2355 msgid "Show pass/deny row background colors" msgstr "显示放行/拒绝行背景色" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1548 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2618 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1552 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2622 msgid "Show rows" msgstr "显示行" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1505 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 msgid "Showing a compact summary of the top of the shown sample." msgstr "显示当前样本顶部的简要摘要。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2542 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2546 msgid "Simple" msgstr "简洁" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:365 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:406 #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:44 msgid "Source" msgstr "源地址" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2685 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2689 msgid "Source IP contains (! to exclude)" msgstr "源 IP 包含(! 表示排除)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:367 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/log.js:408 msgid "Source port" msgstr "源端口" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2690 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2694 msgid "Source port (! to exclude)" msgstr "源端口(! 表示排除)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1507 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 msgid "Summary data is unavailable; show rows to inspect the sample." msgstr "摘要数据不可用;显示行以检查样本。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2609 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2613 msgid "Summary mode" msgstr "摘要模式" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1509 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1513 msgid "Summary was bounded before all categories could be included." msgstr "摘要已受限,无法包含所有类别。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2421 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2425 msgid "" "Switching tabs pauses polling; returning performs one catch-up poll. " "Hostnames are off by default because lookups add work." @@ -675,12 +680,12 @@ msgstr "" "切换到其他标签页会暂停轮询;返回时执行一次追赶轮询。主机名默认关闭,因为解析" "会增加工作量。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:892 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:931 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:894 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:935 msgid "The firewall did not reload; saved and live logging may differ." msgstr "防火墙未能重新加载;已保存的日志设置与当前生效状态可能不一致。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2431 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2435 msgid "" "The rate shown for WAN logging is the firewall zone log_limit. OpenWrt " "defaults to 10/minute when no explicit limit is configured; fwlive does not " @@ -689,7 +694,7 @@ msgstr "" "WAN 日志显示的速率是防火墙区域的 log_limit。未显式配置时 OpenWrt 默认为 10 " "条/分钟;此上限并非 fwlive 施加。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2426 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2430 msgid "" "The router log ring may evict older events before fwlive reads them. fwlive " "cannot recover evicted entries or change forwarding behavior." @@ -697,13 +702,13 @@ msgstr "" "路由器日志环形缓冲区可能在 fwlive 读取前淘汰较旧事件。fwlive 无法恢复已淘汰的" "条目,也不会改变转发行为。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2393 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2397 msgid "" "The table updates automatically when your firewall logs traffic. Use Pause " "if it moves too fast." msgstr "防火墙记录流量时表格会自动更新。如果滚动太快,请使用「暂停」。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2506 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2510 msgid "Theme tint fallback" msgstr "主题着色回退" @@ -720,15 +725,15 @@ msgstr "此路由器报告了 Live View 尚无法识别的日志阻止项。" msgid "Time" msgstr "时间" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1514 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1518 msgid "Top drops" msgstr "主要丢弃" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1517 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1521 msgid "Top rules" msgstr "主要规则" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1511 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1515 msgid "Top talkers" msgstr "主要通信方" @@ -753,16 +758,16 @@ msgstr "开启 WAN 防火墙区域的日志记录并重新加载防火墙。" msgid "Undo:" msgstr "撤销:" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2450 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2454 msgid "Use Detail for all columns (flags, length, raw message)." msgstr "使用「详细」可查看全部列(标志、长度、原始消息)。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2524 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2530 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2528 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2534 msgid "View" msgstr "视图" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:944 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:948 msgid "WAN drop/reject logging is off." msgstr "WAN 丢弃/拒绝日志记录已关闭。" @@ -774,7 +779,7 @@ msgstr "" "WAN 丢弃/拒绝日志记录已开启。被阻止的 WAN 入站流量会显示在这里;正常的 LAN 浏" "览不会。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:908 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 msgid "" "WAN drop/reject logging is on. Blocked inbound traffic should appear here as " "it happens — not normal LAN browsing." @@ -782,7 +787,7 @@ msgstr "" "WAN 丢弃/拒绝日志记录已开启。被阻止的入站流量会实时显示在这里 — 正常的 LAN 浏" "览不会。" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:910 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:912 msgid "WAN logging is already enabled." msgstr "WAN 日志记录已处于启用状态。" @@ -811,25 +816,25 @@ msgstr "WAN 日志不可用:无 WAN 区域" msgid "Waiting for firewall events" msgstr "正在等待防火墙事件" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1701 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2494 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1705 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2498 msgid "Watching" msgstr "监视中" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2584 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2588 msgid "Wrap" msgstr "自动换行" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:71 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2640 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 msgid "block" msgstr "拦截" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1259 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 msgid "buffer filling" msgstr "缓冲区填充中" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1263 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1267 msgid "buffer full" msgstr "缓冲区已满" @@ -846,7 +851,7 @@ msgid "does not contain" msgstr "不包含" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:72 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2641 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 msgid "drop" msgstr "丢弃" @@ -854,16 +859,16 @@ msgstr "丢弃" msgid "is" msgstr "是" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1258 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1262 msgid "loading buffer" msgstr "正在加载缓冲区" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1633 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1637 msgid "loading…" msgstr "加载中…" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1487 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1496 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1491 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1500 msgid "none" msgstr "无" @@ -871,94 +876,94 @@ msgstr "无" msgid "not" msgstr "非" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1848 msgid "not AH" msgstr "非 AH" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1847 msgid "not ESP" msgstr "非 ESP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1846 msgid "not GRE" msgstr "非 GRE" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1839 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1843 msgid "not ICMP" msgstr "非 ICMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1840 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1844 msgid "not ICMPv6" msgstr "非 ICMPv6" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 msgid "not IGMP" msgstr "非 IGMP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1845 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1849 msgid "not SCTP" msgstr "非 SCTP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1837 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1841 msgid "not TCP" msgstr "非 TCP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1838 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1842 msgid "not UDP" msgstr "非 UDP" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2650 msgid "not block" msgstr "非阻止" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2645 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2649 msgid "not drop" msgstr "非丢弃" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2644 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 msgid "not pass" msgstr "非放行" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2651 msgid "not reject" msgstr "非拒绝" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2648 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2652 msgid "not unknown" msgstr "非未知" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2663 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2667 msgid "or type…" msgstr "或输入…" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:70 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2639 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 msgid "pass" msgstr "通过" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:73 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2642 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2646 msgid "reject" msgstr "拒绝" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1265 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1269 msgid "render paused (high rate)" msgstr "渲染已暂停(速率过高)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1274 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1278 msgid "resolve paused (load)" msgstr "解析已暂停(负载)" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1276 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1280 msgid "scroll frozen — scroll to top to follow live" msgstr "滚动已冻结 — 滚动到顶部以恢复跟随" -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1273 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:1277 msgid "truncated" msgstr "已截断" #: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/fwlive/table.js:62 -#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2643 +#: openwrt-feed/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js:2647 msgid "unknown" msgstr "未知" diff --git a/luci-app-fwlive/root/usr/libexec/fwlive-logging.sh b/luci-app-fwlive/root/usr/libexec/fwlive-logging.sh index 401e353f6..d16013b0b 100755 --- a/luci-app-fwlive/root/usr/libexec/fwlive-logging.sh +++ b/luci-app-fwlive/root/usr/libexec/fwlive-logging.sh @@ -36,18 +36,22 @@ NF_LOG_IPV6_READY=false # firewall..log bit, computes a target, then uci set + uci commit. Two # concurrent callers could otherwise interleave and last-commit-wins. # -# BusyBox flock constraint: it has NO -w timeout. The lock is opened with -# `exec 9>>` + `flock 9`. In ash/dash, `>>` clears close-on-exec, so a live -# child keeps fd 9 after this holder dies. A stuck lock therefore blocks any -# waiter until the last fd-9 inheritor exits or the device reboots (killing -# the holder alone may not release it). The critical section MUST stay SHORT -# (a few uci commands). Do NOT hold the lock across the /etc/init.d/firewall -# reload (can take seconds); the lock is released before reload. -# Reload-failure rollback re-acquires the lock so the read-compare-restore -# is atomic against concurrent writers; do not drop that re-acquire. -# Overridable for tests/containers (default is root-only /etc/fwlive). +# BusyBox flock has no -w timeout, so acquire with `flock -n 9` and poll for +# WAN_LOG_LOCK_WAIT_SEC one-second retry intervals. In ash/dash, `>>` clears +# close-on-exec, so a live child can keep fd 9 after this holder dies; callers +# fail closed when that stale lock outlives the wait budget. The critical +# section MUST stay SHORT (a few uci commands). Do NOT hold the lock across +# the /etc/init.d/firewall reload (can take seconds); the lock is released +# before reload. Reload-failure rollback re-acquires the lock and checks the +# volatile commit generation so an intervening off->on write is not mistaken +# for an unchanged value; do not drop that re-acquire or generation check. +# The lock path can be overridden for tests/containers (default is root-only +# /etc/fwlive); generation tests use the analogous FWLIVE_WAN_LOG_GENERATION_FILE. WAN_LOG_LOCK_FILE="${FWLIVE_WAN_LOG_LOCK_FILE:-/etc/fwlive/logging.lock}" WAN_LOG_BASELINE_FILE="${FWLIVE_WAN_LOG_BASELINE_FILE:-/etc/fwlive/wan-log-baseline}" +WAN_LOG_GENERATION_FILE="${FWLIVE_WAN_LOG_GENERATION_FILE:-/var/run/fwlive/wan-log-generation}" +WAN_LOG_LOCK_WAIT_SEC=5 +WAN_LOG_COMMIT_GENERATION='unavailable' WAN_ZONE_DIAGNOSTIC_JSON='' WAN_ZONE_FOUND='' @@ -155,8 +159,9 @@ wan_log_lock_dir_safe() { [ -z "$_writable" ] } -# Acquire the exclusive logging lock on fd 9. Blocks until free; fails closed -# (return 1) only if the lock file cannot be opened or flock is unavailable. +# Acquire the exclusive logging lock on fd 9. Polls non-blocking flock for a +# bounded retry budget; fails closed if the lock file cannot be opened, flock is +# unavailable, or the lock stays busy for WAN_LOG_LOCK_WAIT_SEC intervals. # Create/tighten the lock to 0600 so unprivileged UIDs cannot take LOCK_EX on # a world-readable fd (flock(2) allows exclusive locks on O_RDONLY). acquire_wan_log_lock() { @@ -182,10 +187,25 @@ acquire_wan_log_lock() { # silence this process's stderr on the success path. ( exec 9>>"$WAN_LOG_LOCK_FILE" ) 2>/dev/null || return 1 exec 9>>"$WAN_LOG_LOCK_FILE" - flock 9 2>/dev/null || { - exec 9>&- - return 1 - } + _waited=0 + while :; do + if flock -n 9 2>/dev/null; then + return 0 + else + _flock_rc=$? + fi + # BusyBox and util-linux both use status 1 for lock contention. Other + # failures (including a missing flock command) are setup errors. + if [ "$_flock_rc" -ne 1 ]; then + exec 9>&- + return 1 + fi + [ "$_waited" -ge "$WAN_LOG_LOCK_WAIT_SEC" ] && break + sleep 1 + _waited=$((_waited + 1)) + done + exec 9>&- + return 1 } # Release the logging lock (explicit unlock, then close fd 9). @@ -194,6 +214,66 @@ release_wan_log_lock() { exec 9>&- } +# WAN_LOG_GENERATION_FILE is under a root-only volatile directory. Each +# fwlive writer increments it while holding fd 9, before staging/committing +# the UCI update. Atomic replacement keeps a killed writer from leaving a +# truncated token; a token write that succeeds but is followed by a failed +# commit is conservative (it can only suppress a later rollback). +wan_log_generation_read() { + _generation_dir="$(dirname "$WAN_LOG_GENERATION_FILE")" + [ -L "$_generation_dir" ] && return 1 + wan_log_lock_dir_safe "$_generation_dir" || return 1 + [ -L "$WAN_LOG_GENERATION_FILE" ] && return 1 + if [ ! -e "$WAN_LOG_GENERATION_FILE" ]; then + printf '0' + return 0 + fi + [ -f "$WAN_LOG_GENERATION_FILE" ] || return 1 + _generation_value=$(cat "$WAN_LOG_GENERATION_FILE" 2>/dev/null) || return 1 + case "$_generation_value" in + ''|*[!0-9]*|0[0-9]*) return 1 ;; + esac + printf '%s' "$_generation_value" +} + +wan_log_generation_bump() { + _generation_dir="$(dirname "$WAN_LOG_GENERATION_FILE")" + [ -L "$_generation_dir" ] && return 1 + ( umask 077; mkdir -p "$_generation_dir" ) 2>/dev/null || return 1 + [ -L "$_generation_dir" ] && return 1 + wan_log_lock_dir_safe "$_generation_dir" || return 1 + [ -L "$WAN_LOG_GENERATION_FILE" ] && return 1 + _generation_value=$(wan_log_generation_read) || return 1 + # Keep below signed 32-bit ash arithmetic bounds. Exhaustion fails closed; + # it must never wrap and let an old rollback token compare equal again. + [ "$_generation_value" -lt 2147483646 ] || return 1 + _generation_next=$((_generation_value + 1)) + _generation_tmp=$(mktemp "${WAN_LOG_GENERATION_FILE}.XXXXXX") || return 1 + if ! printf '%s\n' "$_generation_next" >"$_generation_tmp"; then + rm -f "$_generation_tmp" + return 1 + fi + chmod 0600 "$_generation_tmp" 2>/dev/null || { + rm -f "$_generation_tmp" + return 1 + } + [ -L "$WAN_LOG_GENERATION_FILE" ] && { + rm -f "$_generation_tmp" + return 1 + } + mv -f "$_generation_tmp" "$WAN_LOG_GENERATION_FILE" 2>/dev/null || { + rm -f "$_generation_tmp" + return 1 + } + printf '%s' "$_generation_next" +} + +wan_log_tracking_failed_json() { + _zone_json="$1" + logger -t fwlive "WAN log toggle aborted: commit generation unavailable" 2>/dev/null || true + printf '{"ok":false,"changed":false,"wan_zone":%s,"error":"rollback_tracking_failed"}' "$_zone_json" +} + find_wan_zone_section_state() { # Match the first zone whose name is 'wan' or whose effective network list # contains 'wan'/'wan6'. UCI defaults an omitted network option to the @@ -765,6 +845,12 @@ restore_wan_zone_log() { logger -t fwlive "WAN log rollback skipped: firewall changes pending" 2>/dev/null || true return 1 fi + # Record this write before touching UCI. If generation tracking is + # unavailable, do not commit an untracked rollback over another caller. + wan_log_generation_bump >/dev/null || { + logger -t fwlive "WAN log rollback skipped: commit generation unavailable" 2>/dev/null || true + return 1 + } # Capture the committed value before staging our rollback. If another # writer stages a firewall delta after this point, the post-stage guard # below must be able to undo only our rollback staging without reverting @@ -848,6 +934,7 @@ commit_wan_log_change() { zone="$1" zone_json="$2" target="$3" + WAN_LOG_COMMIT_GENERATION='unavailable' # Last-moment guard: runs before OUR delta is staged, so a # non-empty changes list here can only be a foreign writer's race. @@ -857,6 +944,16 @@ commit_wan_log_change() { return 1 fi + # Advance the shared volatile revision before the UCI write. A later + # reload-failure rollback may restore only if this exact revision is still + # current. Failing closed here avoids a commit that other in-flight callers + # cannot detect. A failed UCI operation can leave a harmless revision gap. + _generation=$(wan_log_generation_bump) || { + wan_log_tracking_failed_json "$zone_json" + return 1 + } + WAN_LOG_COMMIT_GENERATION="$_generation" + # Staging is empty here — capture the committed value so a post-stage # foreign race can undo our delta without `uci revert firewall`. previous=$(wan_zone_log_value "$zone") @@ -946,21 +1043,21 @@ report_wan_log_after_commit() { return 0 fi shift 2 - reload_and_report_wan_log "$@" + reload_and_report_wan_log "$@" "$WAN_LOG_COMMIT_GENERATION" } # Firewall reload + best-effort UCI rollback on reload failure. The reload # itself runs WITHOUT the logging lock (it can take seconds and a held lock -# would block a concurrent toggle until the holder exits — BusyBox flock has -# no -w timeout). +# makes concurrent toggles poll across WAN_LOG_LOCK_WAIT_SEC one-second +# intervals, plus command and scheduling overhead). # -# The ROLLBACK re-acquires the lock: read->compare->restore is only -# atomic when no other writer can commit between the read and the restore. -# All writers hold the same flock, so re-acquiring it makes the -# decision-and-restore a serialized unit. The lock is held only for the few -# uci commands of the restore (short critical section), never across the -# reload. If the lock cannot be re-acquired, skip the rollback (report the -# reload failure; the next toggle self-corrects). +# The ROLLBACK re-acquires the lock and checks the generation captured at +# commit time. Value equality alone misses an off->on ABA while reload runs. +# All fwlive writers advance the same generation under the lock before UCI +# changes, so rollback proceeds only when no later writer has intervened. +# The lock is held only for the few uci commands of the restore (short +# critical section), never across the reload. If reacquisition or generation +# verification fails, skip rollback and report the reload failure. reload_and_report_wan_log() { zone="$1" previous="$2" @@ -968,26 +1065,29 @@ reload_and_report_wan_log() { fail_msg="$4" success_msg="$5" zone_json="$6" + committed_generation="$7" if ! reload_firewall; then # Re-acquire the logging lock so the rollback decision is atomic - # against concurrent toggles (no check-then-restore race). + # against concurrent toggles and check for an intervening ABA. if acquire_wan_log_lock; then + current_generation=$(wan_log_generation_read 2>/dev/null || true) now="$(wan_zone_log_value "$zone")" - if [ "$now" = "$committed" ]; then - # Current value is still what THIS caller committed — restore - # the pre-commit value. (If a concurrent toggle committed the - # same value, the toggle is idempotent: the state intent is - # identical, so restoring previous is the correct rollback.) + if [ -n "$committed_generation" ] \ + && [ "$committed_generation" != unavailable ] \ + && [ "$current_generation" = "$committed_generation" ] \ + && [ "$now" = "$committed" ]; then + # No later fwlive commit attempt advanced the generation, and + # UCI still carries this caller's committed value. if restore_wan_zone_log "$zone" "$previous"; then logger -t fwlive "$fail_msg" 2>/dev/null || true else logger -t fwlive "Firewall reload failed; WAN log rollback skipped (pending changes or restore failed)" 2>/dev/null || true fi else - # A concurrent toggle changed the value after our commit; do - # not clobber it. Log the divergence and leave the newer value. - logger -t fwlive "Firewall reload failed; WAN log changed concurrently — rollback skipped" 2>/dev/null || true + # A later writer may have left the same value (ABA), or the + # revision may be unavailable. Do not clobber that intent. + logger -t fwlive "Firewall reload failed; WAN log changed concurrently or revision unavailable — rollback skipped" 2>/dev/null || true fi release_wan_log_lock else @@ -1045,6 +1145,11 @@ enable_wan_logging() { # uninstall restore logging after disable. Skip-if-exists in # the helper. Failure must not become baseline_snapshot_failed. maybe_snapshot_wan_log_baseline "$zone" "" || true + if ! wan_log_generation_bump >/dev/null; then + release_wan_log_lock + wan_log_tracking_failed_json "$zone_json" + return 0 + fi release_wan_log_lock printf '{"ok":true,"changed":false,"wan_zone":%s}' "$zone_json" return 0 @@ -1098,6 +1203,11 @@ disable_wan_logging() { current=$(wan_zone_log_value "$zone") if [ -z "$current" ] || ! wan_filter_log_enabled "$current"; then + if ! wan_log_generation_bump >/dev/null; then + release_wan_log_lock + wan_log_tracking_failed_json "$zone_json" + return 0 + fi release_wan_log_lock printf '{"ok":true,"changed":false,"wan_zone":%s}' "$zone_json" return 0 diff --git a/luci-app-homeproxy-pro/Makefile b/luci-app-homeproxy-pro/Makefile index 7a113785c..9d10c53a8 100644 --- a/luci-app-homeproxy-pro/Makefile +++ b/luci-app-homeproxy-pro/Makefile @@ -23,7 +23,7 @@ LUCI_DEPENDS:= \ PKG_NAME:=luci-app-homeproxy-pro PKG_VERSION:=28.9.1.14 -PKG_RELEASE:=7 +PKG_RELEASE:=8 # Only files the package actually ships belong here. The previous list named # four paths that exist nowhere in the tree - certs/ and ruleset/ are created at diff --git a/luci-app-homeproxy-pro/README.md b/luci-app-homeproxy-pro/README.md index 7c64b2ee3..43035e787 100644 --- a/luci-app-homeproxy-pro/README.md +++ b/luci-app-homeproxy-pro/README.md @@ -74,6 +74,38 @@ **一句话总结**:pro 的核心价值是**把"单文件能跑"变成"orchestrator + table-driven adapter + 可独立测试的模块"**,并把约束、质量、回滚三件事从靠人盯变成靠代码执行(arch-guard 135 checks 静态锁住跨文件不变量)。 +## 排障要点 + +两条会把人带偏的坑,都是实测踩出来的,写在这里省得下一个人重走一遍。 + +**1. 客户端的 `sing-box-c.log` 里会出现"不是本机做出的决定"** + +代理节点侧的失败会用同样的措辞落进客户端日志。例如目的 IP 的 443 没有服务: + +``` +ERROR connection: open connection to 1.2.3.4:443 using outbound/direct[direct]: + dial tcp 1.2.3.4:443: connect: connection refused +``` + +这行**不代表**本机把该流量送去了直连——它可能是远端节点直连目标失败后的回传。曾据此误判"分流规则失效",实际是节点侧错误被记进了客户端日志。 + +判定真实走向要看**转发层**,不要看日志措辞: + +```sh +# 被重定向到本机代理端口 = 流量确实进入了代理路径 +grep -m1 'dst=.*dport=443' /proc/net/nf_conntrack # 回复方向出现 sport=5331 +# 分流链各分支计数:return 的分支=直连,最后 goto=走代理 +nft list chain inet fw4 homeproxy_redirect +# 大陆集合:防火墙据此判定"直连",与路由侧的 china-ip 规则集同源(china_ip4.txt) +nft list chain inet fw4 homeproxy_redirect | grep mainland_addr_v4 +``` + +**2. `sing-box tools connect/fetch` 不能用来验证分流** + +两者都通过 `instance.Outbound().Default()` 取默认出站(`cmd_tools_connect.go` / `cmd_tools_fetch.go`),**不经过 route 规则**。用它们测"某个域名/IP 会走代理还是直连",得到的结论一定是错的。 + +要验证实际走向,只能让**局域网真实客户端**发起连接,再看上面的 conntrack / nft 计数,或看 `sing-box-c.log` 里的 `outbound/xxx[tag]` 行(那才是本机的出站选择)。 + ## 已知限制 - **试验性**:不承诺 API/配置稳定,重大变更可能在 minor 版本里发生。 diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/client.uc b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/client.uc index ec790ad5c..814cce549 100644 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/client.uc +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/client.uc @@ -58,6 +58,20 @@ import { attachSchema, attachExperimental } from './common.uc'; export function generate(dm, env) { const ctx = build_context(dm, env); + /* Everything the client prints lands in one file, and not all of it was + * decided here: when the proxy node cannot reach a destination, sing-box + * reports it through the same logger, so a line like + * + * open connection to 1.2.3.4:443 using outbound/direct[direct]: + * connect: connection refused + * + * can be the *node's* failure rather than this router sending the traffic + * direct. Reading it as a local routing decision already produced one + * wrong conclusion during review. What the router actually did is in the + * forwarding layer: `nft list chain inet fw4 homeproxy_redirect` (a + * `return` branch is direct, the final `goto` is the proxy port) and + * `/proc/net/nf_conntrack` (`sport=5331` on the reply tuple). See the + * README's troubleshooting section. */ const config = { log: { disabled: false, diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/context.uc b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/context.uc index b6dc13f32..fc87f82cd 100644 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/context.uc +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/context.uc @@ -130,9 +130,27 @@ export function build_context(dm, env) { udp_mapping = (udp_mapping_raw === 'default') ? '' : udp_mapping_raw, udp_filtering = (udp_filtering_raw === 'default') ? '' : udp_filtering_raw; + /* Where a destination the preset lists do not mention goes. This is the + * mode's whole default policy, so it is declared once here and read by + * both consumers - the route rule chain and the DNS rule chain: + * + * bypass_mainland_china mainland -> direct, everything else -> proxy + * global everything -> proxy + * gfwlist only the list -> proxy, everything else direct + * proxy_mainland_china mainland -> proxy, everything else -> direct + * + * The two chains have to agree. They used to say it independently (a + * literal `main-dns` in dns.uc, a literal `main-out` in route.uc) with + * nothing tying them together, and the route side applied "unknown goes + * to the proxy" to all four modes - so "Only proxy mainland China" sent + * every unlisted destination through the proxy, which is the opposite of + * what the mode is named. Both now derive from this one value. */ + const proxy_fallback = (routing_mode !== 'proxy_mainland_china'); + /* Routing-mode-dependent defaults */ const ctx = { routing_mode, proxy_mode, ipv6_support, log_level, + proxy_fallback, self_mark, ntp_server, dns_port, mixed_port, redirect_port, tproxy_port, tun_name, tun_addr4, tun_addr6, tun_mtu, diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc index 43619ac27..140996d9a 100644 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc @@ -112,7 +112,11 @@ function append_proxy_dns(config, dm, ctx) { detour: 'main-out', ...parse_dnsserver(ctx.dns_server, 'tcp') }); - config.dns.final = 'main-dns'; + /* The DNS half of the mode's default policy. It has to name the same + * side the route chain falls through to (ctx.proxy_fallback), or a + * domain that ends up proxied would be resolved by the resolver of the + * other path. The pair is asserted per mode in the generator suite. */ + config.dns.final = ctx.proxy_fallback ? 'main-dns' : 'default-dns'; if (length(ctx.direct_domain_list)) push(config.dns.rules, { diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/route.uc b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/route.uc index 51d9c66ab..65319325d 100644 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/route.uc +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/generator/route.uc @@ -26,7 +26,7 @@ 'use strict'; -import { isEmpty, strToInt, strToTime, strToBool, parse_port } from '../homeproxy-pro.uc'; +import { isEmpty, strToInt, strToTime, strToBool, parse_port, HP_DIR } from '../homeproxy-pro.uc'; import { get_outbound, get_resolver, get_ruleset, get_direct_override } from './common.uc'; @@ -92,15 +92,24 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { outbound: 'direct-out' }); - /* Bypass CN traffic: resolve the destination first, then route by IP. - sing-box does not match an IP-based rule set (geoip-cn) against a domain - destination unless it is resolved first, so add an explicit resolve - action; geoip-cn then sends China IPs to direct and everything else falls - through to main-out (proxy). This avoids relying on the geosite-* domain - lists, which can mis-classify foreign domains (e.g. Google's gvt2.com - beacons) as "cn" and send them direct to time out. Keep the direct-domain - fast-path above for known direct domains. */ - if (ctx.routing_mode === 'bypass_mainland_china') { + /* Split by destination IP, in both directions. + * + * sing-box does not match an IP-based rule set (geoip-cn) against a + * domain destination unless it is resolved first, so an explicit resolve + * action comes first. Which way the split points is the mode's default + * policy (ctx.proxy_fallback): + * + * bypass/global/gfwlist mainland -> direct, the rest falls through to + * main-out (proxy) + * proxy_mainland_china mainland -> proxy, the rest falls through to + * direct-out + * + * Using geoip-cn rather than the geosite-* domain lists is deliberate: + * those mis-classify foreign domains (Google's gvt2.com beacons) as "cn" + * and would send them direct to time out. Keep the direct-domain + * fast-path above for known direct domains. */ + if (ctx.routing_mode === 'bypass_mainland_china' + || ctx.routing_mode === 'proxy_mainland_china') { push(config.route.rules, { action: 'resolve', strategy: (ctx.ipv6_support !== '1') ? 'prefer_ipv4' : null @@ -108,6 +117,23 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { push(config.route.rules, { rule_set: 'geoip-cn', action: 'route', + outbound: ctx.proxy_fallback ? 'direct-out' : 'main-out' + }); + } + if (ctx.routing_mode === 'bypass_mainland_china') { + /* geoip-cn.srs is upstream's list; the firewall's mainland set is + * built from our own china_ip4.txt (firewall_post.ut reads it + * directly). The two disagree - the bundled list has 8.152.0.0/13 + * (Alibaba Cloud) and geoip-cn.srs does not - so a connection into + * that range passes the firewall as "not mainland" and would then be + * sent direct by the rule above instead of to the proxy. This local + * rule-set is generated from the same china_ip4.txt, which is what + * makes both sides decide from one list. In + * proxy_mainland_china it is not needed twice: the geoip-cn rule + * already selects the mainland side for the proxy. */ + push(config.route.rules, { + rule_set: 'china-ip', + action: 'route', outbound: 'direct-out' }); } @@ -134,7 +160,10 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { override_port: main_override.override_port }); - config.route.final = 'main-out'; + /* The route half of the mode's default policy - the other consumer of + * ctx.proxy_fallback, and the reason dns.final and this line are + * asserted together per mode. */ + config.route.final = ctx.proxy_fallback ? 'main-out' : 'direct-out'; /* --- proxy-mode rule_set block ----------------------------------- */ @@ -162,7 +191,13 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { ] }); - if (ctx.routing_mode === 'bypass_mainland_china') { + /* Both mainland modes split on geoip-cn, so both need it declared - it is + * what the route rule added above matches. `proxy_mainland_china` used + * to reach this point without it and sing-box refused the whole config + * with "initialize rule[3]: rule-set not found: geoip-cn", which the + * health gate turned into a rollback and an unproxied network. */ + if (ctx.routing_mode === 'bypass_mainland_china' + || ctx.routing_mode === 'proxy_mainland_china') { /* * Fetched straight from the upstream SagerNet repositories and * downloaded through the selected node. A direct fetch depends on @@ -170,18 +205,22 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { * makes it fail intermittently; the files total ~250 KB per * day, so proxying the download costs almost nothing. * - * Both geosite-cn and geoip-cn are still emitted, but they are - * consumed by different blocks: + * Both rule_sets are emitted, but they are consumed by different + * blocks: * - * geoip-cn - referenced by the route rule above (line 105) to - * split CN destinations to direct-out. + * geoip-cn - referenced by the route rule above to split + * destinations by IP: mainland -> direct-out in + * bypass_mainland_china, mainland -> main-out in + * proxy_mainland_china. * geosite-cn - referenced only by the DNS rule in - * generator/dns.uc line 135-139 (rule_set: geosite-cn - * -> server: china-dns); the route layer never - * matches it. Sing-box still loads and keeps the - * rule-set in memory even when only one block - * references it, so removing it would also break the - * DNS split. + * generator/dns.uc (rule_set: geosite-cn -> + * server: china-dns); the route layer never matches + * it. Sing-box still loads and keeps the rule-set in + * memory even when only one block references it, so + * removing it would also break the DNS split. It is + * only declared for bypass_mainland_china because that + * is the only mode whose DNS chain routes through + * china-dns. * * History: a third geosite-noncn used to be declared here as well, * but no rule referenced it and sing-box still loaded and updated @@ -205,6 +244,21 @@ function build_route_proxy(config, dm, ctx, direct_overrides) { update_interval: '24h', download_detour: 'main-out' }); + + /* Local, and not downloaded: it is generated from the same + * china_ip4.txt the firewall renders homeproxy_mainland_addr_v4 + * from, so the two cannot drift apart. `type: local` is watched by + * sing-box with fswatch, so when the resource updater replaces the + * file the running instance reloads it in place - no restart and, + * more importantly, no second copy of the list to keep in sync. + * China IPv6 is deliberately absent: the firewall only fills the v6 + * set when ipv6_support is on, and the client refuses to resolve + * AAAA when it is off. */ + push(config.route.rule_set, { + type: 'local', + tag: 'china-ip', + path: HP_DIR + '/resources/china_ip4.json' + }); } if (isEmpty(config.route.rule_set)) diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc new file mode 100644 index 000000000..d2d744157 --- /dev/null +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc @@ -0,0 +1,147 @@ +#!/usr/bin/ucode +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Turn a plain CIDR list into a sing-box local rule-set, so the route side and + * the firewall decide "is this destination mainland China" from the same bytes. + * + * The firewall's homeproxy_mainland_addr_v4 set is filled by firewall_post.ut + * straight from /etc/homeproxy-pro/resources/china_ip4.txt, while the route rule + * used the upstream geoip-cn.srs. Those two disagree: the bundled list carries + * 8.152.0.0/13 (Alibaba Cloud) which geoip-cn.srs does not, so a connection to + * segmentfault.com or ctrip.com resolved into that range is redirected by the + * firewall (not in the nft set) and then sent *direct* by the route rule (not + * in geoip-cn.srs) - the opposite of what the mode promises. + * + * Reading the same text file on both sides removes the disagreement, and it + * has to survive the resource updater replacing the list: the generated + * rule-set is written with a local `type: local` entry in the client config, + * which sing-box watches with fswatch, so replacing the file is enough - no + * service restart, no second copy of the data. + * + * Usage: ucode -S china_ip_ruleset.uc + * Exit 0 when the file was written, 1 (with a message on stderr) otherwise. + * An unreadable or empty source is *not* an error: the caller may legitimately + * have no list yet, and a missing rule-set file is handled by the generator + * (it emits the local rule only when the file exists). + */ + +'use strict'; + +import { readfile, writefile, rename, unlink } from 'fs'; + +if (length(ARGV) < 2 || ARGV[0] == null || ARGV[1] == null) { + warn('usage: china_ip_ruleset.uc \n'); + exit(1); +} + +const src = ARGV[0]; +const dst = ARGV[1]; + +const data = readfile(src); +if (type(data) !== 'string') { + warn(sprintf('cannot read %s\n', src)); + exit(1); +} + +/* One `ip_cidr` array is one netipx.IPSet on the sing-box side, which is a + * prefix-compressed structure with a binary search per query; splitting the + * list into several rules would only add rules to walk per packet. + * + * The entries are validated here rather than trusted. netip.ParsePrefix() is + * what sing-box uses, it is strict (no leading zeros, no out-of-range octets), + * and one bad entry makes it reject the *whole* rule-set - which would take + * the client's start with it. A malformed line is therefore skipped and + * reported, exactly like the blank lines and comments a list may carry. */ +function is_v4(addr) { + const parts = split(addr, '.'); + if (length(parts) != 4) + return false; + for (let part in parts) { + if (!match(part, /^[0-9]{1,3}$/)) + return false; + /* Go's parser rejects "01"; match it so the file it accepts and + * the file we emit cannot disagree. */ + if (length(part) > 1 && substr(part, 0, 1) == '0') + return false; + if (int(part) > 255) + return false; + } + return true; +} + +function is_v6(addr) { + /* Deliberately structural, not exhaustive: the point is to keep a + * malformed line out, and the strict parser on the other side is the + * authority for what a valid address is. */ + if (!match(addr, /^[0-9a-fA-F:]+$/)) + return false; + if (!match(addr, /:/)) + return false; + if (match(addr, /:::/)) + return false; + return true; +} + +function valid_cidr(entry) { + const slash = index(entry, '/'); + if (slash <= 0) + return false; + const addr = substr(entry, 0, slash); + const bits = substr(entry, slash + 1); + if (!match(bits, /^[0-9]{1,3}$/)) + return false; + if (is_v4(addr)) + return int(bits) <= 32; + if (is_v6(addr)) + return int(bits) <= 128; + return false; +} + +const prefixes = []; +let skipped = 0; +for (let line in split(data, /\n/)) { + const entry = trim(line); + if (entry == '') + continue; + /* The updater's lists are bare CIDRs, but a stray comment or a host + * address must not make sing-box reject the whole rule-set at start. */ + if (match(entry, /^[#;]/)) + continue; + if (!valid_cidr(entry)) { + skipped++; + continue; + } + push(prefixes, entry); +} + +if (skipped > 0) + warn(sprintf('skipped %d malformed entries in %s\n', skipped, src)); + +if (length(prefixes) == 0) { + warn(sprintf('no usable CIDR entries in %s\n', src)); + exit(1); +} + +/* The temporary name is a sibling so the rename stays on one filesystem: the + * watcher must never read a half-written file. `%.J` is the same serializer + * the config generator uses, so the output is the canonical sing-box form. */ +const rendered = sprintf('%.J\n', { + version: 3, + rules: [ + { ip_cidr: prefixes } + ] +}); + +const tmp = dst + '.tmp'; +if (!writefile(tmp, rendered)) { + warn(sprintf('cannot write %s\n', tmp)); + exit(1); +} +if (!rename(tmp, dst)) { + unlink(tmp); + warn(sprintf('cannot install %s\n', dst)); + exit(1); +} + +printf('%d prefixes\n', length(prefixes)); diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh index 6ff65a691..1bbc69156 100644 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh @@ -127,6 +127,24 @@ hp_prepare_runtime_files() { local client_enabled="$4" local server_enabled="$5" + # The route rule that keeps mainland destinations direct matches a local + # rule-set generated from china_ip4.txt, the same list the firewall + # renders its nft set from, so both sides decide from one source. It is + # regenerated here as well as by the resource updater: an install that + # predates this file (or a list replaced while the service was stopped) + # must still get one, or the client config would reference a missing + # file and sing-box would refuse to start. A missing source list is not + # an error - the generator then emits no route-side rule at all. + if [ "$client_enabled" = "1" ] && [ -f "$hp_dir/resources/china_ip4.txt" ]; then + if ucode -S "$hp_dir/scripts/runtime/china_ip_ruleset.uc" \ + "$hp_dir/resources/china_ip4.txt" "$hp_dir/resources/china_ip4.json" >>"$LOG_PATH" 2>&1; then + chown sing-box:sing-box "$hp_dir/resources/china_ip4.json" 2>"/dev/null" \ + || log "Warning: failed to hand ${hp_dir}/resources/china_ip4.json to sing-box." + else + log "Warning: could not generate ${hp_dir}/resources/china_ip4.json; the route side keeps the previous list." + fi + fi + # cache_file is enabled for bypass_mainland_china and custom alike # (generator/common.uc:attachExperimental). The file has to exist before # the client jail binds it, or sing-box cannot create it in there. @@ -219,13 +237,16 @@ hp_procd_client_instance() { # guessed subset. procd orders the mounts by path, so this parent is # bound before the read-write cache.db below and cannot shadow it. procd_add_jail_mount "$hp_dir/" - # cache_file is enabled for bypass_mainland_china and custom alike - # (generator/common.uc:attachExperimental), so both need the file - # writable inside the jail. - case "$routing_mode" in - "bypass_mainland_china"|"custom") - procd_add_jail_mount_rw "$hp_dir/cache.db" ;; - esac + # cache_file is emitted unconditionally (generator/common.uc: + # attachExperimental takes the routing mode and never reads it), so + # every mode's sing-box opens this file and dies with + # initialize cache-file: open /etc/homeproxy-pro/cache.db: read-only file system + # if it is bound read-only - which is what the mode-gated mount here + # did for global / gfwlist / proxy_mainland_china. The instance then + # failed its health gate and the intercept layer was reverted, so + # switching to one of those modes took the whole network off the + # proxy. + procd_add_jail_mount_rw "$hp_dir/cache.db" procd_add_jail_mount "$hp_dir/certs/" # The certificate path gate accepts /etc/acme as well (a client TLS # certificate managed by acme.sh), so the client jail has to carry it diff --git a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/update_resources.sh b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/update_resources.sh index 309217af8..03e51f88f 100755 --- a/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/update_resources.sh +++ b/luci-app-homeproxy-pro/root/etc/homeproxy-pro/scripts/update_resources.sh @@ -193,6 +193,23 @@ check_list_update() { # can read it. date -u +"%Y-%m-%dT%H:%M:%SZ" > "$RESOURCES_DIR/$listtype.updated_at" log "[$(to_upper "$listtype")] Successfully updated via $mirror (blob $local_blob)." + # The route side reads the China list through a generated sing-box + # rule-set rather than geoip-cn.srs, so the list and what the kernel + # decides from cannot drift apart. sing-box watches that file with + # fswatch and reloads it in place, so regenerating it here is the + # whole update path - no service restart. A failure is logged and + # not fatal: the previous rule-set is still valid and the firewall + # has already switched to the new list, which is exactly the state + # the next run (or the next service start) repairs. + if [ "$listtype" = "china_ip4" ]; then + if ucode -S "$SCRIPT_DIR/runtime/china_ip_ruleset.uc" \ + "$RESOURCES_DIR/china_ip4.txt" "$RESOURCES_DIR/china_ip4.json" >>"$LOG_PATH" 2>&1; then + log "[CHINA_IP4] Route-side rule-set regenerated." + chown sing-box:sing-box "$RESOURCES_DIR/china_ip4.json" 2>"/dev/null" + else + log "[CHINA_IP4] Warning: could not regenerate china_ip4.json; the route side keeps the previous list." + fi + fi else rm -f "$RUN_DIR/$listname" log "[$(to_upper "$listtype")] Failed to install update (mv failed)." diff --git a/luci-app-homeproxy-pro/tests/README.md b/luci-app-homeproxy-pro/tests/README.md index 11bb32a8f..d8488a900 100644 --- a/luci-app-homeproxy-pro/tests/README.md +++ b/luci-app-homeproxy-pro/tests/README.md @@ -269,6 +269,7 @@ Two further host differences are bridged so the remaining checks still run: | `tests/i18n-coverage.py` | Reports how many `po/templates/homeproxy-pro.pot` strings have a non-fuzzy, non-empty `po/zh_Hans/homeproxy-pro.po` translation. Technical tokens that stay as-is are listed in `tests/i18n-ignore.txt`; anything else missing fails the run (`--fail-below 100`) and adds a job-summary entry. The release workflow (`build.yml`) deliberately warns instead of failing, so a translation gap cannot block packaging - the PR gates already catch it. | | `tests/luci-form-snapshot.js` | Dumps every option (name, kind, title, description, depends, values, datatype/default/…) of the node, client and server views. Diffs against `tests/snapshots/{node,client,server}.json`, so a refactor that changes a field or its visibility fails. | | `tests/ucode/test_homeproxy_utils.uc` | `executeCommand()` return shape, stderr/exit-code capture, binary detection, and a descriptor-leak check (200 calls). | +| `tests/ucode/test_china_ip_ruleset.sh` | `runtime/china_ip_ruleset.uc`, the generator that turns `china_ip4.txt` into the `type: local` rule-set the route side matches mainland destinations with — the same list `firewall_post.ut` renders `homeproxy_mainland_addr_v4` from, so both sides decide from one source. The cases are the ones that break a router silently: a malformed line must be skipped (sing-box rejects the *whole* rule-set over one bad entry, and the client then will not start), the file must be replaced by rename (the running instance watches it with fswatch), and an empty or unreadable source must fail instead of installing a rule-set that matches nothing. Pins the bundled list's `8.152.0.0/13` — the range `geoip-cn.srs` does not carry, and the reason this exists. | | `tests/ucode/test_resource_blob_sha.sh` | `resource_blob_sha.uc`, the digest the resource updater verifies downloads with. The expected values are git's own (`git hash-object` on the same bytes), covering the two cases an implementation gets wrong quietly: the empty file (a real blob id, not "no digest") and content whose byte length differs from its character count. Unreadable input must produce *no* digest and exit non-zero - the updater treats an empty answer as "cannot verify" and refuses, so a made-up digest would turn an unreadable file into a passing check. Re-checks the repository's real resource files against git when the host has it. | | `tests/ucode/test_homeproxy_utils_inject.uc` | The failure path of `executeCommand()`: the script stages a copy of `homeproxy-pro.uc` whose `system()` call is replaced by `die()`, then checks that the exception still propagates and that neither descriptor leaks. | | `tests/ucode/test_tls_transport.uc` | Direct calls into `buildTLSObject()` / `buildTransportObject()`: client-vs-server-only fields (no `insecure` on a server inbound, no `utls` on a server, `public_key` only on the client and `private_key` only on the server for reality), the ECH client/server split, and the `validateHomeProxyPath()` gate on `cert_path` / `key_path`. This is the boundary the generator fixtures only exercised end-to-end, so it is where the "server emitted insecure=true" and "reality key on the wrong side" classes of bug get named. | diff --git a/luci-app-homeproxy-pro/tests/fixtures/runtime/trace.golden.txt b/luci-app-homeproxy-pro/tests/fixtures/runtime/trace.golden.txt index 5507cd8aa..29d7705aa 100644 --- a/luci-app-homeproxy-pro/tests/fixtures/runtime/trace.golden.txt +++ b/luci-app-homeproxy-pro/tests/fixtures/runtime/trace.golden.txt @@ -174,6 +174,7 @@ procd_add_jail sing-box-c log procfs procd_add_jail_mount var/run/homeproxy-pro/sing-box-c.json procd_add_jail_mount_rw var/run/homeproxy-pro/sing-box-c.log procd_add_jail_mount etc/homeproxy-pro/ +procd_add_jail_mount_rw etc/homeproxy-pro/cache.db procd_add_jail_mount etc/homeproxy-pro/certs/ procd_add_jail_mount /etc/acme/ procd_add_jail_mount /etc/ssl/ diff --git a/luci-app-homeproxy-pro/tests/ucode/run.sh b/luci-app-homeproxy-pro/tests/ucode/run.sh index e6d1cd88f..c7c29e9f0 100755 --- a/luci-app-homeproxy-pro/tests/ucode/run.sh +++ b/luci-app-homeproxy-pro/tests/ucode/run.sh @@ -354,6 +354,14 @@ echo "== resource blob digest helper (B2) ==" # repository's real resource files against git when the host has it. sh "$ROOT/tests/ucode/test_resource_blob_sha.sh" "$ROOT" "$WORK/resource_blob_sha" || FAILED=1 +echo "== china ip rule-set generator ==" +# The route side's mainland split is decided from a local rule-set generated out +# of china_ip4.txt - the same list the firewall renders its nft set from. One +# malformed entry makes sing-box reject the whole rule-set and the client +# refuses to start, and the list is replaced unattended, so the generator's +# validation and its atomic write are both load-bearing. +sh "$ROOT/tests/ucode/test_china_ip_ruleset.sh" "$ROOT" "$WORK/china_ip_ruleset" || FAILED=1 + echo "== test doubles still match production ==" # The mocks copy isEmpty/decodeBase64Str/parseURL/redactUrl from production and # their headers say to keep them in sync; nothing enforced it, and the fetcher's diff --git a/luci-app-homeproxy-pro/tests/ucode/test_china_ip_ruleset.sh b/luci-app-homeproxy-pro/tests/ucode/test_china_ip_ruleset.sh new file mode 100644 index 000000000..8a4afdbaa --- /dev/null +++ b/luci-app-homeproxy-pro/tests/ucode/test_china_ip_ruleset.sh @@ -0,0 +1,154 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# +# runtime/china_ip_ruleset.uc: the text -> sing-box local rule-set generator +# that keeps the route side and the firewall deciding mainland China from one +# list. +# +# Why this has its own test: sing-box parses the generated file with +# netip.ParsePrefix(), which is strict, and one bad entry makes it reject the +# *whole* rule-set - taking the client's start with it ("initialize router: +# parse rule-set[0]: ... ParseAddr: IPv4 field has value >255", reproduced on +# the target). The source list is downloaded and replaced unattended, so the +# failure would arrive on a router nobody is watching. The cases below are the +# ones that decide whether that can happen: a malformed line must be skipped, +# the file must be replaced atomically (the running instance watches it), and +# an empty or unreadable source must fail rather than install an empty rule-set +# that silently matches nothing. +# +# Usage: sh tests/ucode/test_china_ip_ruleset.sh [workdir] + +set -u + +ROOT="$(cd "${1:-$(dirname "$0")/../..}" && pwd)" +WORK="${2:-/tmp/hp-china-ip-test}" + +if ! command -v ucode > "/dev/null" 2>&1; then + echo "NOT RUN: ucode is not on PATH." + exit 2 +fi + +HELPER="$ROOT/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc" +rm -rf "$WORK" +mkdir -p "$WORK" + +FAILED=0 +CHECKS=0 +FAILURES=0 + +expect() { + # expect + CHECKS=$((CHECKS + 1)) + if [ "$2" = "$3" ]; then + echo "PASS: $1" + else + echo "FAIL: $1 (expected '$3', got '$2')" + FAILED=1 + FAILURES=$((FAILURES + 1)) + fi +} + +generate() { + # generate ; stdout is "N prefixes", status 0/1 + ucode -S "$HELPER" "$1" "$2" 2>"/dev/null" +} + +# --- fixtures --------------------------------------------------------------- + +# A list shaped like the real one: comments, blank lines, valid IPv4 and IPv6, +# and five ways a line can be malformed. +cat > "$WORK/mixed.txt" <<'EOF' +# comment +; also a comment + +1.1.8.0/24 +2.2.2.2/32 +10.0.0.0/8 +2001:db8::/32 +fe80::/10 +999.1.1.1/24 +01.2.3.4/24 +1.1.8.0/33 +fe80::/129 +garbage +1.2.3.4 +EOF + +# Five survive: 1.1.8.0/24, 2.2.2.2/32, 10.0.0.0/8, 2001:db8::/32, fe80::/10. +expect "mixed list: only the valid entries survive" \ + "$(generate "$WORK/mixed.txt" "$WORK/mixed.json")" "5 prefixes" +expect "mixed list: the out-of-range octet is gone" \ + "$(grep -c '999\.1\.1\.1' "$WORK/mixed.json")" "0" +expect "mixed list: the leading-zero address is gone" \ + "$(grep -c '01\.2\.3\.4' "$WORK/mixed.json")" "0" +expect "mixed list: the /33 prefix is gone" \ + "$(grep -c '1\.1\.8\.0/33' "$WORK/mixed.json")" "0" +expect "mixed list: the /129 prefix is gone" \ + "$(grep -c 'fe80::/129' "$WORK/mixed.json")" "0" +expect "mixed list: a bare address is gone" \ + "$(grep -c '"1\.2\.3\.4"' "$WORK/mixed.json")" "0" +expect "mixed list: the valid IPv4 entries stay" \ + "$(grep -c '1\.1\.8\.0/24\|2\.2\.2\.2/32\|10\.0\.0\.0/8' "$WORK/mixed.json")" "3" +expect "mixed list: the valid IPv6 entry stays" \ + "$(grep -c '2001:db8::/32' "$WORK/mixed.json")" "1" + +# The rule-set has to be one `ip_cidr` array: one netipx.IPSet on the sing-box +# side, not N rules to walk per packet. +expect "output is a single ip_cidr rule" \ + "$(grep -c '"ip_cidr"' "$WORK/mixed.json")" "1" +expect "output carries a version" \ + "$(grep -c '"version": 3' "$WORK/mixed.json")" "1" + +# --- the real bundled list -------------------------------------------------- + +# The list this ships with is what the firewall renders its nft set from; a +# generator that mangles it would break both sides at once. +expect "the bundled china_ip4.txt generates" \ + "$(generate "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$WORK/real.json")" "4068 prefixes" +# 8.152.0.0/13 is the range geoip-cn.srs does *not* carry, and the one that +# made segmentfault.com and ctrip.com resolve into the proxy path. +expect "the bundled list carries 8.152.0.0/13" \ + "$(grep -c '8\.152\.0\.0/13' "$WORK/real.json")" "1" + +# --- failure paths ---------------------------------------------------------- + +# An empty source must not install an empty rule-set: the caller would then be +# running a split that matches nothing while looking like it worked. +: > "$WORK/empty.txt" +expect "empty source produces no file" "$(generate "$WORK/empty.txt" "$WORK/empty.json")" "" +ucode -S "$HELPER" "$WORK/empty.txt" "$WORK/empty.json" >/dev/null 2>&1 +expect "empty source exits non-zero" "$?" "1" +expect "empty source wrote nothing" "$(test -e "$WORK/empty.json" && echo yes || echo no)" "no" + +ucode -S "$HELPER" "$WORK/does-not-exist.txt" "$WORK/missing.json" >/dev/null 2>&1 +expect "unreadable source exits non-zero" "$?" "1" +expect "unreadable source wrote nothing" "$(test -e "$WORK/missing.json" && echo yes || echo no)" "no" + +ucode -S "$HELPER" >/dev/null 2>&1 +expect "no arguments exits non-zero" "$?" "1" + +# --- atomicity -------------------------------------------------------------- + +# The running instance watches this path with fswatch, so a partial write would +# be read as a broken rule-set. The generator writes a sibling temp file and +# renames it, which is why no `*.tmp` may survive a successful run. +rm -f "$WORK/real.json" "$WORK/real.json.tmp" +generate "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$WORK/real.json" >"/dev/null" +expect "a successful run leaves no temp file" \ + "$(ls "$WORK"/real.json.tmp 2>/dev/null | wc -l)" "0" +expect "a successful run leaves the rule-set" \ + "$(test -s "$WORK/real.json" && echo yes || echo no)" "yes" + +# A failed run must not damage an existing rule-set either: the destination is +# only touched by the rename. +cp "$WORK/real.json" "$WORK/keep.json" +ucode -S "$HELPER" "$WORK/empty.txt" "$WORK/keep.json" >/dev/null 2>&1 +expect "a failed run leaves the previous rule-set in place" \ + "$(test -s "$WORK/keep.json" && echo yes || echo no)" "yes" +expect "a failed run leaves no temp file behind" \ + "$(ls "$WORK"/keep.json.tmp 2>/dev/null | wc -l)" "0" + +echo +echo "$CHECKS checks, $FAILURES failures" +[ "$FAILED" -eq 0 ] && echo "CHINA IP RULESET TESTS PASSED" +exit "$FAILED" diff --git a/luci-app-homeproxy-pro/tests/ucode/test_dns_proxy_list.sh b/luci-app-homeproxy-pro/tests/ucode/test_dns_proxy_list.sh index 2cdef6cc4..f6b502bb4 100644 --- a/luci-app-homeproxy-pro/tests/ucode/test_dns_proxy_list.sh +++ b/luci-app-homeproxy-pro/tests/ucode/test_dns_proxy_list.sh @@ -68,6 +68,15 @@ stage_case() { printf '%s\n' "$DIRECT_DOMAIN" > "$dir/resources/direct_list.txt" printf '%s\n' "$PROXY_DOMAIN" > "$dir/resources/proxy_list.txt" + # The client config carries a `type: local` rule-set generated from + # china_ip4.txt; sing-box opens that path during `check`, and on a router + # hp_prepare_runtime_files generates it before the config is used. + if ! ucode -S "$ROOT/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc" \ + "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$dir/resources/china_ip4.json" \ + >>"$dir/resources/china_ip4.log" 2>&1; then + printf '{"version":3,"rules":[{"ip_cidr":["192.0.2.0/24"]}]}\n' > "$dir/resources/china_ip4.json" + fi + VALIDATE_DATA="${HP_VALIDATE_DATA:-/sbin/validate_data}" sed -e "s#^export const HP_DIR = '/etc/homeproxy-pro';#export const HP_DIR = '$dir';#" \ -e "s#^export const RUN_DIR = '/var/run/homeproxy-pro';#export const RUN_DIR = '$dir/run';#" \ @@ -113,6 +122,68 @@ stage_case() { return 0 } +# The mode's default policy, asserted as a *pair*. The DNS chain and the +# route chain each end in a fallback (`dns.final`, `route.final`), and they +# have to name the same side: a domain that ends up proxied must be resolved +# by the proxy-path resolver, and one that ends up direct must not be +# resolved through the proxy. The two were literals in different modules with +# nothing tying them together, and the route side applied "unknown goes to the +# proxy" to all four modes - so "Only proxy mainland China" proxied everything +# it was not told to proxy. +check_fallback_pair() { + label="$1" + json="$2" + + case "$label" in + proxy_mainland_china) want_route="direct-out"; want_dns="default-dns" ;; + *) want_route="main-out"; want_dns="main-dns" ;; + esac + + # The two finals sit in different blocks and their relative order is not + # fixed (route.final is emitted before dns.final in the modes whose dns + # block grows, after it in the others), so each is taken from its own + # block: dns.final is the only '"final"' indented by two tabs inside the + # top-level dns object, route.final the only one inside route. + have_dns="$(awk '/^\t"dns": \{/{d=1} d && /^\t\t"final":/{gsub(/.*: "|".*/,""); print; exit}' "$json")" + have_route="$(awk '/^\t"route": \{/{r=1} r && /^\t\t"final":/{gsub(/.*: "|".*/,""); print; exit}' "$json")" + + if [ "$have_route" != "$want_route" ]; then + echo "FAIL: $label: route.final is '$have_route', the mode's policy is '$want_route'" + return 1 + fi + if [ "$have_dns" != "$want_dns" ]; then + echo "FAIL: $label: dns.final is '$have_dns', the mode's policy is '$want_dns'" + return 1 + fi + # Stated as its own property, because the failure it catches is silent: + # if one of the two ever gains a new value, the pair is what breaks. + proxy_route=no; proxy_dns=no + [ "$have_route" = "main-out" ] && proxy_route=yes + [ "$have_dns" = "main-dns" ] && proxy_dns=yes + if [ "$proxy_route" != "$proxy_dns" ]; then + echo "FAIL: $label: route.final ($have_route) and dns.final ($have_dns) disagree on the mode's default" + return 1 + fi + + echo "PASS: $label: route.final=$have_route and dns.final=$have_dns agree" + + # Both mainland modes match destinations against geoip-cn, so both have to + # declare it. proxy_mainland_china reached this point without the + # declaration once and sing-box refused the whole config with + # "initialize rule[3]: rule-set not found: geoip-cn"; the health gate then + # rolled the intercept layer back and the network went unproxied. + case "$label" in + bypass_mainland_china|proxy_mainland_china) + if ! grep -qF '"rule_set": "geoip-cn"' "$json" || ! grep -qF '"tag": "geoip-cn"' "$json"; then + echo "FAIL: $label: the route rule matches geoip-cn but the rule-set is not declared" + return 1 + fi + ;; + esac + + return 0 +} + # The rule_set assertions, shared by every case: the list reaches the config, # the DNS half resolves through main-dns ahead of the SVCB/HTTPS reject, and # direct-domain keeps its precedence. @@ -232,6 +303,7 @@ for mode in bypass_mainland_china global gfwlist proxy_mainland_china; do else FAILED=1 fi + check_fallback_pair "$mode" "$dir/run/sing-box-c.json" else FAILED=1 fi diff --git a/luci-app-homeproxy-pro/tests/ucode/test_generators.sh b/luci-app-homeproxy-pro/tests/ucode/test_generators.sh index d1b3921e6..87cf6b6a9 100755 --- a/luci-app-homeproxy-pro/tests/ucode/test_generators.sh +++ b/luci-app-homeproxy-pro/tests/ucode/test_generators.sh @@ -49,6 +49,19 @@ run_case() { : > "$dir/resources/direct_list.txt" : > "$dir/resources/proxy_list.txt" + # The client config now carries a `type: local` rule-set generated from + # china_ip4.txt (the same list the firewall renders its nft set from, so + # both sides decide mainland-China from one source). sing-box opens that + # path during `check`, so the staged tree has to have it; on a router + # hp_prepare_runtime_files generates it before the config is used. + if ! ucode -S "$ROOT/root/etc/homeproxy-pro/scripts/runtime/china_ip_ruleset.uc" \ + "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$dir/resources/china_ip4.json" \ + >>"$dir/resources/china_ip4.log" 2>&1; then + # Most fixtures do not exercise the route side; an empty rule-set + # keeps `sing-box check` happy without inventing data. + printf '{"version":3,"rules":[{"ip_cidr":["192.0.2.0/24"]}]}\n' > "$dir/resources/china_ip4.json" + fi + if grep -q "__RULESET_DIR__" "$fixture"; then # The fixture needs a real local rule-set on disk. The path must # live under /tmp/homeproxy_* (validateHomeProxyPath() in @@ -277,6 +290,34 @@ if ! grep -q '"detour": "main-out"' "$WORK/client/run/sing-box-c.json"; then FAILED=1 fi +# The mainland split must be decided from the same list the firewall renders +# its nft set from. geoip-cn.srs (upstream) and china_ip4.txt (ours) disagree +# on real ranges - the bundled list carries 8.152.0.0/13, geoip-cn.srs does +# not - so a destination in that range passes the firewall as "not mainland" +# and must still be sent direct by the route rule. The local rule-set is +# generated from china_ip4.txt by runtime/china_ip_ruleset.uc and watched with +# fswatch, so a resource update needs no restart. +if ! grep -q '"path": "'"$WORK"'/client/resources/china_ip4.json"' "$WORK/client/run/sing-box-c.json"; then + echo "FAIL: client: the mainland route rule does not read the generated china_ip4 rule-set" + FAILED=1 +fi +if ! grep -q '"tag": "china-ip"' "$WORK/client/run/sing-box-c.json"; then + echo "FAIL: client: the local china-ip rule-set is missing from the generated config" + FAILED=1 +fi +# ... and it has to be a rule the route layer actually consults, not a +# declaration sing-box loads and never matches. +if ! grep -A2 '"rule_set": "china-ip"' "$WORK/client/run/sing-box-c.json" | grep -q '"outbound": "direct-out"'; then + echo "FAIL: client: no route rule sends the china-ip rule-set to direct-out" + FAILED=1 +fi +# The generated file itself must hold the list, or the node would run with a +# split that matches nothing. +if ! grep -q '8\.152\.0\.0/13' "$WORK/client/resources/china_ip4.json"; then + echo "FAIL: client: the generated china_ip4 rule-set does not carry the bundled list" + FAILED=1 +fi + # --- the product default proxy mode -------------------------------------- # # client.uci runs `proxy_mode 'tun'`, where self_mark is empty and no outbound diff --git a/luci-app-qosify/po/cs/qosify.po b/luci-app-qosify/po/cs/qosify.po index bd64cd021..f20a587a3 100644 --- a/luci-app-qosify/po/cs/qosify.po +++ b/luci-app-qosify/po/cs/qosify.po @@ -3,94 +3,108 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Language: cs\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: Pavel Borecki \n" +"Last-Translator: Hannu Nyman \n" "Language-Team: Czech \n" "Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n" -"PO-Revision-Date: 2026-08-22 12:51+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-29 18:07+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" msgid_plural "%d interfaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d rozhraní" +msgstr[1] "%d rozhraní" +msgstr[2] "%d rozhraní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d pravidlo" +msgstr[1] "%d pravidla" +msgstr[2] "%d pravidel" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" msgid_plural "%d sections" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d sekce" +msgstr[1] "%d sekce" +msgstr[2] "%d sekcí" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:682 msgid "%s (current)" -msgstr "" +msgstr "%s (stávající)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 msgid "%s (from bandwidth)" -msgstr "" +msgstr "%s (z šířky pásma)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2085 msgid "" "%s and %s are replaced with the templates shipped by the qosify package, and " "shaping is left disabled." msgstr "" +"%s a %s jsou nahrazeny šablonami dodávanými s balíčkem qosify a omezování " +"rychlosti je ponecháno vypnuté." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1809 msgid "" "%s came back empty although it is %d bytes on disk — refusing to overwrite it" msgstr "" +"%s přišlo nazpět prázdné i když na disku má %d bajtů – odmítá se ho přepsat" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2346 msgid "%s changed on disk — your unsaved edits are still in the editor." msgstr "" +"%s změněno na disku – vámi provedené neuložené úpravy se ale pořád ještě " +"nacházejí v editoru." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2249 msgid "" "%s could not be read — the editor is left empty and will not be saved over " "it." msgstr "" +"%s nebylo možné číst – editor je ponechán prázdný a nebude uložen přes něj." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1833 msgid "" "%s has changed since this editor was loaded. Saving now discards those " "changes." msgstr "" +"%s má změny od okamžiku, kdy byl tento editor načten. Uložení nyní tamty " +"změny zahodí." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1864 msgid "" "%s is %d bytes on disk but was never loaded into the editor — refusing to " "truncate it. Reload the page first." msgstr "" +"%s má na disku %d bajtů, ale nikdy nebylo načteno do editoru – odmítá se " +"provést zkrácení. Nejprve stránku znovu načtěte." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:364 msgid "%s is a list in this section — edit %s directly" -msgstr "" +msgstr "%s je seznam v této sekci – upravte %s přímo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1656 msgid "" "%s is not in the defaults list — qosify does not load it, so the Rules tab " "has no effect" msgstr "" +"%s není na seznamu výchozích – qosify ho nenačte, takže záložka Pravidla " +"nemá žádný efekt" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:286 msgid "" "%s is set to \"%s\" — qosify converts it with atoi(), so anything but a non-" "zero number means off" msgstr "" +"%s je nastavené na „%s“ – qosify ho převede pomocí atoi(), takže cokoli " +"kromě nenulového čísla znamená vypnuto" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:750 msgid "%s quick settings" -msgstr "" +msgstr "%s rychlá nastavení" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2069 msgid "%s uploaded, qosify reloaded." @@ -98,11 +112,11 @@ msgstr "%s nahráno – qosify znovunačteno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2103 msgid "%s was not written: %s" -msgstr "" +msgstr "%s nebylo zapsáno: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2106 msgid "%s was reset but %s was not written: %s" -msgstr "" +msgstr "%s bylo resetováno, ale %s nebylo zapsáno: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1945 msgid "%s, applied (QoS disabled)." @@ -112,6 +126,8 @@ msgstr "%s, uplatněno (QoS zakázáno)." msgid "" "%s, applied — qosify did not answer on ubus, so shaping could not be checked." msgstr "" +"%s, uplatněno – qosify neodpovědělo na ubus, takže omezování provozu nebylo " +"možné zkontrolovat." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1947 msgid "%s, applied." @@ -120,31 +136,39 @@ msgstr "%s, uplatněno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:459 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:468 msgid "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify ignores it" -msgstr "" +msgstr "%s: %s „%s“ není třída, kódový bod nebo 0-63 – qosify ho ignoruje" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:456 msgid "" "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify rejects the whole " "config and interface changes are not applied" msgstr "" +"%s: %s „%s“ není třída, kódový bod nebo 0-63 – qosify odmítne celé nastavení " +"a změny pro rozhraní nejsou uplatněny" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:465 msgid "" "%s: %s \"%s\" is not a codepoint or 0-63 — qosify drops this class and the " "rules using it" msgstr "" +"%s: %s „%s“ není kódový bod nebo 0-63 – qosify zahodí tuto třídu a pravidla, " +"které ji používají" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:448 msgid "" "%s: %s cannot be checked — write it as one plain or fully quoted value, with " "no backslash" msgstr "" +"%s: „%s“ nebylo možné zkontrolovat – zapište to jako jednu holou nebo plně " +"citovanou hodnotu, bez jakýchkoli zpětných lomítek" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:451 msgid "" "%s: %s contains shell metacharacters — qosify runs the tc command with sh -c " "as root, so they would break it or be executed" msgstr "" +"%s: %s obsahuje metaznaky shellu – qosify spustí příkaz tc s sh - c jako " +"root, takže by to rozbili nebo budou vykonány" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "(alias)" @@ -152,7 +176,7 @@ msgstr "(alternativní název)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "(this qosify build has no NQB)" -msgstr "" +msgstr "(toto sestavení qosify nemá žádné NQB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2185 msgid "A config defaults section already exists." @@ -160,7 +184,7 @@ msgstr "Sekce výchozích nastavení už existuje." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2183 msgid "A section name may only contain letters, digits and underscores." -msgstr "" +msgstr "Název sekce může obsahovat pouze písmena, číslice a podtržítka." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:856 msgid "Active" @@ -173,19 +197,19 @@ msgstr "Přidat" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:85 msgid "Adds atm, noatm or ptm when overhead_type is manual" -msgstr "" +msgstr "Pokud overhead_type je manual (ruční), přidá atm, noatm nebo ptm" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:87 msgid "Adds ether-vlan once per level (1 or 2)" -msgstr "" +msgstr "Přidá ether-vlan jednou na každou úroveň (1 nebo 2)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:86 msgid "Adds mpu " -msgstr "" +msgstr "Přidá mpu " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:84 msgid "Adds overhead when overhead_type is manual" -msgstr "" +msgstr "Když overhead_type je manual (ruční), přidá overhead " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:608 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:737 @@ -194,11 +218,11 @@ msgstr "Pokročilé" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "An empty %s stops all shaping. Continue?" -msgstr "" +msgstr "Prázdné %s zastaví veškeré omezování provozu. Pokračovat?" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:726 msgid "Automatic download rate" -msgstr "" +msgstr "Automatická rychlost stahování" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:893 msgid "Autostart" @@ -206,7 +230,7 @@ msgstr "Automatické spouštění" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:924 msgid "Autostart state unknown — rpcd did not answer" -msgstr "" +msgstr "Stav automatického spouštění neznámý – rpcd neodpovědělo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" @@ -214,17 +238,19 @@ msgstr "K dispozici" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" -msgstr "" +msgstr "Záloha" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:76 msgid "" "Bandwidth for both directions, where bandwidth_up or bandwidth_down is not " "set" msgstr "" +"Šířka pásma pro oba směry, kde bandwitdth_up nebo bandwidth_down není " +"nastaveno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:716 msgid "Basic" -msgstr "" +msgstr "Základní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:224 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2029 @@ -233,57 +259,59 @@ msgstr "Binární obsah odmítnut" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:79 msgid "CAKE diffserv mode" -msgstr "" +msgstr "CAKE diffserv režim" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:89 msgid "CAKE egress options" -msgstr "" +msgstr "CAKE egress předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "CAKE egress options, space separated." -msgstr "" +msgstr "CAKE egress předvolby (oddělované mezerou)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:88 msgid "CAKE ingress options" -msgstr "" +msgstr "CAKE ingress předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "CAKE ingress options, space separated." -msgstr "" +msgstr "CAKE ingress předvolby (oddělované mezerou)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:90 msgid "CAKE options for ingress + egress" -msgstr "" +msgstr "CAKE předvolby pro ingress + egress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:83 msgid "" "CAKE overhead keyword added to options; manual uses overhead and " "overhead_encap" msgstr "" +"CAKE overhead klíčová slova přidaná k předvolbám; manual použije overhead a " +"overhead_encap" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "CAKE overhead keyword. Use none if unsure." -msgstr "" +msgstr "CAKE overhead klíčové slovo. Pokud nevíte, použijte none." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "Zrušit" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" -msgstr "" +msgstr "Zkontrolovat zařízení" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1193 msgid "Choose file…" -msgstr "" +msgstr "Zvolte soubor…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1114 msgid "Classes" -msgstr "" +msgstr "Třídy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1737 msgid "Cleanup exited with code %d" -msgstr "" +msgstr "Vyčistit ukončené s kódem %d" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 @@ -293,12 +321,12 @@ msgstr "Vyčistit" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1869 msgid "Clear configuration" -msgstr "" +msgstr "Vyčistit nastavení" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "Clear editor" -msgstr "" +msgstr "Vyčistit editor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:929 msgid "Click to disable autostart" @@ -310,7 +338,7 @@ msgstr "Kliknutím povolíte automatické spouštění" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:740 msgid "Common CAKE options" -msgstr "" +msgstr "Běžné CAKE předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:604 msgid "Config" @@ -322,7 +350,7 @@ msgstr "Nastavení vyčištěno, qosify zastaveno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1894 msgid "Config cleared." -msgstr "" +msgstr "Nastavení vyčištěno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1915 msgid "Config saved" @@ -335,28 +363,28 @@ msgstr "Nastavení: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:566 msgid "Continue" -msgstr "" +msgstr "Pokračovat" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1245 msgid "Could not read %s: %s" -msgstr "" +msgstr "Nebylo možné číst %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:607 msgid "Counters" -msgstr "" +msgstr "Čítače" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1627 msgid "DNS Entries" -msgstr "" +msgstr "DNS položky" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d of %d)" -msgstr "" +msgstr "DNS položky (%d z %d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d)" -msgstr "" +msgstr "DNS položky (%d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "" @@ -365,51 +393,56 @@ msgid "" "accepted too, and any dscp_* value may also name a class. Prefix with + to " "override only when the DSCP field is zero." msgstr "" +"DSCP kódové body: CS0-CS7, AF11-AF43, EF, VA, NQB, LE, DF (NQB potřebuje " +"verzi qosify nejméně z června 2026, kterou 24.10 a 25.12 ještě neobsahuje). " +"Holá hodnota od 0 po 63 je také přijímána a jakákoli hodnota dscp_* může " +"také jmenovat třídu. Pokud chcete přepsat pouze pokud je kolonka DSCP nula, " +"přidejte před + (plus)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:63 msgid "DSCP value for ICMP packets" -msgstr "" +msgstr "DSCP hodnota pro ICMP pakety" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:65 msgid "DSCP value for bulk-marked packets" -msgstr "" +msgstr "DSCP hodnota pro hromadně označené pakety" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:71 msgid "DSCP value for egress" -msgstr "" +msgstr "DSCP hodnota pro egress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:70 msgid "DSCP value for ingress" -msgstr "" +msgstr "DSCP hodnota pro ingress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:69 msgid "DSCP value for ingress and egress, where they are not set" -msgstr "" +msgstr "DSCP hodnota pro ingress a egress, kde nejsou nastavené" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:64 msgid "DSCP value for priority-marked packets" -msgstr "" +msgstr "DSCP hodnota pro pakety označené jako prioritní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "DSCP values" -msgstr "" +msgstr "DSCP hodnoty" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:61 msgid "Default DSCP value for TCP packets" -msgstr "" +msgstr "Výchozí DSCP hodnota pro TCP pakety" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:62 msgid "Default DSCP value for UDP packets" -msgstr "" +msgstr "Výchozí DSCP hodnota pro UDP pakety" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:60 msgid "Default timeout for dynamically added entries" -msgstr "" +msgstr "Výchozí časový limit pro dynamicky přidané položky" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1217 msgid "Defaults" -msgstr "" +msgstr "Výchozí" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 msgid "" @@ -427,15 +460,15 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "Zařízení" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." -msgstr "" +msgstr "Kontrola zařízení dokončena." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1714 msgid "Device check failed: %s" -msgstr "" +msgstr "Kontrola zařízení se nezdařila: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:859 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 @@ -445,11 +478,13 @@ msgstr "Zakázáno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:75 msgid "Downlink bandwidth (same format as tc)" -msgstr "" +msgstr "Šířka downlink pásma (stejný formát jako tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Downlink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Šířka downlink pásma, stejný formát jako tc. Nastavte kousek pod rychlost " +"linky." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1247 @@ -458,15 +493,15 @@ msgstr "Stáhnout" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Download bandwidth" -msgstr "" +msgstr "Šířka pásma stahování" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:724 msgid "Download shaping" -msgstr "" +msgstr "Omezování rychlosti stahování" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1197 msgid "Download the current files from the router." -msgstr "" +msgstr "Stáhnout si stávající soubory ze směrovače." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "" @@ -474,10 +509,14 @@ msgid "" "raw value, a codepoint like CS0, or a class name. DNS entries are compared " "in the order in which they are specified, using the first matching entry." msgstr "" +"Každý řádek, který má kolonky oddělované dvěma prázdnými znaky, odpovídá " +"dscp. dscp může být holá hodnota, kódový bod jako např. CS0 nebo název " +"třídy. DNS položky jsou porovnávány v pořadí ve kterém jsou uvedeny, pomocí " +"první odpovídající položky." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "Egress CAKE options" -msgstr "" +msgstr "Egress CAKE předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2020 msgid "Empty file" @@ -487,31 +526,35 @@ msgstr "Vyprázdnit soubor" msgid "" "Empty the config editor? Nothing is written until you click Save & Apply." msgstr "" +"Vyprázdnit editor nastavení? Nic není zapsáno dokud nekliknete na „Uložit a " +"použít“." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "" "Empty the rules editor? Nothing is written until you click Save & Apply." msgstr "" +"Vyprázdnit editor pravidel? Nic není zapsáno dokud nekliknete na „Uložit a " +"použít“." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:80 msgid "Enable CAKE NAT host detection via conntrack" -msgstr "" +msgstr "Zapnout CAKE zjišťování NAT hostitele prostřednictvím conntrack" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:82 msgid "Enable CAKE automatic rate estimation for ingress" -msgstr "" +msgstr "Zapnout CAKE automatické odhadování rychlosti pro ingress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:81 msgid "Enable CAKE host isolation" -msgstr "" +msgstr "Zapnout CAKE izolování hostitelů" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:78 msgid "Enable egress shaping" -msgstr "" +msgstr "Zapnout omezování rychlosti egress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:77 msgid "Enable ingress shaping" -msgstr "" +msgstr "Zapnout omezování rychlosti ingress" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 @@ -528,11 +571,11 @@ msgstr "Povoleno – neomezující provoz (zkontrolujte nastavení)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Encapsulation overhead" -msgstr "" +msgstr "Režie zapouzdřování" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2182 msgid "Enter a section name." -msgstr "" +msgstr "Zadejte název sekce." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2156 msgid "Enter a single IPv4 address (qosify does not accept CIDR)." @@ -541,7 +584,7 @@ msgstr "Zadejte jedinou IPv4 adresu (qosify nepřijímá CIDR)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2159 msgid "" "Enter a single IPv6 address (qosify does not accept CIDR or a %zone suffix)." -msgstr "" +msgstr "Zadejte jednu IPv6 adresu (qosify nepřijímá CIDR nebo příponu %zone)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2141 msgid "Enter a value." @@ -549,7 +592,7 @@ msgstr "Zadejte hodnotu." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 msgid "Entries" -msgstr "" +msgstr "Položky" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1848 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1961 @@ -565,6 +608,8 @@ msgid "" "Error: invalid characters in bandwidth or options fields. Use alphanumeric, " "spaces, hyphens, dots, colons only." msgstr "" +"Chyba: neplatné znaky v šířce pásma nebo kolonkách předvoleb. Používejte " +"pouze písmena a číslice, mezery, spojovníky, tečky a dvojtečky." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1798 msgid "Error: name must be a device or interface name" @@ -576,7 +621,7 @@ msgstr "Chyba: je třeba, aby režie bylo celé číslo bajtů" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1768 msgid "Error: overhead_mpu must be a whole number of bytes" -msgstr "" +msgstr "Chyba: je třeba, aby overhead_mpu bylo celé číslo počtu bajtů" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2070 msgid "Errors:" @@ -586,11 +631,11 @@ msgstr "Chyby:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "File" -msgstr "" +msgstr "Soubor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1832 msgid "File changed on disk" -msgstr "" +msgstr "Soubor změněn na disku" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2021 msgid "File too large (max 64KB)" @@ -598,7 +643,7 @@ msgstr "Soubor příliš velký (nejvýše 64KB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:667 msgid "Files" -msgstr "" +msgstr "Soubory" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Found (empty or invalid)" @@ -610,78 +655,82 @@ msgstr "Udělit přístup k LuCI aplikaci qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:728 msgid "Host isolation" -msgstr "" +msgstr "Izolace hostitele" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1169 msgid "IPv4 address, e.g. 1.1.1.1" -msgstr "" +msgstr "IPv4 adresa, např. 1.1.1.1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1170 msgid "IPv6 address, e.g. ff01::1" -msgstr "" +msgstr "IPv6 adresa, např. ff01::1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "Ingress CAKE options" -msgstr "" +msgstr "Ingress CAKE předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Interface" -msgstr "" +msgstr "Rozhraní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:741 msgid "Invalid CAKE options can stop qosify starting." -msgstr "" +msgstr "Neplatné CAKE předvolby mohou zastavit spouštění qosify." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1173 msgid "Like dns:... but only matches cname entries" -msgstr "" +msgstr "Jako dns:… ale odpovídá pouze cname položkám" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:228 msgid "" "Line %d is longer than 1023 characters — the rule loader reads fixed-size " "lines and would split it, comment included" msgstr "" +"Řádek %d je delší než 1023 znaků – komponenta pro načítání pravidel čte " +"řádky pevné délky rozdělila by ho, včetně komentáře" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:59 msgid "List of files with port/IP/host mappings" -msgstr "" +msgstr "Seznam souborů s mapováními portu/IP/hostitele" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 msgid "Loading..." -msgstr "" +msgstr "Načítání…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1212 msgid "Maintenance" -msgstr "" +msgstr "Údržba" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Manual overhead" -msgstr "" +msgstr "Ruční režie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "Mapping file syntax" -msgstr "" +msgstr "Syntaxe souboru s mapováními" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1692 msgid "Mapping files reloaded." -msgstr "" +msgstr "Soubor s mapováními znovu načten." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:434 msgid "" "Match not loaded by qosify on line %s — ports 1-65534, one IPv4/IPv6 address " "(no CIDR or %%zone), or dns:, dns_c:" msgstr "" +"Shoda nenačtena qosify na řádku %s – porty 1-65534, jedna IPv4/IPv6 adresa " +"(žádný CIDR záznam nebo %%%zone), nebo dns:,dns_c:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:66 msgid "Maximum average packet length for marking a flow as priority" -msgstr "" +msgstr "Nejvyšší průměrná délka paketu pro označení toku jako přednostního" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Minimum packet unit (MPU)" -msgstr "" +msgstr "Minimální jednotka paketu (MPU)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 @@ -691,37 +740,39 @@ msgstr "Chybí" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Modified" -msgstr "" +msgstr "Změněno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:433 msgid "" "More than two fields on line %s — qosify reads the rest of the line as the " "DSCP value and skips it" msgstr "" +"Více než dvě kolonky na řádku %s – qosify čte zbytek řádku jako DSCP hodnotu " +"a přeskakuje to" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:727 msgid "NAT awareness" -msgstr "" +msgstr "Povědomí o NAT" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Netdev to enable QoS on. Required." -msgstr "" +msgstr "Netdev na kterém zapnout QoS. Vyžadováno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No CAKE tin statistics." -msgstr "" +msgstr "Žádné CAKE tin statistiky." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1628 msgid "No DNS entries." -msgstr "" +msgstr "Žádné DNS záznamy." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:432 msgid "No DSCP target on line %s — qosify skips single-field lines" -msgstr "" +msgstr "Žádný DSCP cíl na řádku %s – qosify přeskočí řádky s jedinou kolonkou" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1107 msgid "No classes defined in %s" -msgstr "" +msgstr "V %s nejsou definovány žádné třídy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2142 msgid "No classes defined. Add classes in the Config tab first." @@ -730,7 +781,7 @@ msgstr "Nedefinovány žádné třídy. Nejprve na kartě Nastavení nějaké p #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1191 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1192 msgid "No file selected" -msgstr "" +msgstr "Nevybrán žádný soubor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2006 msgid "No files selected." @@ -738,11 +789,11 @@ msgstr "Nevybrány žádné soubory." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No output." -msgstr "" +msgstr "Žádný výstup." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1568 msgid "No per-class counters." -msgstr "" +msgstr "Žádné čítače pro jednotlivé třídy." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2154 msgid "No spaces or # allowed in patterns or addresses." @@ -764,17 +815,19 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:67 msgid "Number of packets per second to trigger bulk flow detection" -msgstr "" +msgstr "Počet paketů za sekundu pro spuštění dávkového zjišťování toku" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1161 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1174 msgid "Only override the DSCP value if it is zero" -msgstr "" +msgstr "Hodnotu DSCP přepisovat pouze pokud je nula" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:704 msgid "" "Only sent with host isolation on — add nat to common CAKE options to force it" msgstr "" +"Posílat pouze se zapnutou izolací hostitele – pokud chcete vynutit, přidejte " +"k běžným CAKE předvolbám nat" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1017 msgid "Options" @@ -782,11 +835,11 @@ msgstr "Předvolby" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:730 msgid "Overhead" -msgstr "" +msgstr "Režie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "Overhead preset" -msgstr "" +msgstr "Přednastavení režie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:603 msgid "Overview" @@ -794,17 +847,20 @@ msgstr "Přehled" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1834 msgid "Overwrite" -msgstr "" +msgstr "Přepsat" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2007 msgid "Overwrite config files" -msgstr "" +msgstr "Přepsat soubory s nastaveními" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1172 msgid "" "POSIX.2 extended regular expression for matching hostnames. Only works if " "dns lookups are passed to qosify via the add_dns_host ubus call." msgstr "" +"POSIX.2 rozšířilo regulární výraz pro odpovídající názvy hostitelů. Funguje " +"pouze pokud jsou dns vyhledávání předávána do qosify prostřednictvím ubus " +"volání add_dns_host." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2150 msgid "Port must be 1-65534 (qosify rejects 65535)." @@ -813,7 +869,7 @@ msgstr "Je třeba, aby port byl 1-65534 (qosify odmítne 65535)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2149 msgid "Port must be a number or a range (4500, 5060-5061)." -msgstr "" +msgstr "Je třeba, aby port bylo číslo nebo rozsah (4500, 5060-5061)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "QoS Enabled" @@ -821,15 +877,15 @@ msgstr "QoS povoleno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:721 msgid "Queueing mode" -msgstr "" +msgstr "Režim zařazování do fronty" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1163 msgid "Quick Add" -msgstr "" +msgstr "Rychlé přidání" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1016 msgid "Quick Add: %s" -msgstr "" +msgstr "Rychlé přidání: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2153 msgid "Range start must not exceed end." @@ -837,19 +893,19 @@ msgstr "Je třeba, aby začátek rozsahu nebyl vyšší než jeho konec." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1213 msgid "Re-check devices" -msgstr "" +msgstr "Znovu zkontrolovat zařízení" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1707 msgid "Re-checking devices..." -msgstr "" +msgstr "Opětovná kontrola zařízení…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:768 msgid "Re-read the mapping files only" -msgstr "" +msgstr "Znovu načíst pouze soubory s mapováním" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1690 msgid "Re-reading the mapping files..." -msgstr "" +msgstr "Opětovné načítání souborů s mapováním…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1215 msgid "" @@ -858,6 +914,10 @@ msgid "" "is stopped. Nothing is reported back by the call — the result shows in the " "Service table on the Overview tab." msgstr "" +"Znovu spustit průchod zařízení procesu služby samotného: je znovu vyhledána " +"každá sekce shaped. Taková, které zařízení nyní existuje je spuštěna a " +"taková, pro které už ne naopak zastavena. Zpět voláním není hlášeno nic – " +"výsledek se ukáže v tabulce Služby na kartě Přehled." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2024 msgid "Read error" @@ -869,11 +929,11 @@ msgstr "Načítání a ověřování souborů…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1681 msgid "Reading tc output..." -msgstr "" +msgstr "Čtení výstupu tc…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1019 msgid "Reference" -msgstr "" +msgstr "Reference" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload" @@ -881,20 +941,20 @@ msgstr "Znovunačíst" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload Rules" -msgstr "" +msgstr "Znovunačíst pravidla" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1695 msgid "Reload failed: %s" -msgstr "" +msgstr "Znovunačtení se nezdařilo: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "Requires write access." -msgstr "" +msgstr "Vyžaduje přístup pro zápis." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1219 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2086 msgid "Reset" -msgstr "" +msgstr "Reset" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2120 msgid "Reset failed: %s" @@ -902,7 +962,7 @@ msgstr "Resetování se nezdařilo: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2084 msgid "Reset to defaults" -msgstr "" +msgstr "Vrátit na výchozí" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2116 msgid "Reset to defaults, applied." @@ -918,11 +978,11 @@ msgstr "Restart" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1203 msgid "Restore" -msgstr "" +msgstr "Obnovit" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1218 msgid "Restore qosify defaults" -msgstr "" +msgstr "Obnovit výchozí pro qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2095 msgid "Restoring defaults..." @@ -930,7 +990,7 @@ msgstr "Obnovování výchozích…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:605 msgid "Rules" -msgstr "" +msgstr "Pravidla" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1976 msgid "Rules saved" @@ -951,7 +1011,7 @@ msgstr "Spuštěné – provoz neomezující" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:867 msgid "Running — Shaping Unknown" -msgstr "" +msgstr "Spuštěné – omezování rychlosti neznámé" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:753 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1147 @@ -984,6 +1044,9 @@ msgid "" "Section name is the class name that rules and dscp_* values refer to. " "qosify.init reads config alias the same way as config class." msgstr "" +"Název sekce je názvem třídy, která ovládá a odkazuje na dscp_* hodnoty. " +"qosify.init čte alternativní názvy nastavení stejným způsobem, jako třídy " +"nastavení." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1724 msgid "Sending %s to qosify..." @@ -991,23 +1054,23 @@ msgstr "Odesílání %s do qosify…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Sent to CAKE as atm, noatm or ptm." -msgstr "" +msgstr "Odeslat do CAKE jako atm, noatm nebo ptm." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "Sent to CAKE as ether-vlan, once per tag." -msgstr "" +msgstr "Odeslat do CAKE jako ether-vlan (jednou na štítek)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Sent to CAKE as mpu, in bytes." -msgstr "" +msgstr "Odesláno do CAKE jako mpu (v bajtech)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Sent to CAKE as overhead, in bytes." -msgstr "" +msgstr "Odesláno do CAKE jako overhead (v bajtech)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:663 msgid "Service" -msgstr "" +msgstr "Služba" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1745 msgid "Service action failed: %s" @@ -1020,16 +1083,16 @@ msgstr "Nastavení uložena" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:723 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:894 msgid "Shaping" -msgstr "" +msgstr "Omezování rychlosti" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "Velikost" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" -msgstr "" +msgstr "Přeskočit tento výběr" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:764 msgid "Start" @@ -1043,7 +1106,7 @@ msgstr "Stav" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:855 msgid "Status Unknown" -msgstr "" +msgstr "Stav neznámý" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:766 msgid "Stop" @@ -1051,40 +1114,44 @@ msgstr "Zastavit" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1167 msgid "TCP single port, or range from to " -msgstr "" +msgstr "TCP jediný port nebo rozsah od po " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1680 msgid "The detailed tc output needs write access to this page." -msgstr "" +msgstr "Podrobný výstup z tc vyžaduje oprávnění k zápisu na tuto stránku." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:590 msgid "" "The qosify UCI configuration could not be loaded — class and interface lists " "may be incomplete." msgstr "" +"UCI nastavení pro qosify nebylo možné načíst – je možné, že seznamy tříd a " +"rozhraní nebudou úplné." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1204 msgid "" "The selected files replace the ones on the router and qosify is reloaded." -msgstr "" +msgstr "Vybrané soubory nahradí ty na směrovači a qosify bude načteno znovu." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2008 msgid "" "The selected files replace the ones on the router and qosify is reloaded. " "Download a backup from this tab first if you need one." msgstr "" +"Vybrané soubory nahradí ty na směrovači a qosify bude načteno znovu. Pokud " +"ji potřebujete, nejprve si z této karty stáhněte zálohu." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:68 msgid "Time below bulk_trigger_pps threshold until a bulk flow mark is removed" -msgstr "" +msgstr "Čas pod prahem bulk_trigger_pps dokud není odebrána dávkového toku" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 msgid "Traffic by CAKE Tin" -msgstr "" +msgstr "Provoz podle CAKE Tin" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1401 msgid "Traffic by Class" -msgstr "" +msgstr "Provoz podle tříd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:596 msgid "Traffic shaping and DSCP classification via qosify" @@ -1092,13 +1159,13 @@ msgstr "Omezování provozu a DSCP rozřazování prostřednictvím qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1168 msgid "UDP single port, or range from to " -msgstr "" +msgstr "UDP jediný port nebo rozsah od po " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:864 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:866 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:925 msgid "Unknown" -msgstr "" +msgstr "Neznámé" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "Unknown class/DSCP target: %s" @@ -1106,31 +1173,33 @@ msgstr "Neznámá třída / DSCP cíl: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "Unticked sets disabled 1 and qosify skips this section." -msgstr "" +msgstr "Nezaškrtnuté nastaví disabled (na) 1 a qosify tuto sekci přeskočí." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:74 msgid "Uplink bandwidth (same format as tc)" -msgstr "" +msgstr "Šířka uplink pásma (stejný formát jako tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Uplink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Šířka uplink pásma (stejný formát jako tc). Nastavte mírně pod rychlost " +"linky." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "Upload" -msgstr "" +msgstr "Nahrát" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1210 msgid "Upload & Apply" -msgstr "" +msgstr "Nahrát a použít" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2009 msgid "Upload and apply" -msgstr "" +msgstr "Nahrát a použít" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Upload bandwidth" -msgstr "" +msgstr "Šířka pásma odesílání" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2061 msgid "Upload error: %s" @@ -1142,7 +1211,7 @@ msgstr "Nahrání se nezdařilo: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:725 msgid "Upload shaping" -msgstr "" +msgstr "Omezování rychlosti odesílání" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2035 msgid "Uploading" @@ -1150,11 +1219,11 @@ msgstr "Nahrávání" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:892 msgid "Uptime" -msgstr "" +msgstr "Doba chodu" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "VLAN tags" -msgstr "" +msgstr "VLAN štítky" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Valid" @@ -1172,7 +1241,7 @@ msgstr "Pracující" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "Write empty file" -msgstr "" +msgstr "Zapsat prázdný soubor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1906 msgid "Writing config and reloading qosify..." @@ -1187,42 +1256,52 @@ msgid "" "You have read-only access to this page, so editing and service control are " "disabled." msgstr "" +"K této stránce máte přístup pouze pro čtení, takže upravování a ovládání " +"služby je vypnuté." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "active" -msgstr "" +msgstr "aktivní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1767 msgid "" "bandwidth_down does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_down se nejeví být rychlostí pro tc (100mbit, 12MBps, unlimited) – " +"předává se ale i tak" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1766 msgid "" "bandwidth_up does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_up se nejeví být rychlostí pro tc (100mbit, 12MBps, unlimited) – " +"předává se ale i tak" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1012 msgid "" "config device takes the same options, with name set to a netdev. nat " "defaults to 1 for interfaces and 0 for devices." msgstr "" +"nastavení zařízení přijímá stejné předvolby, s názvem nastaveným na netdev. " +"nat je ve výchozím stavu 1 pro rozhraní a 0 pro zařízení." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "device %s" -msgstr "" +msgstr "zařízení %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "device: %s, ingress: %s, egress: %s" -msgstr "" +msgstr "zařízení: %s, ingress: %s, egress: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:289 msgid "" "disabled is set to \"%s\" — config_get_bool does not recognise that, so the " "section stays enabled" msgstr "" +"disabled je nastavené na \"%s\" – config_get_bool toto nerozpoznává, takže " +"sekce zůstává povolená" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 @@ -1232,23 +1311,23 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2129 msgid "e.g. %s" -msgstr "" +msgstr "např. %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1171 msgid "fnmatch() pattern supporting * and ? as wildcard characters" -msgstr "" +msgstr "fnmatch() vzorec podporující * a ? jako zástupné znaky" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1613 msgid "get_stats did not answer." -msgstr "" +msgstr "get_stats neodpovědělo." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "inactive" -msgstr "" +msgstr "neaktivní" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "ingress %s, egress %s" -msgstr "" +msgstr "ingress %s, egress %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:282 msgid "ingress and egress are both 0 — nothing is shaped" @@ -1256,11 +1335,11 @@ msgstr "vstup a výstup je obojí 0 – nic není omezováno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "interface %s" -msgstr "" +msgstr "rozhraní %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1155 msgid "match" -msgstr "" +msgstr "shoda" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:274 msgid "" @@ -1291,14 +1370,16 @@ msgid "" "netifd interface (config interface) or netdev (config device) to enable QoS " "on" msgstr "" +"netifd rozhraní (nastavit rozhraní) nebo netdev (nastavit zařízení) na " +"kterém zapnout QoS" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "netifd interface to enable QoS on. Required." -msgstr "" +msgstr "netifd rozhraní na kterém zapnout QoS. Vyžadováno." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "no" -msgstr "" +msgstr "ne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:284 msgid "no bandwidth_down or bandwidth — ingress CAKE runs unlimited" @@ -1310,7 +1391,7 @@ msgstr "žádné bandwidth_down nebo bandwidth – výstupní CAKE běží neome #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "none" -msgstr "" +msgstr "žádné" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:281 msgid "overhead and overhead_encap are ignored unless overhead_type is manual" @@ -1326,11 +1407,13 @@ msgstr "qosify" msgid "" "qosify did not appear on ubus, so its config was not applied — press Reload" msgstr "" +"qosify se neobjevilo na ubus, takže nastavení na něj nebylo uplatněno – " +"klikněte na Znovunačíst" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:833 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1729 msgid "qosify did not come up — check the system log" -msgstr "" +msgstr "qosify nenastartovalo – podívejte se do systémového záznamu událostí" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1610 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1672 @@ -1340,7 +1423,7 @@ msgstr "qosify není spuštěné. Napravte to z karty Přehled." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1735 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1887 msgid "qosify is still running — leaving the qdiscs alone" -msgstr "" +msgstr "qosify pořád ještě je spuštěné – qdisc jsou ponechány napokoji" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" @@ -1355,6 +1438,8 @@ msgid "" "rpcd is not answering for qosify — check the ACL in /usr/share/rpcd/acl.d " "and restart rpcd" msgstr "" +"rpcd neodpovídá na qosify – zkontrolujte ACL seznamy v /usr/share/rpcd/acl.d " +"a restartujte rpcd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:832 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1609 @@ -1363,32 +1448,32 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1734 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1886 msgid "rpcd is not answering for qosify, so the service state is unknown." -msgstr "" +msgstr "rpcd neodpovídá ohledně qosify, takže stav služby není znám." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:955 msgid "section name" -msgstr "" +msgstr "název sekce" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:953 msgid "section type" -msgstr "" +msgstr "typ sekce" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1529 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1533 msgid "share" -msgstr "" +msgstr "sdílet" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1541 msgid "total" -msgstr "" +msgstr "celkem" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 msgid "value" -msgstr "" +msgstr "hodnota" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "yes" -msgstr "" +msgstr "ano" #~ msgid "%s contains a quote — qosify rejects the whole value" #~ msgstr "%s obsahuje uvozovku – qosify odmítne celou hodnotu" diff --git a/luci-app-qosify/po/de/qosify.po b/luci-app-qosify/po/de/qosify.po index a34d7da36..67761fee0 100644 --- a/luci-app-qosify/po/de/qosify.po +++ b/luci-app-qosify/po/de/qosify.po @@ -3,11 +3,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Language: de\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: Pavel Borecki \n" +"Last-Translator: Ettore Atalan \n" "Language-Team: German \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"PO-Revision-Date: 2026-09-24 06:06+0000\n" +"PO-Revision-Date: 2026-09-28 18:23+0000\n" "X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 @@ -19,8 +19,8 @@ msgstr[1] "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d Regel" +msgstr[1] "%d Regeln" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" @@ -30,7 +30,7 @@ msgstr[1] "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:682 msgid "%s (current)" -msgstr "" +msgstr "%s (aktuell)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 msgid "%s (from bandwidth)" @@ -1369,15 +1369,15 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1541 msgid "total" -msgstr "" +msgstr "gesamt" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 msgid "value" -msgstr "" +msgstr "Wert" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "yes" -msgstr "" +msgstr "ja" #~ msgid "" #~ "DSCP codepoints: CS0–CS7, AF11–AF43, EF, VA, NQB, LE, DF. Any dscp_* " diff --git a/luci-app-qosify/po/es/qosify.po b/luci-app-qosify/po/es/qosify.po index 0bd2cd0fd..a563d3548 100644 --- a/luci-app-qosify/po/es/qosify.po +++ b/luci-app-qosify/po/es/qosify.po @@ -7,87 +7,100 @@ msgstr "" "Language-Team: Spanish \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"PO-Revision-Date: 2026-09-23 19:06+0000\n" +"PO-Revision-Date: 2026-09-29 12:10+0000\n" "X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" msgid_plural "%d interfaces" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d interfaz" +msgstr[1] "%d interfaces" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d regla" +msgstr[1] "%d reglas" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" msgid_plural "%d sections" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d sección" +msgstr[1] "%d secciones" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:682 msgid "%s (current)" -msgstr "" +msgstr "%s (actual)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 msgid "%s (from bandwidth)" -msgstr "" +msgstr "%s (del ancho de banda)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2085 msgid "" "%s and %s are replaced with the templates shipped by the qosify package, and " "shaping is left disabled." msgstr "" +"%s y %s se reemplazan con las plantillas que vienen con el paquete qosify, y " +"el modelado se deja desactivado." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1809 msgid "" "%s came back empty although it is %d bytes on disk — refusing to overwrite it" msgstr "" +"%s devolvió vacío aunque son %d bytes en el disco — se niega a sobrescribirlo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2346 msgid "%s changed on disk — your unsaved edits are still in the editor." msgstr "" +"%s se modificaron en el disco — sus ediciones no guardadas aún se encuentran " +"en el editor." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2249 msgid "" "%s could not be read — the editor is left empty and will not be saved over " "it." -msgstr "" +msgstr "No se pudo leer %s — el editor se deja vacío y no se guardará sobre él." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1833 msgid "" "%s has changed since this editor was loaded. Saving now discards those " "changes." msgstr "" +"%s ha cambiado desde que se cargó este editor. Guardar ahora descarta esos " +"cambios." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1864 msgid "" "%s is %d bytes on disk but was never loaded into the editor — refusing to " "truncate it. Reload the page first." msgstr "" +"%s ocupa %d bytes en el disco, pero nunca se cargó en el editor — por lo " +"tanto, se niega a truncarlo. Recargue la página primero." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:364 msgid "%s is a list in this section — edit %s directly" -msgstr "" +msgstr "%s es una lista en esta sección — editar %s directamente" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1656 msgid "" "%s is not in the defaults list — qosify does not load it, so the Rules tab " "has no effect" msgstr "" +"%s no está en la lista predeterminada — qosify no lo carga, por lo que la " +"pestaña Reglas no tiene ningún efecto" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:286 msgid "" "%s is set to \"%s\" — qosify converts it with atoi(), so anything but a non-" "zero number means off" msgstr "" +"%s se establece en \"%s\" — qosify lo convierte con atoi(), por lo que " +"cualquier cosa que no sea un número distinto de cero significa apagado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:750 msgid "%s quick settings" -msgstr "" +msgstr "Configuración rápida de %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2069 msgid "%s uploaded, qosify reloaded." @@ -95,11 +108,11 @@ msgstr "%s subido, qosify recargado." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2103 msgid "%s was not written: %s" -msgstr "" +msgstr "%s no se escribió: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2106 msgid "%s was reset but %s was not written: %s" -msgstr "" +msgstr "%s se reinició pero %s no se escribió: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1945 msgid "%s, applied (QoS disabled)." @@ -109,6 +122,8 @@ msgstr "%s, aplicado (QoS desactivado)." msgid "" "%s, applied — qosify did not answer on ubus, so shaping could not be checked." msgstr "" +"%s, aplicado — qosify no respondió en ubus, por lo que no se pudo comprobar " +"el modelado." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1947 msgid "%s, applied." @@ -118,30 +133,40 @@ msgstr "%s, aplicado." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:468 msgid "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify ignores it" msgstr "" +"%s: %s \"%s\" no es una clase, punto de código ni un valor entre 0 y 63 — " +"qosify lo ignora" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:456 msgid "" "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify rejects the whole " "config and interface changes are not applied" msgstr "" +"%s: %s \"%s\" no es una clase, punto de código ni un valor entre 0 y 63 — " +"qosify rechaza toda la configuración y no se aplican los cambios de interfaz" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:465 msgid "" "%s: %s \"%s\" is not a codepoint or 0-63 — qosify drops this class and the " "rules using it" msgstr "" +"%s: %s \"%s\" no es un punto de código ni un valor entre 0 y 63 — qosify " +"descarta esta clase y las reglas que la utilizan" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:448 msgid "" "%s: %s cannot be checked — write it as one plain or fully quoted value, with " "no backslash" msgstr "" +"%s: %s no se puede comprobar — escríbalo como un único valor simple o entre " +"comillas completas, sin barra invertida" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:451 msgid "" "%s: %s contains shell metacharacters — qosify runs the tc command with sh -c " "as root, so they would break it or be executed" msgstr "" +"%s: %s contiene metacaracteres de shell — qosify ejecuta el comando tc con " +"sh -c como root, por lo que lo romperían o se ejecutarían" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "(alias)" @@ -149,7 +174,7 @@ msgstr "(alias)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "(this qosify build has no NQB)" -msgstr "" +msgstr "(Esta compilación de Qosify no tiene NQB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2185 msgid "A config defaults section already exists." @@ -158,6 +183,7 @@ msgstr "Ya existe una sección de configuración predeterminada." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2183 msgid "A section name may only contain letters, digits and underscores." msgstr "" +"El nombre de una sección solo puede contener letras, dígitos y guiones bajos." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:856 msgid "Active" @@ -170,19 +196,19 @@ msgstr "Añadir" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:85 msgid "Adds atm, noatm or ptm when overhead_type is manual" -msgstr "" +msgstr "Agrega atm, noatm o ptm cuando overhead_type es manual" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:87 msgid "Adds ether-vlan once per level (1 or 2)" -msgstr "" +msgstr "Agrega ether-vlan una vez por nivel (1 o 2)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:86 msgid "Adds mpu " -msgstr "" +msgstr "Agrega mpu " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:84 msgid "Adds overhead when overhead_type is manual" -msgstr "" +msgstr "Agrega sobrecarga cuando overhead_type es manual" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:608 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:737 @@ -191,11 +217,11 @@ msgstr "Avanzado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "An empty %s stops all shaping. Continue?" -msgstr "" +msgstr "Un %s vacío detiene todo el procesamiento. ¿Continuar?" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:726 msgid "Automatic download rate" -msgstr "" +msgstr "Tasa de descarga automática" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:893 msgid "Autostart" @@ -203,7 +229,7 @@ msgstr "Inicio automático" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:924 msgid "Autostart state unknown — rpcd did not answer" -msgstr "" +msgstr "Estado de inicio automático desconocido — rpcd no respondió" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" @@ -211,17 +237,19 @@ msgstr "Disponible" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" -msgstr "" +msgstr "Respaldo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:76 msgid "" "Bandwidth for both directions, where bandwidth_up or bandwidth_down is not " "set" msgstr "" +"Ancho de banda para ambas direcciones, cuando no se ha configurado " +"bandwidth_up ni bandwidth_down" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:716 msgid "Basic" -msgstr "" +msgstr "Básico" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:224 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2029 @@ -230,57 +258,59 @@ msgstr "Contenido binario rechazado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:79 msgid "CAKE diffserv mode" -msgstr "" +msgstr "Modo diffserv de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:89 msgid "CAKE egress options" -msgstr "" +msgstr "Opciones de salida de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "CAKE egress options, space separated." -msgstr "" +msgstr "Opciones de salida CAKE, espacio separado." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:88 msgid "CAKE ingress options" -msgstr "" +msgstr "Opciones de ingreso de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "CAKE ingress options, space separated." -msgstr "" +msgstr "Opciones de ingreso de CAKE, separadas por espacios." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:90 msgid "CAKE options for ingress + egress" -msgstr "" +msgstr "Opciones de CAKE para ingreso y egreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:83 msgid "" "CAKE overhead keyword added to options; manual uses overhead and " "overhead_encap" msgstr "" +"Se agregó la palabra clave CAKE overhead a las opciones; el manual usa " +"overhead y overhead_encap" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "CAKE overhead keyword. Use none if unsure." -msgstr "" +msgstr "Palabra clave CAKE overhead. Use none si no está seguro." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "Cancelar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" -msgstr "" +msgstr "Comprobar dispositivos" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1193 msgid "Choose file…" -msgstr "" +msgstr "Elegir archivo…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1114 msgid "Classes" -msgstr "" +msgstr "Clases" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1737 msgid "Cleanup exited with code %d" -msgstr "" +msgstr "La limpieza finalizó con el código %d" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 @@ -290,12 +320,12 @@ msgstr "Limpiar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1869 msgid "Clear configuration" -msgstr "" +msgstr "Limpiar configuración" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "Clear editor" -msgstr "" +msgstr "Limpiar editor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:929 msgid "Click to disable autostart" @@ -307,7 +337,7 @@ msgstr "Haga clic para activar el inicio automático" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:740 msgid "Common CAKE options" -msgstr "" +msgstr "Opciones comunes de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:604 msgid "Config" @@ -319,7 +349,7 @@ msgstr "Config borrada, qosify detenido." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1894 msgid "Config cleared." -msgstr "" +msgstr "Configuración limpiada." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1915 msgid "Config saved" @@ -332,28 +362,28 @@ msgstr "Configuración: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:566 msgid "Continue" -msgstr "" +msgstr "Continuar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1245 msgid "Could not read %s: %s" -msgstr "" +msgstr "No se pudo leer %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:607 msgid "Counters" -msgstr "" +msgstr "Contadores" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1627 msgid "DNS Entries" -msgstr "" +msgstr "Entradas DNS" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d of %d)" -msgstr "" +msgstr "Entradas DNS (%d de %d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d)" -msgstr "" +msgstr "Entradas DNS (%d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "" @@ -362,51 +392,56 @@ msgid "" "accepted too, and any dscp_* value may also name a class. Prefix with + to " "override only when the DSCP field is zero." msgstr "" +"Puntos de código DSCP: CS0–CS7, AF11–AF43, EF, VA, NQB, LE, DF (NQB requiere " +"qosify a partir de junio de 2026; las versiones 24.10 y 25.12 no lo tienen). " +"También se acepta un valor sin procesar de 0 a 63, y cualquier valor dscp_* " +"puede nombrar una clase. Anteponga + para anular solo cuando el campo DSCP " +"sea cero." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:63 msgid "DSCP value for ICMP packets" -msgstr "" +msgstr "Valor DSCP para paquetes ICMP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:65 msgid "DSCP value for bulk-marked packets" -msgstr "" +msgstr "Valor DSCP para paquetes marcados masivamente" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:71 msgid "DSCP value for egress" -msgstr "" +msgstr "Valor DSCP para el egreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:70 msgid "DSCP value for ingress" -msgstr "" +msgstr "Valor DSCP para el ingreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:69 msgid "DSCP value for ingress and egress, where they are not set" -msgstr "" +msgstr "Valor DSCP para ingreso y egreso, donde no están configurados" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:64 msgid "DSCP value for priority-marked packets" -msgstr "" +msgstr "Valor DSCP para paquetes marcados con prioridad" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "DSCP values" -msgstr "" +msgstr "Valores DSCP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:61 msgid "Default DSCP value for TCP packets" -msgstr "" +msgstr "Valor DSCP predeterminado para paquetes TCP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:62 msgid "Default DSCP value for UDP packets" -msgstr "" +msgstr "Valor DSCP predeterminado para paquetes UDP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:60 msgid "Default timeout for dynamically added entries" -msgstr "" +msgstr "Tiempo de espera predeterminado para entradas agregadas dinámicamente" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1217 msgid "Defaults" -msgstr "" +msgstr "Valores predeterminados" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 msgid "" @@ -424,15 +459,15 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "Dispositivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." -msgstr "" +msgstr "Comprobación del dispositivo realizada." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1714 msgid "Device check failed: %s" -msgstr "" +msgstr "Falló la comprobación del dispositivo: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:859 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 @@ -442,11 +477,13 @@ msgstr "Desactivado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:75 msgid "Downlink bandwidth (same format as tc)" -msgstr "" +msgstr "Ancho de banda de enlace descendente (mismo formato que tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Downlink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Ancho de banda de enlace descendente, mismo formato que tc. Ajustar justo " +"por debajo de la velocidad de línea." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1247 @@ -455,15 +492,15 @@ msgstr "Descargar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Download bandwidth" -msgstr "" +msgstr "Ancho de banda de descarga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:724 msgid "Download shaping" -msgstr "" +msgstr "Modelado de descarga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1197 msgid "Download the current files from the router." -msgstr "" +msgstr "Descargar los archivos actuales del enrutador." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "" @@ -471,10 +508,14 @@ msgid "" "raw value, a codepoint like CS0, or a class name. DNS entries are compared " "in the order in which they are specified, using the first matching entry." msgstr "" +"Cada línea tiene dos campos separados por espacios en blanco: match y dscp. " +"dscp puede ser un valor sin formato, un punto de código como CS0 o un nombre " +"de clase. Las entradas DNS se comparan en el orden en que se especifican, " +"utilizando la primera entrada que coincida." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "Egress CAKE options" -msgstr "" +msgstr "Opciones de egreso de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2020 msgid "Empty file" @@ -484,31 +525,35 @@ msgstr "Archivo vacío" msgid "" "Empty the config editor? Nothing is written until you click Save & Apply." msgstr "" +"¿Editor de configuración vacío? No se escribe nada hasta que hagas clic en " +"Guardar y aplicar." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "" "Empty the rules editor? Nothing is written until you click Save & Apply." msgstr "" +"¿Editor de reglas vacío? No se escribirá nada hasta que haga clic en Guardar " +"y aplicar." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:80 msgid "Enable CAKE NAT host detection via conntrack" -msgstr "" +msgstr "Activar la detección de hosts NAT de CAKE a través de conntrack" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:82 msgid "Enable CAKE automatic rate estimation for ingress" -msgstr "" +msgstr "Activar la estimación automática de la tasa de CAKE para el ingreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:81 msgid "Enable CAKE host isolation" -msgstr "" +msgstr "Activar el aislamiento del host CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:78 msgid "Enable egress shaping" -msgstr "" +msgstr "Activar modelado de engreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:77 msgid "Enable ingress shaping" -msgstr "" +msgstr "Activar modelado de ingreso" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 @@ -525,11 +570,11 @@ msgstr "Activado — No se está modelando (verificar configuración)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Encapsulation overhead" -msgstr "" +msgstr "Sobrecarga de encapsulación" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2182 msgid "Enter a section name." -msgstr "" +msgstr "Introduzca el nombre de una sección." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2156 msgid "Enter a single IPv4 address (qosify does not accept CIDR)." @@ -539,6 +584,8 @@ msgstr "Introduzca una única dirección IPv4 (qosify no acepta CIDR)." msgid "" "Enter a single IPv6 address (qosify does not accept CIDR or a %zone suffix)." msgstr "" +"Introduzca una única dirección IPv6 (qosify no acepta CIDR ni el sufijo " +"%zone)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2141 msgid "Enter a value." @@ -546,7 +593,7 @@ msgstr "Introduzca un valor." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 msgid "Entries" -msgstr "" +msgstr "Entradas" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1848 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1961 @@ -562,6 +609,9 @@ msgid "" "Error: invalid characters in bandwidth or options fields. Use alphanumeric, " "spaces, hyphens, dots, colons only." msgstr "" +"Error: caracteres no válidos en los campos de ancho de banda u opciones. " +"Utilice únicamente caracteres alfanuméricos, espacios, guiones, puntos y dos " +"puntos." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1798 msgid "Error: name must be a device or interface name" @@ -573,7 +623,7 @@ msgstr "Error: la sobrecarga debe ser un número entero de bytes" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1768 msgid "Error: overhead_mpu must be a whole number of bytes" -msgstr "" +msgstr "Error: overhead_mpu debe ser un número entero de bytes" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2070 msgid "Errors:" @@ -583,11 +633,11 @@ msgstr "Errores:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "File" -msgstr "" +msgstr "Archivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1832 msgid "File changed on disk" -msgstr "" +msgstr "Archivo modificado en el disco" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2021 msgid "File too large (max 64KB)" @@ -595,7 +645,7 @@ msgstr "El archivo es demasiado grande (máximo 64 KB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:667 msgid "Files" -msgstr "" +msgstr "Archivos" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Found (empty or invalid)" @@ -607,78 +657,82 @@ msgstr "Otorgar acceso a la aplicación LuCI qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:728 msgid "Host isolation" -msgstr "" +msgstr "Aislamiento del host" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1169 msgid "IPv4 address, e.g. 1.1.1.1" -msgstr "" +msgstr "Dirección IPv4, p. ej. 1.1.1.1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1170 msgid "IPv6 address, e.g. ff01::1" -msgstr "" +msgstr "Dirección IPv6, p. ej. ff01::1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "Ingress CAKE options" -msgstr "" +msgstr "Opciones de ingreso de CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Interface" -msgstr "" +msgstr "Interfaz" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:741 msgid "Invalid CAKE options can stop qosify starting." -msgstr "" +msgstr "Las opciones de CAKE no válidas pueden impedir que qosify se inicie." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1173 msgid "Like dns:... but only matches cname entries" -msgstr "" +msgstr "Similar a dns:... pero solo coincide con las entradas cname" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:228 msgid "" "Line %d is longer than 1023 characters — the rule loader reads fixed-size " "lines and would split it, comment included" msgstr "" +"La línea %d es más larga que 1023 caracteres — el cargador de reglas lee " +"líneas de tamaño fijo y la dividiría, comentario incluido" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:59 msgid "List of files with port/IP/host mappings" -msgstr "" +msgstr "Lista de archivos con asignaciones de puerto/IP/host" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 msgid "Loading..." -msgstr "" +msgstr "Cargando..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1212 msgid "Maintenance" -msgstr "" +msgstr "Mantenimiento" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Manual overhead" -msgstr "" +msgstr "Sobrecarga manual" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "Mapping file syntax" -msgstr "" +msgstr "Sintaxis del archivo de mapeo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1692 msgid "Mapping files reloaded." -msgstr "" +msgstr "Archivos de mapeo recargados." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:434 msgid "" "Match not loaded by qosify on line %s — ports 1-65534, one IPv4/IPv6 address " "(no CIDR or %%zone), or dns:, dns_c:" msgstr "" +"Coincidencia no cargada por qosify en la línea %s — puertos 1-65534, una " +"dirección IPv4/IPv6 (sin CIDR o %%zone), o dns:, dns_c:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:66 msgid "Maximum average packet length for marking a flow as priority" -msgstr "" +msgstr "Longitud media máxima del paquete para marcar un flujo como prioritario" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Minimum packet unit (MPU)" -msgstr "" +msgstr "Unidad mínima de paquete (MPU)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 @@ -688,37 +742,40 @@ msgstr "Ausente" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Modified" -msgstr "" +msgstr "Modificado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:433 msgid "" "More than two fields on line %s — qosify reads the rest of the line as the " "DSCP value and skips it" msgstr "" +"Más de dos campos en la línea %s —qosify lee el resto de la línea como el " +"valor DSCP y lo omite" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:727 msgid "NAT awareness" -msgstr "" +msgstr "Conciencia NAT" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Netdev to enable QoS on. Required." -msgstr "" +msgstr "Netdev para activar QoS. Es obligatorio." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No CAKE tin statistics." -msgstr "" +msgstr "No hay estadísticas sobre tin de CAKE." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1628 msgid "No DNS entries." -msgstr "" +msgstr "No hay entradas DNS." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:432 msgid "No DSCP target on line %s — qosify skips single-field lines" msgstr "" +"No hay objetivo DSCP en la línea %s — qosify omite las líneas de campo único" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1107 msgid "No classes defined in %s" -msgstr "" +msgstr "No se han definido clases en %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2142 msgid "No classes defined. Add classes in the Config tab first." @@ -729,7 +786,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1191 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1192 msgid "No file selected" -msgstr "" +msgstr "No se ha seleccionado ningún archivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2006 msgid "No files selected." @@ -737,11 +794,11 @@ msgstr "No se ha seleccionado ningún archivo." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No output." -msgstr "" +msgstr "Sin salida." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1568 msgid "No per-class counters." -msgstr "" +msgstr "No hay contadores por clase." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2154 msgid "No spaces or # allowed in patterns or addresses." @@ -766,16 +823,19 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:67 msgid "Number of packets per second to trigger bulk flow detection" msgstr "" +"Número de paquetes por segundo para activar la detección de flujo masivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1161 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1174 msgid "Only override the DSCP value if it is zero" -msgstr "" +msgstr "Solo se puede sobrescribir el valor DSCP si es cero" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:704 msgid "" "Only sent with host isolation on — add nat to common CAKE options to force it" msgstr "" +"Solo se envía con el aislamiento del host activado — agregue nat a las " +"opciones comunes de CAKE para forzarlo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1017 msgid "Options" @@ -783,11 +843,11 @@ msgstr "Opciones" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:730 msgid "Overhead" -msgstr "" +msgstr "Sobrecarga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "Overhead preset" -msgstr "" +msgstr "Preajuste de sobrecarga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:603 msgid "Overview" @@ -795,17 +855,20 @@ msgstr "Vista general" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1834 msgid "Overwrite" -msgstr "" +msgstr "Sobreescribir" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2007 msgid "Overwrite config files" -msgstr "" +msgstr "Sobrescribir archivos de configuración" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1172 msgid "" "POSIX.2 extended regular expression for matching hostnames. Only works if " "dns lookups are passed to qosify via the add_dns_host ubus call." msgstr "" +"Expresión regular extendida POSIX.2 para la coincidencia de nombres de host. " +"Solo funciona si las consultas DNS se pasan a qosify mediante la llamada a " +"ubus add_dns_host." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2150 msgid "Port must be 1-65534 (qosify rejects 65535)." @@ -814,7 +877,7 @@ msgstr "El puerto debe ser 1-65534 (qosify rechaza el 65535)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2149 msgid "Port must be a number or a range (4500, 5060-5061)." -msgstr "" +msgstr "El puerto debe ser un número o un rango (4500, 5060-5061)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "QoS Enabled" @@ -822,15 +885,15 @@ msgstr "QoS activado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:721 msgid "Queueing mode" -msgstr "" +msgstr "Modo de cola" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1163 msgid "Quick Add" -msgstr "" +msgstr "Agregar rápidamente" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1016 msgid "Quick Add: %s" -msgstr "" +msgstr "Agregar rápidamente: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2153 msgid "Range start must not exceed end." @@ -838,19 +901,19 @@ msgstr "El inicio del rango no debe exceder el final." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1213 msgid "Re-check devices" -msgstr "" +msgstr "Volver a comprobar los dispositivos" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1707 msgid "Re-checking devices..." -msgstr "" +msgstr "Revisando los dispositivos..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:768 msgid "Re-read the mapping files only" -msgstr "" +msgstr "Volver a leer únicamente los archivos de mapeo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1690 msgid "Re-reading the mapping files..." -msgstr "" +msgstr "Releyendo los archivos de mapeo..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1215 msgid "" @@ -859,6 +922,11 @@ msgid "" "is stopped. Nothing is reported back by the call — the result shows in the " "Service table on the Overview tab." msgstr "" +"Volver a ejecutar el proceso de detección de dispositivos del propio " +"demonio: se busca de nuevo en cada sección de modelado, se inicia la sección " +"cuyo dispositivo existe ahora y se detiene la sección cuyo dispositivo ha " +"desaparecido. La llamada no devuelve ningún resultado; este se muestra en la " +"tabla de Servicio de la pestaña Vista general." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2024 msgid "Read error" @@ -870,11 +938,11 @@ msgstr "Lectura y validación de archivos..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1681 msgid "Reading tc output..." -msgstr "" +msgstr "Leyendo la salida de tc..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1019 msgid "Reference" -msgstr "" +msgstr "Referencia" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload" @@ -882,20 +950,20 @@ msgstr "Recargar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload Rules" -msgstr "" +msgstr "Reglas de recarga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1695 msgid "Reload failed: %s" -msgstr "" +msgstr "Error al recargar: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "Requires write access." -msgstr "" +msgstr "Requiere permisos de escritura." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1219 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2086 msgid "Reset" -msgstr "" +msgstr "Restablecer" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2120 msgid "Reset failed: %s" @@ -903,7 +971,7 @@ msgstr "Error al reiniciar: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2084 msgid "Reset to defaults" -msgstr "" +msgstr "Restablecer valores predeterminados" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2116 msgid "Reset to defaults, applied." @@ -920,11 +988,11 @@ msgstr "Reiniciar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1203 msgid "Restore" -msgstr "" +msgstr "Restaurar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1218 msgid "Restore qosify defaults" -msgstr "" +msgstr "Restaurar la configuración predeterminada de qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2095 msgid "Restoring defaults..." @@ -932,7 +1000,7 @@ msgstr "Restaurando valores predeterminados..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:605 msgid "Rules" -msgstr "" +msgstr "Reglas" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1976 msgid "Rules saved" @@ -953,7 +1021,7 @@ msgstr "Ejecutándose — Sin modelado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:867 msgid "Running — Shaping Unknown" -msgstr "" +msgstr "Ejecutándose — Modelado desconocido" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:753 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1147 @@ -986,6 +1054,9 @@ msgid "" "Section name is the class name that rules and dscp_* values refer to. " "qosify.init reads config alias the same way as config class." msgstr "" +"El nombre de la sección es el nombre de la clase a la que se refieren las " +"reglas y los valores dscp_*. qosify.init lee el alias de configuración de la " +"misma manera que la clase de configuración." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1724 msgid "Sending %s to qosify..." @@ -993,23 +1064,23 @@ msgstr "Enviando %s a qosify..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Sent to CAKE as atm, noatm or ptm." -msgstr "" +msgstr "Enviado a CAKE como atm, noatm o ptm." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "Sent to CAKE as ether-vlan, once per tag." -msgstr "" +msgstr "Enviado a CAKE como ether-vlan, una vez por etiqueta." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Sent to CAKE as mpu, in bytes." -msgstr "" +msgstr "Enviado a CAKE como mpu, en bytes." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Sent to CAKE as overhead, in bytes." -msgstr "" +msgstr "Enviado a CAKE como sobrecarga, en bytes." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:663 msgid "Service" -msgstr "" +msgstr "Servicio" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1745 msgid "Service action failed: %s" @@ -1022,16 +1093,16 @@ msgstr "Configuración guardada" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:723 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:894 msgid "Shaping" -msgstr "" +msgstr "Modelado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "Tamaño" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" -msgstr "" +msgstr "Omitir esta sección" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:764 msgid "Start" @@ -1045,7 +1116,7 @@ msgstr "Estado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:855 msgid "Status Unknown" -msgstr "" +msgstr "Estado desconocido" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:766 msgid "Stop" @@ -1053,40 +1124,50 @@ msgstr "Detener" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1167 msgid "TCP single port, or range from to " -msgstr "" +msgstr "Puerto TCP único, o rango desde hasta " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1680 msgid "The detailed tc output needs write access to this page." msgstr "" +"La salida detallada de tc necesita permisos de escritura en esta página." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:590 msgid "" "The qosify UCI configuration could not be loaded — class and interface lists " "may be incomplete." msgstr "" +"No se pudo cargar la configuración UCI de qosify — es posible que las listas " +"de clases e interfaces estén incompletas." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1204 msgid "" "The selected files replace the ones on the router and qosify is reloaded." msgstr "" +"Los archivos seleccionados reemplazan a los del enrutador y se vuelve a " +"cargar qosify." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2008 msgid "" "The selected files replace the ones on the router and qosify is reloaded. " "Download a backup from this tab first if you need one." msgstr "" +"Los archivos seleccionados reemplazan a los del enrutador y qosify se " +"recarga. Si necesita una copia de seguridad, descárguela primero desde esta " +"pestaña." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:68 msgid "Time below bulk_trigger_pps threshold until a bulk flow mark is removed" msgstr "" +"Tiempo por debajo del umbral bulk_trigger_pps hasta que se elimine una marca " +"de flujo masivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 msgid "Traffic by CAKE Tin" -msgstr "" +msgstr "Tráfico Tin por CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1401 msgid "Traffic by Class" -msgstr "" +msgstr "Tráfico por clase" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:596 msgid "Traffic shaping and DSCP classification via qosify" @@ -1094,13 +1175,13 @@ msgstr "Modelado de tráfico y DSCP mediante qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1168 msgid "UDP single port, or range from to " -msgstr "" +msgstr "UDP de un solo puerto o rango desde hasta " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:864 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:866 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:925 msgid "Unknown" -msgstr "" +msgstr "Desconocido" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "Unknown class/DSCP target: %s" @@ -1109,30 +1190,34 @@ msgstr "Destino de clase/DSCP desconocido: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "Unticked sets disabled 1 and qosify skips this section." msgstr "" +"Si no se marca la casilla, se desactiva la opción 1 y qosify omite esta " +"sección." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:74 msgid "Uplink bandwidth (same format as tc)" -msgstr "" +msgstr "Ancho de banda de enlace ascendente (mismo formato que tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Uplink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Ancho de banda de enlace ascendente, mismo formato que tc. Ajustar justo por " +"debajo de la velocidad de línea." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "Upload" -msgstr "" +msgstr "Carga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1210 msgid "Upload & Apply" -msgstr "" +msgstr "Subir y aplicar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2009 msgid "Upload and apply" -msgstr "" +msgstr "Subir y aplicar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Upload bandwidth" -msgstr "" +msgstr "Ancho de banda de carga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2061 msgid "Upload error: %s" @@ -1144,7 +1229,7 @@ msgstr "Error al cargar: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:725 msgid "Upload shaping" -msgstr "" +msgstr "Modelado de carga" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2035 msgid "Uploading" @@ -1152,11 +1237,11 @@ msgstr "Cargando" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:892 msgid "Uptime" -msgstr "" +msgstr "Tiempo de actividad" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "VLAN tags" -msgstr "" +msgstr "Etiquetas VLAN" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Valid" @@ -1176,7 +1261,7 @@ msgstr "Trabajando" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "Write empty file" -msgstr "" +msgstr "Escribir archivo vacío" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1906 msgid "Writing config and reloading qosify..." @@ -1191,42 +1276,53 @@ msgid "" "You have read-only access to this page, so editing and service control are " "disabled." msgstr "" +"Tiene acceso de solo lectura a esta página, por lo que la edición y el " +"control del servicio están desactivados." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "active" -msgstr "" +msgstr "activo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1767 msgid "" "bandwidth_down does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_down no parece una tasa tc (100mbit, 12 MBps, ilimitado) — de " +"todos modos, se deja pasar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1766 msgid "" "bandwidth_up does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_up no parece una tasa tc (100mbit, 12 MBps, ilimitado) — de todos " +"modos, se deja pasar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1012 msgid "" "config device takes the same options, with name set to a netdev. nat " "defaults to 1 for interfaces and 0 for devices." msgstr "" +"el dispositivo de configuración acepta las mismas opciones, con el nombre " +"establecido en un netdev. nat por defecto es 1 para interfaces y 0 para " +"dispositivos." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "device %s" -msgstr "" +msgstr "dispositivo %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "device: %s, ingress: %s, egress: %s" -msgstr "" +msgstr "dispositivo: %s, ingreso: %s, egreso: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:289 msgid "" "disabled is set to \"%s\" — config_get_bool does not recognise that, so the " "section stays enabled" msgstr "" +"desactivado está configurado para «%s» — config_get_bool no lo reconoce, por " +"lo que la sección permanece activada" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 @@ -1236,23 +1332,23 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2129 msgid "e.g. %s" -msgstr "" +msgstr "p. ej. %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1171 msgid "fnmatch() pattern supporting * and ? as wildcard characters" -msgstr "" +msgstr "fnmatch() admite patrones * y ? como caracteres comodín" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1613 msgid "get_stats did not answer." -msgstr "" +msgstr "get_stats no respondió." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "inactive" -msgstr "" +msgstr "inactivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "ingress %s, egress %s" -msgstr "" +msgstr "ingreso %s, egreso %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:282 msgid "ingress and egress are both 0 — nothing is shaped" @@ -1260,11 +1356,11 @@ msgstr "ingress y egress son ambos 0 — no se modela nada" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "interface %s" -msgstr "" +msgstr "interfaz %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1155 msgid "match" -msgstr "" +msgstr "coincidir" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:274 msgid "" @@ -1295,14 +1391,16 @@ msgid "" "netifd interface (config interface) or netdev (config device) to enable QoS " "on" msgstr "" +"interfaz netifd (interfaz de configuración) o netdev (dispositivo de " +"configuración) para activar QoS en" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "netifd interface to enable QoS on. Required." -msgstr "" +msgstr "interfaz netifd para activar QoS. Es obligatorio." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "no" -msgstr "" +msgstr "no" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:284 msgid "no bandwidth_down or bandwidth — ingress CAKE runs unlimited" @@ -1316,7 +1414,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "none" -msgstr "" +msgstr "ninguno" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:281 msgid "overhead and overhead_encap are ignored unless overhead_type is manual" @@ -1332,11 +1430,13 @@ msgstr "Qosify" msgid "" "qosify did not appear on ubus, so its config was not applied — press Reload" msgstr "" +"qosify no apareció en ubus, por lo que su configuración no se aplicó — " +"presione Recargar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:833 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1729 msgid "qosify did not come up — check the system log" -msgstr "" +msgstr "qosify no se inició — revise el registro del sistema" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1610 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1672 @@ -1346,7 +1446,7 @@ msgstr "qosify no se está ejecutando. Comience desde la pestaña Vista general. #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1735 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1887 msgid "qosify is still running — leaving the qdiscs alone" -msgstr "" +msgstr "qosify sigue en ejecución — dejando los qdiscs solos" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" @@ -1361,6 +1461,8 @@ msgid "" "rpcd is not answering for qosify — check the ACL in /usr/share/rpcd/acl.d " "and restart rpcd" msgstr "" +"rpcd no responde a qosify — comprobar la ACL en /usr/share/rpcd/acl.d y " +"reiniciar rpcd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:832 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1609 @@ -1370,31 +1472,32 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1886 msgid "rpcd is not answering for qosify, so the service state is unknown." msgstr "" +"rpcd no responde a qosify, por lo que se desconoce el estado del servicio." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:955 msgid "section name" -msgstr "" +msgstr "nombre de la sección" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:953 msgid "section type" -msgstr "" +msgstr "tipo de sección" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1529 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1533 msgid "share" -msgstr "" +msgstr "compartir" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1541 msgid "total" -msgstr "" +msgstr "total" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 msgid "value" -msgstr "" +msgstr "valor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "yes" -msgstr "" +msgstr "sí" #~ msgid "%s contains a quote — qosify rejects the whole value" #~ msgstr "%s contiene una comilla — qosify rechaza todo el valor" diff --git a/luci-app-qosify/po/ko/qosify.po b/luci-app-qosify/po/ko/qosify.po index 02889ca07..bfc30e617 100644 --- a/luci-app-qosify/po/ko/qosify.po +++ b/luci-app-qosify/po/ko/qosify.po @@ -7,8 +7,8 @@ msgstr "" "Language-Team: Korean \n" "Plural-Forms: nplurals=1; plural=0;\n" -"PO-Revision-Date: 2026-08-17 17:59+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-29 17:59+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" @@ -208,7 +208,7 @@ msgstr "사용 가능" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" -msgstr "" +msgstr "백업" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:76 msgid "" @@ -231,7 +231,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:89 msgid "CAKE egress options" -msgstr "" +msgstr "CAKE 이그레스 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "CAKE egress options, space separated." @@ -239,7 +239,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:88 msgid "CAKE ingress options" -msgstr "" +msgstr "CAKE 인그레스 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "CAKE ingress options, space separated." @@ -247,7 +247,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:90 msgid "CAKE options for ingress + egress" -msgstr "" +msgstr "인그레스 및 이그레스 CAKE 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:83 msgid "" @@ -261,7 +261,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "취소" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" @@ -269,7 +269,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1193 msgid "Choose file…" -msgstr "" +msgstr "파일 선택…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1114 msgid "Classes" @@ -304,7 +304,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:740 msgid "Common CAKE options" -msgstr "" +msgstr "공통 CAKE 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:604 msgid "Config" @@ -329,7 +329,7 @@ msgstr "설정: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:566 msgid "Continue" -msgstr "" +msgstr "계속" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1245 msgid "Could not read %s: %s" @@ -416,7 +416,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "장치" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." @@ -447,7 +447,7 @@ msgstr "다운로드" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Download bandwidth" -msgstr "" +msgstr "다운로드 대역폭" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:724 msgid "Download shaping" @@ -466,7 +466,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "Egress CAKE options" -msgstr "" +msgstr "이그레스 CAKE 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2020 msgid "Empty file" @@ -492,7 +492,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:81 msgid "Enable CAKE host isolation" -msgstr "" +msgstr "CAKE 호스트 격리 활성화" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:78 msgid "Enable egress shaping" @@ -575,7 +575,7 @@ msgstr "오류:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "File" -msgstr "" +msgstr "파일" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1832 msgid "File changed on disk" @@ -599,7 +599,7 @@ msgstr "LuCI 앱 qosify에 접근 권한 부여" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:728 msgid "Host isolation" -msgstr "" +msgstr "호스트 격리" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1169 @@ -613,11 +613,11 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "Ingress CAKE options" -msgstr "" +msgstr "인그레스 CAKE 옵션" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Interface" -msgstr "" +msgstr "인터페이스" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:741 msgid "Invalid CAKE options can stop qosify starting." @@ -808,7 +808,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:721 msgid "Queueing mode" -msgstr "" +msgstr "대기열 관리 모드" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1163 msgid "Quick Add" @@ -917,7 +917,7 @@ msgstr "기본값 복원 중..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:605 msgid "Rules" -msgstr "" +msgstr "규칙" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1976 msgid "Rules saved" @@ -994,7 +994,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:663 msgid "Service" -msgstr "" +msgstr "서비스" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1745 msgid "Service action failed: %s" @@ -1012,7 +1012,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "크기" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" @@ -1085,7 +1085,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:866 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:925 msgid "Unknown" -msgstr "" +msgstr "알 수 없음" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "Unknown class/DSCP target: %s" @@ -1105,19 +1105,19 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "Upload" -msgstr "" +msgstr "업로드" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1210 msgid "Upload & Apply" -msgstr "" +msgstr "업로드 및 적용" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2009 msgid "Upload and apply" -msgstr "" +msgstr "업로드 및 적용" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Upload bandwidth" -msgstr "" +msgstr "업로드 대역폭" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2061 msgid "Upload error: %s" @@ -1177,7 +1177,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "active" -msgstr "" +msgstr "활성" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1767 msgid "" @@ -1199,11 +1199,11 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "device %s" -msgstr "" +msgstr "장치 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "device: %s, ingress: %s, egress: %s" -msgstr "" +msgstr "장치: %s, 인그레스: %s, 이그레스: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:289 msgid "" @@ -1231,7 +1231,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "inactive" -msgstr "" +msgstr "비활성" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "ingress %s, egress %s" @@ -1243,7 +1243,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "interface %s" -msgstr "" +msgstr "인터페이스 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1155 msgid "match" @@ -1347,11 +1347,11 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:955 msgid "section name" -msgstr "" +msgstr "섹션 이름" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:953 msgid "section type" -msgstr "" +msgstr "섹션 유형" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1529 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1533 diff --git a/luci-app-qosify/po/pl/qosify.po b/luci-app-qosify/po/pl/qosify.po index 67daf4272..f17cabc26 100644 --- a/luci-app-qosify/po/pl/qosify.po +++ b/luci-app-qosify/po/pl/qosify.po @@ -8,90 +8,106 @@ msgstr "" "luciapplicationsqosify/pl/>\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -"PO-Revision-Date: 2026-08-16 22:03+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-27 20:14+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" msgid_plural "%d interfaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d interfejs" +msgstr[1] "%d interfejsy" +msgstr[2] "%d interfejsów" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d reguła" +msgstr[1] "%d reguły" +msgstr[2] "%d reguł" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" msgid_plural "%d sections" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d sekcja" +msgstr[1] "%d sekcje" +msgstr[2] "%d sekcji" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:682 msgid "%s (current)" -msgstr "" +msgstr "%s (bieżący)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 msgid "%s (from bandwidth)" -msgstr "" +msgstr "%s (z przepustowości)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2085 msgid "" "%s and %s are replaced with the templates shipped by the qosify package, and " "shaping is left disabled." msgstr "" +"%s i %s są zastępowane szablonami dostarczanymi w pakiecie qosify, a " +"kształtowanie ruchu pozostaje wyłączone." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1809 msgid "" "%s came back empty although it is %d bytes on disk — refusing to overwrite it" msgstr "" +"%s zwróciło pusty wynik, mimo że na dysku zajmuje %d bajtów — odmowa " +"nadpisania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2346 msgid "%s changed on disk — your unsaved edits are still in the editor." msgstr "" +"%s uległo zmianie na dysku — twoje niezapisane zmiany nadal znajdują się w " +"edytorze." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2249 msgid "" "%s could not be read — the editor is left empty and will not be saved over " "it." msgstr "" +"%s nie udało się odczytać — edytor pozostaje pusty i nie zostanie zapisany w " +"jego miejsce." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1833 msgid "" "%s has changed since this editor was loaded. Saving now discards those " "changes." msgstr "" +"%s uległo zmianie od momentu załadowania tego edytora. Zapisanie spowoduje " +"utratę tych zmian." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1864 msgid "" "%s is %d bytes on disk but was never loaded into the editor — refusing to " "truncate it. Reload the page first." msgstr "" +"%s zajmuje na dysku %d bajtów, ale nie został wczytany do edytora – odmowa " +"skrócenia pliku. Najpierw odśwież stronę." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:364 msgid "%s is a list in this section — edit %s directly" -msgstr "" +msgstr "%s to lista w tej sekcji — edytuj %s bezpośrednio" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1656 msgid "" "%s is not in the defaults list — qosify does not load it, so the Rules tab " "has no effect" msgstr "" +"%s nie znajduje się na liście domyślnej — qosify go nie wczytuje, więc karta " +"„Reguły” nie przynosi żadnego efektu" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:286 msgid "" "%s is set to \"%s\" — qosify converts it with atoi(), so anything but a non-" "zero number means off" msgstr "" +"%s ustawiono na „%s” — qosify przetwarza go za pomocą funkcji atoi(), więc " +"każda wartość inna niż liczba niezerowa oznacza wyłączenie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:750 msgid "%s quick settings" -msgstr "" +msgstr "Szybkie ustawienia %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2069 msgid "%s uploaded, qosify reloaded." @@ -99,11 +115,11 @@ msgstr "%s przesłano, qosify załadowano ponownie." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2103 msgid "%s was not written: %s" -msgstr "" +msgstr "Nie zapisano %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2106 msgid "%s was reset but %s was not written: %s" -msgstr "" +msgstr "Zresetowano %s, ale nie zapisano %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1945 msgid "%s, applied (QoS disabled)." @@ -113,6 +129,8 @@ msgstr "%s, zastosowano (QoS wyłączone)." msgid "" "%s, applied — qosify did not answer on ubus, so shaping could not be checked." msgstr "" +"%s, zastosowano — qosify nie odpowiedziało przez ubus, więc nie można było " +"zweryfikować kształtowania ruchu." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1947 msgid "%s, applied." @@ -122,30 +140,42 @@ msgstr "%s, zastosowano." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:468 msgid "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify ignores it" msgstr "" +"%s: %s „%s” nie jest klasą, punktem kodowym ani wartością z zakresu 0–63 — " +"qosify to ignoruje" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:456 msgid "" "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify rejects the whole " "config and interface changes are not applied" msgstr "" +"%s: %s „%s” nie jest klasą, punktem kodowym ani wartością z zakresu 0–63 — " +"qosify odrzuca całą konfigurację, a zmiany dotyczące interfejsu nie zostają " +"wprowadzone" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:465 msgid "" "%s: %s \"%s\" is not a codepoint or 0-63 — qosify drops this class and the " "rules using it" msgstr "" +"%s: %s „%s” nie jest punktem kodowym ani wartością z zakresu 0‐63 — qosify " +"odrzuca tę klasę oraz reguły, które z niej korzystają" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:448 msgid "" "%s: %s cannot be checked — write it as one plain or fully quoted value, with " "no backslash" msgstr "" +"%s: nie można sprawdzić %s — zapisz to jako pojedynczą, zwykłą lub w pełni " +"ujętą w cudzysłów wartość, bez znaku odwrotnego ukośnika" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:451 msgid "" "%s: %s contains shell metacharacters — qosify runs the tc command with sh -c " "as root, so they would break it or be executed" msgstr "" +"%s: %s zawiera metaznaki powłoki — qosify uruchamia polecenie tc za pomocą " +"sh -c z uprawnieniami roota, więc mogłyby one zakłócić działanie polecenia " +"lub zostać wykonane" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "(alias)" @@ -153,7 +183,7 @@ msgstr "(alias)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "(this qosify build has no NQB)" -msgstr "" +msgstr "(ta kompilacja qosify nie zawiera NQB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2185 msgid "A config defaults section already exists." @@ -161,7 +191,7 @@ msgstr "Sekcja ustawień domyślnych już istnieje." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2183 msgid "A section name may only contain letters, digits and underscores." -msgstr "" +msgstr "Nazwa sekcji może zawierać tylko litery, cyfry i znaki podkreślenia." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:856 msgid "Active" @@ -174,19 +204,19 @@ msgstr "Dodaj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:85 msgid "Adds atm, noatm or ptm when overhead_type is manual" -msgstr "" +msgstr "Dodaje atm, noatm lub ptm, gdy overhead_type ma wartość manual" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:87 msgid "Adds ether-vlan once per level (1 or 2)" -msgstr "" +msgstr "Dodaje ether-vlan raz na poziom (1 lub 2)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:86 msgid "Adds mpu " -msgstr "" +msgstr "Dodaje MPU " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:84 msgid "Adds overhead when overhead_type is manual" -msgstr "" +msgstr "Dodaje narzut , gdy overhead_type ma wartość manual" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:608 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:737 @@ -196,10 +226,12 @@ msgstr "Zaawansowane" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "An empty %s stops all shaping. Continue?" msgstr "" +"Puste pole %s powoduje zatrzymanie wszelkich działań związanych z " +"kształtowaniem ruchu. Kontynuować?" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:726 msgid "Automatic download rate" -msgstr "" +msgstr "Automatyczna prędkość pobierania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:893 msgid "Autostart" @@ -207,7 +239,7 @@ msgstr "Autostart" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:924 msgid "Autostart state unknown — rpcd did not answer" -msgstr "" +msgstr "Stan autostartu nieznany — rpcd nie odpowiedział" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" @@ -215,17 +247,19 @@ msgstr "Dostępne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" -msgstr "" +msgstr "Kopia zapasowa" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:76 msgid "" "Bandwidth for both directions, where bandwidth_up or bandwidth_down is not " "set" msgstr "" +"Przepustowość dla obu kierunków, gdy nie określono bandwidth_up ani " +"bandwidth_down" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:716 msgid "Basic" -msgstr "" +msgstr "Podstawowe" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:224 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2029 @@ -234,57 +268,59 @@ msgstr "Zawartość binarna odrzucona" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:79 msgid "CAKE diffserv mode" -msgstr "" +msgstr "Tryb diffserv CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:89 msgid "CAKE egress options" -msgstr "" +msgstr "Opcje wyjścia CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "CAKE egress options, space separated." -msgstr "" +msgstr "Opcje wyjścia CAKE, rozdzielone spacjami." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:88 msgid "CAKE ingress options" -msgstr "" +msgstr "Opcje wejścia CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "CAKE ingress options, space separated." -msgstr "" +msgstr "Opcje wejścia CAKE, oddzielone spacją." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:90 msgid "CAKE options for ingress + egress" -msgstr "" +msgstr "Opcje CAKE dla wejścia i wyjścia" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:83 msgid "" "CAKE overhead keyword added to options; manual uses overhead and " "overhead_encap" msgstr "" +"Do opcji dodano słowo kluczowe CAKE overhead; manual używa overhead i " +"overhead_encap" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "CAKE overhead keyword. Use none if unsure." -msgstr "" +msgstr "Słowo kluczowe CAKE overhead. Jeśli nie masz pewności, użyj none." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "Anuluj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" -msgstr "" +msgstr "Sprawdź urządzenia" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1193 msgid "Choose file…" -msgstr "" +msgstr "Wybierz plik…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1114 msgid "Classes" -msgstr "" +msgstr "Klasy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1737 msgid "Cleanup exited with code %d" -msgstr "" +msgstr "Proces czyszczenia zakończył się kodem %d" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 @@ -294,12 +330,12 @@ msgstr "Wyczyść" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1869 msgid "Clear configuration" -msgstr "" +msgstr "Wyczyść konfigurację" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "Clear editor" -msgstr "" +msgstr "Wyczyść edytor" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:929 msgid "Click to disable autostart" @@ -311,7 +347,7 @@ msgstr "Kliknij, aby włączyć autostart" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:740 msgid "Common CAKE options" -msgstr "" +msgstr "Typowe opcje CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:604 msgid "Config" @@ -323,7 +359,7 @@ msgstr "Konfiguracja wyczyszczona, qosify zatrzymany." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1894 msgid "Config cleared." -msgstr "" +msgstr "Konfiguracja wyczyszczona." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1915 msgid "Config saved" @@ -336,28 +372,28 @@ msgstr "Konfiguracja: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:566 msgid "Continue" -msgstr "" +msgstr "Kontynuuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1245 msgid "Could not read %s: %s" -msgstr "" +msgstr "Nie można odczytać %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:607 msgid "Counters" -msgstr "" +msgstr "Liczniki" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1627 msgid "DNS Entries" -msgstr "" +msgstr "Wpisy DNS" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d of %d)" -msgstr "" +msgstr "Wpisy DNS (%d z %d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d)" -msgstr "" +msgstr "Wpisy DNS (%d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "" @@ -366,51 +402,58 @@ msgid "" "accepted too, and any dscp_* value may also name a class. Prefix with + to " "override only when the DSCP field is zero." msgstr "" +"Punkty kodowe DSCP: CS0–CS7, AF11–AF43, EF, VA, NQB, LE, DF (dla NQB " +"wymagana jest obsługa qosify od czerwca 2026 r.; wersje 24.10 i 25.12 jej " +"nie mają). Akceptowana jest również surowa wartość z zakresu 0-63, a każda " +"wartość dscp_* może także określać klasę. Użyj prefiksu +, aby zastosować " +"nadpisanie tylko wtedy, gdy pole DSCP ma wartość zero." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:63 msgid "DSCP value for ICMP packets" -msgstr "" +msgstr "Wartość DSCP dla pakietów ICMP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:65 msgid "DSCP value for bulk-marked packets" -msgstr "" +msgstr "Wartość DSCP dla pakietów oznaczonych jako ruch masowy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:71 msgid "DSCP value for egress" -msgstr "" +msgstr "Wartość DSCP dla ruchu wychodzącego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:70 msgid "DSCP value for ingress" -msgstr "" +msgstr "Wartość DSCP dla ruchu przychodzącego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:69 msgid "DSCP value for ingress and egress, where they are not set" msgstr "" +"Wartość DSCP dla ruchu przychodzącego i wychodzącego w przypadkach, gdy nie " +"została ona ustawiona" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:64 msgid "DSCP value for priority-marked packets" -msgstr "" +msgstr "Wartość DSCP dla pakietów oznaczonych priorytetem" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "DSCP values" -msgstr "" +msgstr "Wartości DSCP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:61 msgid "Default DSCP value for TCP packets" -msgstr "" +msgstr "Domyślna wartość DSCP dla pakietów TCP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:62 msgid "Default DSCP value for UDP packets" -msgstr "" +msgstr "Domyślna wartość DSCP dla pakietów UDP" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:60 msgid "Default timeout for dynamically added entries" -msgstr "" +msgstr "Domyślny limit czasu dla wpisów dodanych dynamicznie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1217 msgid "Defaults" -msgstr "" +msgstr "Domyślne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 msgid "" @@ -428,15 +471,15 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "Urządzenie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." -msgstr "" +msgstr "Sprawdzenie urządzenia zakończone." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1714 msgid "Device check failed: %s" -msgstr "" +msgstr "Sprawdzenie urządzenia nie powiodło się: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:859 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 @@ -446,11 +489,13 @@ msgstr "Wyłączone" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:75 msgid "Downlink bandwidth (same format as tc)" -msgstr "" +msgstr "Przepustowość łącza przychodzącego (w tym samym formacie co w tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Downlink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Przepustowość łącza przychodzącego, ten sam format co tc. Ustawiono tuż " +"poniżej prędkości łącza." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1247 @@ -459,15 +504,15 @@ msgstr "Pobierz" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Download bandwidth" -msgstr "" +msgstr "Przepustowość pobierania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:724 msgid "Download shaping" -msgstr "" +msgstr "Kształtowanie pobierania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1197 msgid "Download the current files from the router." -msgstr "" +msgstr "Pobierz bieżące pliki z routera." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "" @@ -475,10 +520,14 @@ msgid "" "raw value, a codepoint like CS0, or a class name. DNS entries are compared " "in the order in which they are specified, using the first matching entry." msgstr "" +"Każdy wiersz zawiera dwa pola rozdzielone białymi znakami: `match` oraz " +"`dscp`. Pole `dscp` może przyjmować postać wartości surowej, punktu kodowego " +"(np. CS0) lub nazwy klasy. Wpisy są porównywane w kolejności ich " +"zdefiniowania, a system wykorzystuje pierwszy pasujący wpis." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "Egress CAKE options" -msgstr "" +msgstr "Opcje wyjścia CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2020 msgid "Empty file" @@ -488,31 +537,36 @@ msgstr "Pusty plik" msgid "" "Empty the config editor? Nothing is written until you click Save & Apply." msgstr "" +"Opróżnić edytor konfiguracji? Żadne zmiany nie zostaną zapisane, dopóki nie " +"klikniesz „Zapisz i zastosuj”." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "" "Empty the rules editor? Nothing is written until you click Save & Apply." msgstr "" +"Wyczyścić edytor reguł? Żadne zmiany nie zostaną zapisane, dopóki nie " +"klikniesz „Zapisz i zastosuj”." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:80 msgid "Enable CAKE NAT host detection via conntrack" -msgstr "" +msgstr "Włącz wykrywanie hostów NAT CAKE za pomocą conntrack" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:82 msgid "Enable CAKE automatic rate estimation for ingress" msgstr "" +"Włącz automatyczne szacowanie przepustowości CAKE dla ruchu przychodzącego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:81 msgid "Enable CAKE host isolation" -msgstr "" +msgstr "Włącz izolację hostów CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:78 msgid "Enable egress shaping" -msgstr "" +msgstr "Włącz kształtowanie ruchu wychodzącego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:77 msgid "Enable ingress shaping" -msgstr "" +msgstr "Włącz kształtowanie ruchu przychodzącego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 @@ -529,11 +583,11 @@ msgstr "Włączone — brak kształtowania (sprawdź konfigurację)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Encapsulation overhead" -msgstr "" +msgstr "Narzut enkapsulacji" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2182 msgid "Enter a section name." -msgstr "" +msgstr "Wpisz nazwę sekcji." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2156 msgid "Enter a single IPv4 address (qosify does not accept CIDR)." @@ -543,6 +597,8 @@ msgstr "Wpisz pojedynczy adres IPv4 (qosify nie akceptuje CIDR)." msgid "" "Enter a single IPv6 address (qosify does not accept CIDR or a %zone suffix)." msgstr "" +"Wpisz pojedynczy adres IPv6 (qosify nie akceptuje zapisu CIDR ani przyrostka " +"%zone)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2141 msgid "Enter a value." @@ -550,7 +606,7 @@ msgstr "Wpisz wartość." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 msgid "Entries" -msgstr "" +msgstr "Wpisy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1848 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1961 @@ -566,6 +622,8 @@ msgid "" "Error: invalid characters in bandwidth or options fields. Use alphanumeric, " "spaces, hyphens, dots, colons only." msgstr "" +"Błąd: niedozwolone znaki w polach przepustowości lub opcji. Należy używać " +"wyłącznie znaków alfanumerycznych, spacji, myślników, kropek i dwukropków." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1798 msgid "Error: name must be a device or interface name" @@ -577,7 +635,7 @@ msgstr "Błąd: narzut musi być liczbą całkowitą bajtów" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1768 msgid "Error: overhead_mpu must be a whole number of bytes" -msgstr "" +msgstr "Błąd: overhead_mpu musi być liczbą całkowitą określającą liczbę bajtów" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2070 msgid "Errors:" @@ -587,11 +645,11 @@ msgstr "Błędy:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "File" -msgstr "" +msgstr "Plik" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1832 msgid "File changed on disk" -msgstr "" +msgstr "Plik zmieniono na dysku" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2021 msgid "File too large (max 64KB)" @@ -599,7 +657,7 @@ msgstr "Plik jest za duży (maks. 64 KB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:667 msgid "Files" -msgstr "" +msgstr "Pliki" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Found (empty or invalid)" @@ -611,78 +669,84 @@ msgstr "Udziel dostępu do aplikacji LuCI qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:728 msgid "Host isolation" -msgstr "" +msgstr "Izolacja hosta" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1169 msgid "IPv4 address, e.g. 1.1.1.1" -msgstr "" +msgstr "Adres IPv4, np. 1.1.1.1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1170 msgid "IPv6 address, e.g. ff01::1" -msgstr "" +msgstr "Adres IPv6, np. ff01::1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "Ingress CAKE options" -msgstr "" +msgstr "Opcje wejścia CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Interface" -msgstr "" +msgstr "Interfejs" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:741 msgid "Invalid CAKE options can stop qosify starting." -msgstr "" +msgstr "Nieprawidłowe opcje CAKE mogą uniemożliwić uruchomienie qosify." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1173 msgid "Like dns:... but only matches cname entries" -msgstr "" +msgstr "Jak DNS:..., ale dopasowuje tylko wpisy CNAME" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:228 msgid "" "Line %d is longer than 1023 characters — the rule loader reads fixed-size " "lines and would split it, comment included" msgstr "" +"Wiersz nr %d jest dłuższy niż 1023 znaki – moduł wczytujący reguły obsługuje " +"wiersze o stałej długości i podzieliłby go, wliczając w to komentarz" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:59 msgid "List of files with port/IP/host mappings" -msgstr "" +msgstr "Lista plików z mapowaniami portów, adresów IP i hostów" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 msgid "Loading..." -msgstr "" +msgstr "Ładowanie..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1212 msgid "Maintenance" -msgstr "" +msgstr "Konserwacja" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Manual overhead" -msgstr "" +msgstr "Narzut ręczny" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "Mapping file syntax" -msgstr "" +msgstr "Składnia pliku mapowania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1692 msgid "Mapping files reloaded." -msgstr "" +msgstr "Pliki mapowania zostały ponownie załadowany." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:434 msgid "" "Match not loaded by qosify on line %s — ports 1-65534, one IPv4/IPv6 address " "(no CIDR or %%zone), or dns:, dns_c:" msgstr "" +"Reguła nie została wczytana przez qosify w wierszu %s — porty 1–65534, jeden " +"adres IPv4/IPv6 (bez CIDR ani %%zone) lub dns:, dns_c:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:66 msgid "Maximum average packet length for marking a flow as priority" msgstr "" +"Maksymalna średnia długość pakietu dla oznaczenia przepływu jako " +"priorytetowego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Minimum packet unit (MPU)" -msgstr "" +msgstr "Minimalna jednostka pakietu (MPU)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 @@ -692,37 +756,41 @@ msgstr "Brak" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Modified" -msgstr "" +msgstr "Zmodyfikowano" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:433 msgid "" "More than two fields on line %s — qosify reads the rest of the line as the " "DSCP value and skips it" msgstr "" +"Więcej niż dwa pola w wierszu %s — qosify traktuje resztę wiersza jako " +"wartość DSCP i ją pomija" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:727 msgid "NAT awareness" -msgstr "" +msgstr "Obsługa NAT" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Netdev to enable QoS on. Required." -msgstr "" +msgstr "Netdev do włączenia QoS. Wymagane." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No CAKE tin statistics." -msgstr "" +msgstr "Brak statystyk puszek CAKE." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1628 msgid "No DNS entries." -msgstr "" +msgstr "Brak wpisów DNS." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:432 msgid "No DSCP target on line %s — qosify skips single-field lines" msgstr "" +"Brak docelowej wartości DSCP w wierszu %s — qosify pomija wiersze z " +"pojedynczym polem" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1107 msgid "No classes defined in %s" -msgstr "" +msgstr "Nie określono żadnych klas w %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2142 msgid "No classes defined. Add classes in the Config tab first." @@ -732,7 +800,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1191 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1192 msgid "No file selected" -msgstr "" +msgstr "Nie wybrano pliku" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2006 msgid "No files selected." @@ -740,11 +808,11 @@ msgstr "Nie wybrano plików." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No output." -msgstr "" +msgstr "Brak danych wyjściowych." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1568 msgid "No per-class counters." -msgstr "" +msgstr "Brak liczników dla poszczególnych klas." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2154 msgid "No spaces or # allowed in patterns or addresses." @@ -766,17 +834,19 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:67 msgid "Number of packets per second to trigger bulk flow detection" -msgstr "" +msgstr "Liczba pakietów na sekundę wyzwalająca wykrywanie przepływów masowych" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1161 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1174 msgid "Only override the DSCP value if it is zero" -msgstr "" +msgstr "Nadpisuj wartość DSCP tylko wtedy, gdy wynosi ona zero" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:704 msgid "" "Only sent with host isolation on — add nat to common CAKE options to force it" msgstr "" +"Wysyłane tylko przy włączonej izolacji hosta — dodaj nat do typowych opcji " +"CAKE, aby to wymusić" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1017 msgid "Options" @@ -784,11 +854,11 @@ msgstr "Opcje" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:730 msgid "Overhead" -msgstr "" +msgstr "Narzut" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "Overhead preset" -msgstr "" +msgstr "Ustawienie wstępne narzutu" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:603 msgid "Overview" @@ -796,17 +866,20 @@ msgstr "Przegląd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1834 msgid "Overwrite" -msgstr "" +msgstr "Nadpisz" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2007 msgid "Overwrite config files" -msgstr "" +msgstr "Nadpisz pliki konfiguracyjne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1172 msgid "" "POSIX.2 extended regular expression for matching hostnames. Only works if " "dns lookups are passed to qosify via the add_dns_host ubus call." msgstr "" +"Rozszerzone wyrażenie regularne POSIX.2 służące do dopasowywania nazw " +"hostów. Działa tylko wtedy, gdy wyniki wyszukiwania DNS są przekazywane do " +"qosify za pośrednictwem wywołania ubus `add_dns_host`." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2150 msgid "Port must be 1-65534 (qosify rejects 65535)." @@ -815,7 +888,7 @@ msgstr "Port musi być 1-65534 (qosify odrzuca port 65535)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2149 msgid "Port must be a number or a range (4500, 5060-5061)." -msgstr "" +msgstr "Port musi być liczbą lub zakresem (4500, 5060-5061)." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "QoS Enabled" @@ -823,15 +896,15 @@ msgstr "QoS włączono" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:721 msgid "Queueing mode" -msgstr "" +msgstr "Tryb kolejkowania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1163 msgid "Quick Add" -msgstr "" +msgstr "Szybkie dodawanie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1016 msgid "Quick Add: %s" -msgstr "" +msgstr "Szybkie dodawanie: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2153 msgid "Range start must not exceed end." @@ -839,19 +912,19 @@ msgstr "Początek zakresu nie może przekraczać końca." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1213 msgid "Re-check devices" -msgstr "" +msgstr "Sprawdź ponownie urządzenia" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1707 msgid "Re-checking devices..." -msgstr "" +msgstr "Ponowne sprawdzanie urządzeń..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:768 msgid "Re-read the mapping files only" -msgstr "" +msgstr "Ponownie odczytaj tylko pliki mapowania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1690 msgid "Re-reading the mapping files..." -msgstr "" +msgstr "Ponowne odczytanie plików mapowania..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1215 msgid "" @@ -860,6 +933,11 @@ msgid "" "is stopped. Nothing is reported back by the call — the result shows in the " "Service table on the Overview tab." msgstr "" +"Ponownie uruchamia własny przebieg urządzenia demona: każda sekcja o " +"określonym kształcie jest ponownie wyszukiwana, uruchamiana jest sekcja, " +"której urządzenie istnieje, a sekcja, której urządzenie zniknęło, jest " +"zatrzymywana. Wywołanie nie zwraca żadnych informacji — wynik jest " +"wyświetlany w tabeli Usługa na karcie Przegląd." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2024 msgid "Read error" @@ -871,11 +949,11 @@ msgstr "Odczytywanie i sprawdzanie poprawności plików..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1681 msgid "Reading tc output..." -msgstr "" +msgstr "Odczytywanie danych wyjściowych tc..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1019 msgid "Reference" -msgstr "" +msgstr "Odniesienie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload" @@ -883,20 +961,20 @@ msgstr "Przeładuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload Rules" -msgstr "" +msgstr "Przeładuj reguły" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1695 msgid "Reload failed: %s" -msgstr "" +msgstr "Przeładowanie nie powiodło się: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "Requires write access." -msgstr "" +msgstr "Wymaga uprawnień do zapisu." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1219 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2086 msgid "Reset" -msgstr "" +msgstr "Resetuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2120 msgid "Reset failed: %s" @@ -904,7 +982,7 @@ msgstr "Resetowanie nie powiodło się: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2084 msgid "Reset to defaults" -msgstr "" +msgstr "Resetuj do ustawień domyślnych" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2116 msgid "Reset to defaults, applied." @@ -920,11 +998,11 @@ msgstr "Restartuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1203 msgid "Restore" -msgstr "" +msgstr "Przywróć" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1218 msgid "Restore qosify defaults" -msgstr "" +msgstr "Przywróć domyślne ustawienia qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2095 msgid "Restoring defaults..." @@ -932,7 +1010,7 @@ msgstr "Przywracanie ustawień domyślnych..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:605 msgid "Rules" -msgstr "" +msgstr "Reguły" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1976 msgid "Rules saved" @@ -953,7 +1031,7 @@ msgstr "Uruchomione — nie kształtuje" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:867 msgid "Running — Shaping Unknown" -msgstr "" +msgstr "Uruchomione — kształtowanie nieznanego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:753 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1147 @@ -986,6 +1064,9 @@ msgid "" "Section name is the class name that rules and dscp_* values refer to. " "qosify.init reads config alias the same way as config class." msgstr "" +"Nazwa sekcji to nazwa klasy, do której odnoszą się reguły oraz wartości " +"dscp_*. qosify.init traktuje alias konfiguracji tak samo jak klasę " +"konfiguracji." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1724 msgid "Sending %s to qosify..." @@ -993,23 +1074,23 @@ msgstr "Wysyłanie %s do qosify..." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Sent to CAKE as atm, noatm or ptm." -msgstr "" +msgstr "Wysłano do CAKE jako atm, noatm lub ptm." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "Sent to CAKE as ether-vlan, once per tag." -msgstr "" +msgstr "Wysłano do CAKE jako ether-vlan, raz na znacznik." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Sent to CAKE as mpu, in bytes." -msgstr "" +msgstr "Wysłano do CAKE jako mpu, w bajtach." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Sent to CAKE as overhead, in bytes." -msgstr "" +msgstr "Wysłane do CAKE jako narzut, w bajtach." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:663 msgid "Service" -msgstr "" +msgstr "Usługa" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1745 msgid "Service action failed: %s" @@ -1022,16 +1103,16 @@ msgstr "Ustawienia zapisano" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:723 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:894 msgid "Shaping" -msgstr "" +msgstr "Kształtowanie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "Rozmiar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" -msgstr "" +msgstr "Pomiń tę sekcję" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:764 msgid "Start" @@ -1045,7 +1126,7 @@ msgstr "Status" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:855 msgid "Status Unknown" -msgstr "" +msgstr "Status nieznany" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:766 msgid "Stop" @@ -1053,40 +1134,51 @@ msgstr "Zatrzymaj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1167 msgid "TCP single port, or range from to " -msgstr "" +msgstr "Pojedynczy port TCP lub zakres od do " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1680 msgid "The detailed tc output needs write access to this page." msgstr "" +"Szczegółowe dane wyjściowe polecenia tc wymagają uprawnień do zapisu na tej " +"stronie." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:590 msgid "" "The qosify UCI configuration could not be loaded — class and interface lists " "may be incomplete." msgstr "" +"Nie udało się wczytać konfiguracji UCI dla qosify — listy klas i interfejsów " +"mogą być niekompletne." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1204 msgid "" "The selected files replace the ones on the router and qosify is reloaded." msgstr "" +"Wybrane pliki zastępują te znajdujące się w routerze, a qosify jest ponownie " +"ładowane." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2008 msgid "" "The selected files replace the ones on the router and qosify is reloaded. " "Download a backup from this tab first if you need one." msgstr "" +"Wybrane pliki zastępują te znajdujące się w routerze, a qosify jest ponownie " +"ładowane. Jeśli potrzebujesz kopii zapasowej, pobierz ją najpierw z tej " +"karty." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:68 msgid "Time below bulk_trigger_pps threshold until a bulk flow mark is removed" msgstr "" +"Czas utrzymywania się poniżej progu bulk_trigger_pps do momentu usunięcia " +"znacznika przepływu masowego" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 msgid "Traffic by CAKE Tin" -msgstr "" +msgstr "Ruch wg puszki CAKE" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1401 msgid "Traffic by Class" -msgstr "" +msgstr "Ruch wg klasy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:596 msgid "Traffic shaping and DSCP classification via qosify" @@ -1094,13 +1186,13 @@ msgstr "Kształtowanie ruchu i klasyfikacja DSCP za pomocą qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1168 msgid "UDP single port, or range from to " -msgstr "" +msgstr "Pojedynczy port UDP lub zakres od do " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:864 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:866 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:925 msgid "Unknown" -msgstr "" +msgstr "Nieznany" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "Unknown class/DSCP target: %s" @@ -1109,30 +1201,34 @@ msgstr "Nieznana klasa/cel DSCP: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "Unticked sets disabled 1 and qosify skips this section." msgstr "" +"Odznaczenie zestawów powoduje wyłączenie opcji „1”, a mechanizm QoS pomija " +"tę sekcję." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:74 msgid "Uplink bandwidth (same format as tc)" -msgstr "" +msgstr "Przepustowość łącza wychodzącego (w tym samym formacie co w tc)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Uplink bandwidth, same format as tc. Set just below line speed." msgstr "" +"Przepustowość łącza wychodzącego, ten sam format co tc. Ustawiono tuż " +"poniżej prędkości łącza." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "Upload" -msgstr "" +msgstr "Wysyłanie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1210 msgid "Upload & Apply" -msgstr "" +msgstr "Wyślij i zastosuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2009 msgid "Upload and apply" -msgstr "" +msgstr "Wyślij i zastosuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Upload bandwidth" -msgstr "" +msgstr "Przepustowość wysyłania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2061 msgid "Upload error: %s" @@ -1144,7 +1240,7 @@ msgstr "Nie udało się przesłać: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:725 msgid "Upload shaping" -msgstr "" +msgstr "Kształtowanie wysyłania" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2035 msgid "Uploading" @@ -1152,11 +1248,11 @@ msgstr "Przesyłanie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:892 msgid "Uptime" -msgstr "" +msgstr "Czas pracy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "VLAN tags" -msgstr "" +msgstr "Znaczniki VLAN" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Valid" @@ -1175,7 +1271,7 @@ msgstr "Pracuje" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "Write empty file" -msgstr "" +msgstr "Utwórz pusty plik" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1906 msgid "Writing config and reloading qosify..." @@ -1190,42 +1286,52 @@ msgid "" "You have read-only access to this page, so editing and service control are " "disabled." msgstr "" +"Masz dostęp do tej strony tylko do odczytu, więc edycja oraz sterowanie " +"usługą są wyłączone." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "active" -msgstr "" +msgstr "aktywne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1767 msgid "" "bandwidth_down does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_down nie wygląda na parametr szybkości tc (100mbit, 12MBps, " +"unlimited) — mimo to przekazuję go dalej" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1766 msgid "" "bandwidth_up does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" msgstr "" +"bandwidth_up nie wygląda na parametr szybkości tc (100mbit, 12MBps, " +"unlimited) — mimo to przekazuję go dalej" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1012 msgid "" "config device takes the same options, with name set to a netdev. nat " "defaults to 1 for interfaces and 0 for devices." msgstr "" +"konfiguracja urządzenia przyjmuje te same opcje, przy czym jako nazwę należy " +"podać netdev. Domyślną wartością nat jest 1 dla interfejsów i 0 dla urządzeń." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "device %s" -msgstr "" +msgstr "urządzenie %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "device: %s, ingress: %s, egress: %s" -msgstr "" +msgstr "urządzenie: %s, ruch przychodzący: %s, ruch wychodzący: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:289 msgid "" "disabled is set to \"%s\" — config_get_bool does not recognise that, so the " "section stays enabled" msgstr "" +"disabled ma wartość „%s” — funkcja config_get_bool tego nie rozpoznaje, więc " +"sekcja pozostaje włączona" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 @@ -1235,23 +1341,23 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2129 msgid "e.g. %s" -msgstr "" +msgstr "np. %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1171 msgid "fnmatch() pattern supporting * and ? as wildcard characters" -msgstr "" +msgstr "Wzorzec fnmatch() obsługujący znaki wieloznaczne * oraz ?" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1613 msgid "get_stats did not answer." -msgstr "" +msgstr "get_stats nie odpowiedziało." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "inactive" -msgstr "" +msgstr "nieaktywne" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "ingress %s, egress %s" -msgstr "" +msgstr "ruch przychodzący %s, ruch wychodzący %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:282 msgid "ingress and egress are both 0 — nothing is shaped" @@ -1259,11 +1365,11 @@ msgstr "wejście i wyjście są równe 0 — nic nie jest kształtowane" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "interface %s" -msgstr "" +msgstr "interfejs %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1155 msgid "match" -msgstr "" +msgstr "dopasuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:274 msgid "" @@ -1294,14 +1400,16 @@ msgid "" "netifd interface (config interface) or netdev (config device) to enable QoS " "on" msgstr "" +"Interfejs netifd (interfejs konfiguracyjny) lub netdev (urządzenie " +"konfiguracyjne) w celu włączenia QoS" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "netifd interface to enable QoS on. Required." -msgstr "" +msgstr "Interfejs netifd, na którym należy włączyć QoS. Wymagane." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "no" -msgstr "" +msgstr "nie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:284 msgid "no bandwidth_down or bandwidth — ingress CAKE runs unlimited" @@ -1313,7 +1421,7 @@ msgstr "brak bandwidth_up lub bandwidth — wyjście CAKE działa bez ogranicze #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "none" -msgstr "" +msgstr "brak" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:281 msgid "overhead and overhead_encap are ignored unless overhead_type is manual" @@ -1329,21 +1437,23 @@ msgstr "qosify" msgid "" "qosify did not appear on ubus, so its config was not applied — press Reload" msgstr "" +"qosify nie pojawiło się w ubus, więc jego konfiguracja nie została " +"zastosowana — naciśnij Przeładuj" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:833 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1729 msgid "qosify did not come up — check the system log" -msgstr "" +msgstr "qosify nie uruchomiło się – sprawdź dziennik systemowy" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1610 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1672 msgid "qosify is not running. Start from the Overview tab." -msgstr "qosify jest nieuruchomiony. Rozpocznij od karty „Przegląd”." +msgstr "qosify jest nieuruchomione. Rozpocznij od karty „Przegląd”." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1735 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1887 msgid "qosify is still running — leaving the qdiscs alone" -msgstr "" +msgstr "qosify nadal działa — qdiscs pozostają nienaruszone" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" @@ -1358,6 +1468,8 @@ msgid "" "rpcd is not answering for qosify — check the ACL in /usr/share/rpcd/acl.d " "and restart rpcd" msgstr "" +"rpcd nie odpowiada na żądania qosify — sprawdź listę ACL w /usr/share/rpcd/" +"acl.d i zrestartuj rpcd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:832 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1609 @@ -1366,32 +1478,32 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1734 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1886 msgid "rpcd is not answering for qosify, so the service state is unknown." -msgstr "" +msgstr "rpcd nie odpowiada qosify, więc stan usługi jest nieznany." #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:955 msgid "section name" -msgstr "" +msgstr "nazwa sekcji" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:953 msgid "section type" -msgstr "" +msgstr "typ sekcji" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1529 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1533 msgid "share" -msgstr "" +msgstr "udział" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1541 msgid "total" -msgstr "" +msgstr "łącznie" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 msgid "value" -msgstr "" +msgstr "wartość" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "yes" -msgstr "" +msgstr "tak" #~ msgid "%s contains a quote — qosify rejects the whole value" #~ msgstr "%s zawiera cudzysłów — qosify odrzuca całą wartość" diff --git a/luci-app-qosify/po/pt/qosify.po b/luci-app-qosify/po/pt/qosify.po index a79c39d0f..8ab77c011 100644 --- a/luci-app-qosify/po/pt/qosify.po +++ b/luci-app-qosify/po/pt/qosify.po @@ -3,9 +3,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Language: pt\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"Last-Translator: Pavel Borecki \n" +"Language-Team: Portuguese \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" +"PO-Revision-Date: 2026-09-29 12:10+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" @@ -204,7 +207,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" -msgstr "" +msgstr "Disponível" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" @@ -261,7 +264,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "Cancelar" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" @@ -416,7 +419,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "Dispositivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." @@ -430,7 +433,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 msgid "Disabled" -msgstr "" +msgstr "Desativado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:75 msgid "Downlink bandwidth (same format as tc)" @@ -505,7 +508,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 msgid "Enabled" -msgstr "" +msgstr "Ativado" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:858 msgid "Enabled — Not Running" @@ -1012,7 +1015,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "Tamanho" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" @@ -1324,7 +1327,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" -msgstr "" +msgstr "qosify-status" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1682 msgid "qosify-status returned no output." diff --git a/luci-app-qosify/po/pt_BR/qosify.po b/luci-app-qosify/po/pt_BR/qosify.po index d5146ea92..9d4cbc1ea 100644 --- a/luci-app-qosify/po/pt_BR/qosify.po +++ b/luci-app-qosify/po/pt_BR/qosify.po @@ -3,12 +3,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Language: pt_BR\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: Martin Olmer \n" +"Last-Translator: Pavel Borecki \n" "Language-Team: Portuguese (Brazil) \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"PO-Revision-Date: 2026-09-02 07:51+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-29 17:59+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" @@ -207,7 +207,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" -msgstr "" +msgstr "Disponível" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" @@ -419,7 +419,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "Dispositivo" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." @@ -1015,7 +1015,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "Tamanho" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" @@ -1303,7 +1303,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:595 #: applications/luci-app-qosify/root/usr/share/luci/menu.d/luci-app-qosify.json:3 msgid "qosify" -msgstr "" +msgstr "qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:847 msgid "" @@ -1327,7 +1327,7 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" -msgstr "" +msgstr "qosify-status" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1682 msgid "qosify-status returned no output." diff --git a/luci-app-qosify/po/ru/qosify.po b/luci-app-qosify/po/ru/qosify.po index 3c6fbf4b9..5f0bb4a33 100644 --- a/luci-app-qosify/po/ru/qosify.po +++ b/luci-app-qosify/po/ru/qosify.po @@ -9,22 +9,22 @@ msgstr "" "luciapplicationsqosify/ru/>\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" -"PO-Revision-Date: 2026-08-28 22:28+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-28 18:23+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" msgid_plural "%d interfaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d интерфейс" +msgstr[1] "%d интерфейса" +msgstr[2] "%d интерфейсов" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d правило" +msgstr[1] "%d правила" +msgstr[2] "%d правил" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" diff --git a/luci-app-qosify/po/zh_Hans/qosify.po b/luci-app-qosify/po/zh_Hans/qosify.po index 30c3a39eb..771b2786a 100644 --- a/luci-app-qosify/po/zh_Hans/qosify.po +++ b/luci-app-qosify/po/zh_Hans/qosify.po @@ -8,84 +8,84 @@ msgstr "" "Language-Team: Chinese (Simplified Han script) \n" "Plural-Forms: nplurals=1; plural=0;\n" -"PO-Revision-Date: 2026-08-17 17:59+0000\n" -"X-Generator: Weblate 2026.9.dev0\n" +"PO-Revision-Date: 2026-09-29 12:10+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "%d interface" msgid_plural "%d interfaces" -msgstr[0] "" +msgstr[0] "%d 个接口" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:943 msgid "%d rule" msgid_plural "%d rules" -msgstr[0] "" +msgstr[0] "%d 条规则" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:942 msgid "%d section" msgid_plural "%d sections" -msgstr[0] "" +msgstr[0] "%d 个选中" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:682 msgid "%s (current)" -msgstr "" +msgstr "%s (当前)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 msgid "%s (from bandwidth)" -msgstr "" +msgstr "%s (来自带宽)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2085 msgid "" "%s and %s are replaced with the templates shipped by the qosify package, and " "shaping is left disabled." -msgstr "" +msgstr "qosify 包内置的模板替换了 %s 和 %s,流量整形被禁用。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1809 msgid "" "%s came back empty although it is %d bytes on disk — refusing to overwrite it" -msgstr "" +msgstr "%s 在磁盘上大小为 %d 字节,但返回大小为空 — 拒绝覆盖它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2346 msgid "%s changed on disk — your unsaved edits are still in the editor." -msgstr "" +msgstr "%s 在磁盘上已改变 — 未保存的编辑仍在编辑器中。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2249 msgid "" "%s could not be read — the editor is left empty and will not be saved over " "it." -msgstr "" +msgstr "%s 无法读取 — 编辑器无内容,不会覆盖保存。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1833 msgid "" "%s has changed since this editor was loaded. Saving now discards those " "changes." -msgstr "" +msgstr "%s 自该编辑器加载以来已更改。立刻保存会丢弃这些更改。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1864 msgid "" "%s is %d bytes on disk but was never loaded into the editor — refusing to " "truncate it. Reload the page first." -msgstr "" +msgstr "%s 在磁盘上大小为 %d 字节— 拒绝截断它。请先重新加载页面。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:364 msgid "%s is a list in this section — edit %s directly" -msgstr "" +msgstr "%s 是该部分的一个列表 — 直接编辑 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1656 msgid "" "%s is not in the defaults list — qosify does not load it, so the Rules tab " "has no effect" -msgstr "" +msgstr "%s 不在默认列表中— qosify 不加载它,因此规则标签页无效果" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:286 msgid "" "%s is set to \"%s\" — qosify converts it with atoi(), so anything but a non-" "zero number means off" -msgstr "" +msgstr "%s 设为 \"%s\" — qosify 用 atoi() 转换它,因此仅非零数字表示开启" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:750 msgid "%s quick settings" -msgstr "" +msgstr "%s 快速设置" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2069 msgid "%s uploaded, qosify reloaded." @@ -93,11 +93,11 @@ msgstr "%s 已上传, qosify 已重载。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2103 msgid "%s was not written: %s" -msgstr "" +msgstr "%s 未被写入: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2106 msgid "%s was reset but %s was not written: %s" -msgstr "" +msgstr "%s 被重置 %s 未被写入: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1945 msgid "%s, applied (QoS disabled)." @@ -106,7 +106,7 @@ msgstr "%s, 已应用 (已禁用 QoS)。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1950 msgid "" "%s, applied — qosify did not answer on ubus, so shaping could not be checked." -msgstr "" +msgstr "%s, 已应用 — qosify 未响响应 ubus,因此无法检查流量整形。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1947 msgid "%s, applied." @@ -115,31 +115,33 @@ msgstr "%s, 已应用。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:459 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:468 msgid "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify ignores it" -msgstr "" +msgstr "%s: %s \"%s\" 不是类、代码点或 0-63 — qosify 忽略它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:456 msgid "" "%s: %s \"%s\" is not a class, codepoint or 0-63 — qosify rejects the whole " "config and interface changes are not applied" -msgstr "" +msgstr "%s: %s \"%s\" 不是类、代码点或 0-63 — qosify 拒绝整个配置,接口更改未应用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:465 msgid "" "%s: %s \"%s\" is not a codepoint or 0-63 — qosify drops this class and the " "rules using it" -msgstr "" +msgstr "%s: %s \"%s\" 不是代码点或 0-63 — qosify 丢弃该类和使用它的规则" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:448 msgid "" "%s: %s cannot be checked — write it as one plain or fully quoted value, with " "no backslash" -msgstr "" +msgstr "%s: 无法检查 %s— 将其写成纯文本或前后带引号的值,没有反斜杠" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:451 msgid "" "%s: %s contains shell metacharacters — qosify runs the tc command with sh -c " "as root, so they would break it or be executed" msgstr "" +"%s: %s 包含 shell 元字符— qosify 用 sh -c 以 root 用户身份运行 tc 命令,因此" +"它们会破坏或执行该命令" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "(alias)" @@ -147,7 +149,7 @@ msgstr "(别名)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "(this qosify build has no NQB)" -msgstr "" +msgstr "(这个 qosify 版本没有 NQB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2185 msgid "A config defaults section already exists." @@ -155,7 +157,7 @@ msgstr "已存在一个配置默认部分。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2183 msgid "A section name may only contain letters, digits and underscores." -msgstr "" +msgstr "部分名称只能含字母、数字和下划线。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:856 msgid "Active" @@ -168,19 +170,19 @@ msgstr "添加" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:85 msgid "Adds atm, noatm or ptm when overhead_type is manual" -msgstr "" +msgstr "overhead_type 为手动时添加 atm、noatm 或 ptm" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:87 msgid "Adds ether-vlan once per level (1 or 2)" -msgstr "" +msgstr "每个层级(1 或 2)添加一次 ether-vlan" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:86 msgid "Adds mpu " -msgstr "" +msgstr "添加 mpu " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:84 msgid "Adds overhead when overhead_type is manual" -msgstr "" +msgstr "当 overhead_type 为手动时添加 overhead " #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:608 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:737 @@ -189,11 +191,11 @@ msgstr "高级" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "An empty %s stops all shaping. Continue?" -msgstr "" +msgstr "一个空的 %s 停止所有整形。继续吗?" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:726 msgid "Automatic download rate" -msgstr "" +msgstr "自动下载速率" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:893 msgid "Autostart" @@ -201,7 +203,7 @@ msgstr "自启动" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:924 msgid "Autostart state unknown — rpcd did not answer" -msgstr "" +msgstr "自启动状态未知 — rpcd 未应答" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 msgid "Available" @@ -209,17 +211,17 @@ msgstr "可用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1196 msgid "Backup" -msgstr "" +msgstr "备份" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:76 msgid "" "Bandwidth for both directions, where bandwidth_up or bandwidth_down is not " "set" -msgstr "" +msgstr "双向带宽,bandwidth_up 或 bandwidth_down 均未设置" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:716 msgid "Basic" -msgstr "" +msgstr "基础" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:224 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2029 @@ -228,57 +230,57 @@ msgstr "拒绝了二进制内容" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:79 msgid "CAKE diffserv mode" -msgstr "" +msgstr "CAKE diffserv 模式" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:89 msgid "CAKE egress options" -msgstr "" +msgstr "CAKE 出口选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "CAKE egress options, space separated." -msgstr "" +msgstr "CAKE 出口选项,空格隔开。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:88 msgid "CAKE ingress options" -msgstr "" +msgstr "CAKE 入口选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "CAKE ingress options, space separated." -msgstr "" +msgstr "CAKE 入口选项,空格隔开。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:90 msgid "CAKE options for ingress + egress" -msgstr "" +msgstr "CAKE 出口+入口选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:83 msgid "" "CAKE overhead keyword added to options; manual uses overhead and " "overhead_encap" -msgstr "" +msgstr "已添加 CAKE overhead 关键词到选项;手动使用 overhead 和 overhead_encap" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "CAKE overhead keyword. Use none if unsure." -msgstr "" +msgstr "CAKE overhead 关键词。如不确定使用 none。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:564 msgid "Cancel" -msgstr "" +msgstr "取消" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1214 msgid "Check Devices" -msgstr "" +msgstr "检查设备" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1193 msgid "Choose file…" -msgstr "" +msgstr "选择文件…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1114 msgid "Classes" -msgstr "" +msgstr "类" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1737 msgid "Cleanup exited with code %d" -msgstr "" +msgstr "清理已退出,代码 %d" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 @@ -288,12 +290,12 @@ msgstr "清除" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1869 msgid "Clear configuration" -msgstr "" +msgstr "配置清理" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "Clear editor" -msgstr "" +msgstr "清理编辑器" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:929 msgid "Click to disable autostart" @@ -305,7 +307,7 @@ msgstr "单击启用自启动" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:740 msgid "Common CAKE options" -msgstr "" +msgstr "常见 CAKE 选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:604 msgid "Config" @@ -317,7 +319,7 @@ msgstr "已清空配置,qosify 已停止。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1894 msgid "Config cleared." -msgstr "" +msgstr "配置已清理。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1915 msgid "Config saved" @@ -330,28 +332,28 @@ msgstr "配置:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:566 msgid "Continue" -msgstr "" +msgstr "继续" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1245 msgid "Could not read %s: %s" -msgstr "" +msgstr "无法读取 %s: %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:607 msgid "Counters" -msgstr "" +msgstr "计数器" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1627 msgid "DNS Entries" -msgstr "" +msgstr "DNS 条目" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d of %d)" -msgstr "" +msgstr "DNS 条目 (%d,共 %d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1364 msgid "DNS Entries (%d)" -msgstr "" +msgstr "DNS 条目 (%d)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "" @@ -360,51 +362,54 @@ msgid "" "accepted too, and any dscp_* value may also name a class. Prefix with + to " "override only when the DSCP field is zero." msgstr "" +"DSCP 代码点: CS0–CS7, AF11–AF43, EF, VA, NQB, LE, DF (NQB 从 26 年 6 月起需" +"要 qosify; 24.10 和 25.12 没有 qosify). 也接受0~63的原始值,任何 dscp_* 值也" +"可以命名一个类。仅在 DSCP 字段为 0 时在开头加 + 来绕过。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:63 msgid "DSCP value for ICMP packets" -msgstr "" +msgstr "ICMP 包的 DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:65 msgid "DSCP value for bulk-marked packets" -msgstr "" +msgstr "批量标记的数据包的 DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:71 msgid "DSCP value for egress" -msgstr "" +msgstr "DSCP 出口值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:70 msgid "DSCP value for ingress" -msgstr "" +msgstr "DSCP 入口值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:69 msgid "DSCP value for ingress and egress, where they are not set" -msgstr "" +msgstr "未设置 DSCP 出口值和入口值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:64 msgid "DSCP value for priority-marked packets" -msgstr "" +msgstr "优先级标记数据包的 DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1021 msgid "DSCP values" -msgstr "" +msgstr "DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:61 msgid "Default DSCP value for TCP packets" -msgstr "" +msgstr "TCP 数据包的默认 DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:62 msgid "Default DSCP value for UDP packets" -msgstr "" +msgstr "UDP 包的默认 DSCP 值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:60 msgid "Default timeout for dynamically added entries" -msgstr "" +msgstr "动态添加条目的默认超时" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1217 msgid "Defaults" -msgstr "" +msgstr "默认" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1022 msgid "" @@ -421,15 +426,15 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Device" -msgstr "" +msgstr "设备" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1711 msgid "Device check done." -msgstr "" +msgstr "设备检查已完成。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1714 msgid "Device check failed: %s" -msgstr "" +msgstr "设备检查失败:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:859 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 @@ -439,11 +444,11 @@ msgstr "已禁用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:75 msgid "Downlink bandwidth (same format as tc)" -msgstr "" +msgstr "下行链路带宽(与 tc 格式相同)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Downlink bandwidth, same format as tc. Set just below line speed." -msgstr "" +msgstr "下行链路带宽,与 tc 格式相同。就在线路速度下方设置。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1247 @@ -452,15 +457,15 @@ msgstr "下载" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:720 msgid "Download bandwidth" -msgstr "" +msgstr "下载带宽" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:724 msgid "Download shaping" -msgstr "" +msgstr "下载整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1197 msgid "Download the current files from the router." -msgstr "" +msgstr "从路由器下载当前文件。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "" @@ -468,10 +473,12 @@ msgid "" "raw value, a codepoint like CS0, or a class name. DNS entries are compared " "in the order in which they are specified, using the first matching entry." msgstr "" +"每行包含两个以空格分隔的字段:match 和 dscp。dscp 可以是原始值、代码点(例如 " +"CS0)或类名。DNS 条目按照指定的顺序进行比较,使用第一个匹配的条目。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:739 msgid "Egress CAKE options" -msgstr "" +msgstr "出口 CAKE 选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2020 msgid "Empty file" @@ -480,32 +487,32 @@ msgstr "空文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1990 msgid "" "Empty the config editor? Nothing is written until you click Save & Apply." -msgstr "" +msgstr "清空配置编辑器?单击保存并应用前不会写入任何东西。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1996 msgid "" "Empty the rules editor? Nothing is written until you click Save & Apply." -msgstr "" +msgstr "清空规则编辑器?单击保存并应用前不会写入任何东西。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:80 msgid "Enable CAKE NAT host detection via conntrack" -msgstr "" +msgstr "通过 conntrack 启用 CAKE NAT 主机检测" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:82 msgid "Enable CAKE automatic rate estimation for ingress" -msgstr "" +msgstr "为入口启用 CAKE 自动速率预测" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:81 msgid "Enable CAKE host isolation" -msgstr "" +msgstr "启用 CAKE 主机隔离" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:78 msgid "Enable egress shaping" -msgstr "" +msgstr "启用出口整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:77 msgid "Enable ingress shaping" -msgstr "" +msgstr "启用入口整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:881 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:930 @@ -522,11 +529,11 @@ msgstr "已启用 — 未在整形流量(检查配置)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Encapsulation overhead" -msgstr "" +msgstr "封装开销" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2182 msgid "Enter a section name." -msgstr "" +msgstr "输入部分名称。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2156 msgid "Enter a single IPv4 address (qosify does not accept CIDR)." @@ -535,7 +542,7 @@ msgstr "输入单个 IPv4 地址(qosify 不接受 CIDR)。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2159 msgid "" "Enter a single IPv6 address (qosify does not accept CIDR or a %zone suffix)." -msgstr "" +msgstr "输入单个 IPv6 地址(qosify 不接受 CIDR 或 %zone 后缀)。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2141 msgid "Enter a value." @@ -543,7 +550,7 @@ msgstr "输入一个值。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 msgid "Entries" -msgstr "" +msgstr "条目" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1848 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1961 @@ -558,7 +565,7 @@ msgstr "错误:未找到哟小的配置段。" msgid "" "Error: invalid characters in bandwidth or options fields. Use alphanumeric, " "spaces, hyphens, dots, colons only." -msgstr "" +msgstr "错误:带宽或选项字段中的无效字符。仅使用字母数字、空格、连字符、点、冒号。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1798 msgid "Error: name must be a device or interface name" @@ -570,7 +577,7 @@ msgstr "错误:开销必须是整数字节" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1768 msgid "Error: overhead_mpu must be a whole number of bytes" -msgstr "" +msgstr "错误:overhead_mpu 必须是整数字节" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2070 msgid "Errors:" @@ -580,11 +587,11 @@ msgstr "错误:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "File" -msgstr "" +msgstr "文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1832 msgid "File changed on disk" -msgstr "" +msgstr "文件在磁盘上已更改" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2021 msgid "File too large (max 64KB)" @@ -592,7 +599,7 @@ msgstr "文件太大(最大 64KB)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:667 msgid "Files" -msgstr "" +msgstr "文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Found (empty or invalid)" @@ -604,78 +611,80 @@ msgstr "授予对 LuCI 应用 qosify 的访问权" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:728 msgid "Host isolation" -msgstr "" +msgstr "主机隔离" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1169 msgid "IPv4 address, e.g. 1.1.1.1" -msgstr "" +msgstr "IPv4 地址,如 1.1.1.1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1156 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1170 msgid "IPv6 address, e.g. ff01::1" -msgstr "" +msgstr "IPv6 地址,如 ff01::1" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:738 msgid "Ingress CAKE options" -msgstr "" +msgstr "入口 CAKE 选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Interface" -msgstr "" +msgstr "接口" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:741 msgid "Invalid CAKE options can stop qosify starting." -msgstr "" +msgstr "无效 CAKE 选项可能阻止 qosify 启动。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1173 msgid "Like dns:... but only matches cname entries" -msgstr "" +msgstr "类似 dns:... 但只匹配 cname 条目" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:228 msgid "" "Line %d is longer than 1023 characters — the rule loader reads fixed-size " "lines and would split it, comment included" -msgstr "" +msgstr "第 %d 行超过 1023 个字符 - 规则加载器读取固定大小的行数并分割它,包括注释" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:59 msgid "List of files with port/IP/host mappings" -msgstr "" +msgstr "含端口/IP/主机映射的文件的列表" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1404 msgid "Loading..." -msgstr "" +msgstr "加载中…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1212 msgid "Maintenance" -msgstr "" +msgstr "维护" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Manual overhead" -msgstr "" +msgstr "手动开销" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1166 msgid "Mapping file syntax" -msgstr "" +msgstr "映射文件语法" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1692 msgid "Mapping files reloaded." -msgstr "" +msgstr "已重新加载映射文件。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:434 msgid "" "Match not loaded by qosify on line %s — ports 1-65534, one IPv4/IPv6 address " "(no CIDR or %%zone), or dns:, dns_c:" msgstr "" +"qosify 未在第 %s 行加载匹配 — 端口 1-65534,一个 IPv4/IPv6 地址(无 CIDR 或 " +"%%zone),或 dns:,dns_c:" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:66 msgid "Maximum average packet length for marking a flow as priority" -msgstr "" +msgstr "将数据流标记为优先的最大平均数据包长度" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Minimum packet unit (MPU)" -msgstr "" +msgstr "最小数据包单位(MPU)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:883 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 @@ -685,37 +694,37 @@ msgstr "缺失" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Modified" -msgstr "" +msgstr "已修改" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:433 msgid "" "More than two fields on line %s — qosify reads the rest of the line as the " "DSCP value and skips it" -msgstr "" +msgstr "第 %s 行上有超过 2 个字段 — qosify 将剩余行读取为 DSCP 值并跳过它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:727 msgid "NAT awareness" -msgstr "" +msgstr "NAT 感知" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "Netdev to enable QoS on. Required." -msgstr "" +msgstr "启用 QoS 的 Netdev。必需。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No CAKE tin statistics." -msgstr "" +msgstr "无 CAKE tin 统计数字。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1628 msgid "No DNS entries." -msgstr "" +msgstr "无 DNS 条目。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:432 msgid "No DSCP target on line %s — qosify skips single-field lines" -msgstr "" +msgstr "第 %s 行上无 DSCP 目标 — qosify 跳过单字段行" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1107 msgid "No classes defined in %s" -msgstr "" +msgstr "%s 中未定义类" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2142 msgid "No classes defined. Add classes in the Config tab first." @@ -724,7 +733,7 @@ msgstr "未定义类。先在配置标签页中添加类。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1191 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1192 msgid "No file selected" -msgstr "" +msgstr "未选中文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2006 msgid "No files selected." @@ -732,11 +741,11 @@ msgstr "未选中文件。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "No output." -msgstr "" +msgstr "无输出。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1568 msgid "No per-class counters." -msgstr "" +msgstr "无每个类计数器。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2154 msgid "No spaces or # allowed in patterns or addresses." @@ -756,17 +765,17 @@ msgstr "注:未设置带宽 — CAKE 在那个方向上运行不受限。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:67 msgid "Number of packets per second to trigger bulk flow detection" -msgstr "" +msgstr "触发大流量检测的每秒数据包量" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1161 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1174 msgid "Only override the DSCP value if it is zero" -msgstr "" +msgstr "仅当 DSCP 值为零时覆盖该值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:704 msgid "" "Only sent with host isolation on — add nat to common CAKE options to force it" -msgstr "" +msgstr "仅在开启主机隔离的情况下发送 — 添加常见 CAKE 选项来强制它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1017 msgid "Options" @@ -774,11 +783,11 @@ msgstr "选项" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:730 msgid "Overhead" -msgstr "" +msgstr "开销" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:731 msgid "Overhead preset" -msgstr "" +msgstr "开销预设" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:603 msgid "Overview" @@ -786,17 +795,19 @@ msgstr "概览" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1834 msgid "Overwrite" -msgstr "" +msgstr "覆盖" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2007 msgid "Overwrite config files" -msgstr "" +msgstr "覆盖配置文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1172 msgid "" "POSIX.2 extended regular expression for matching hostnames. Only works if " "dns lookups are passed to qosify via the add_dns_host ubus call." msgstr "" +"用于匹配主机名的 POSIX.2 扩展正则表达式。仅在通过 add_dns_host ubus 调用将 " +"dns 查询传递到 qosify 时生效。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2150 msgid "Port must be 1-65534 (qosify rejects 65535)." @@ -805,7 +816,7 @@ msgstr "端口必须是 1-65534(qosify 拒绝 65535)。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2146 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2149 msgid "Port must be a number or a range (4500, 5060-5061)." -msgstr "" +msgstr "端口必须时一个数字或范围(4500、5060-5061)。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "QoS Enabled" @@ -813,15 +824,15 @@ msgstr "QoS 已启用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:721 msgid "Queueing mode" -msgstr "" +msgstr "队列模式" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1163 msgid "Quick Add" -msgstr "" +msgstr "快速添加" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1016 msgid "Quick Add: %s" -msgstr "" +msgstr "快速添加:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2153 msgid "Range start must not exceed end." @@ -829,19 +840,19 @@ msgstr "范围开头不能超过结尾。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1213 msgid "Re-check devices" -msgstr "" +msgstr "重新检查设备" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1707 msgid "Re-checking devices..." -msgstr "" +msgstr "正在重新检查设备…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:768 msgid "Re-read the mapping files only" -msgstr "" +msgstr "只重新读取映射文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1690 msgid "Re-reading the mapping files..." -msgstr "" +msgstr "正在重新读取映射文件…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1215 msgid "" @@ -861,11 +872,11 @@ msgstr "正在读取并验证文件…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1681 msgid "Reading tc output..." -msgstr "" +msgstr "正在读取 tc 输出…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1019 msgid "Reference" -msgstr "" +msgstr "参考" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload" @@ -873,20 +884,20 @@ msgstr "重新加载" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:765 msgid "Reload Rules" -msgstr "" +msgstr "重新加载规则" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1695 msgid "Reload failed: %s" -msgstr "" +msgstr "重新加载失败:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1585 msgid "Requires write access." -msgstr "" +msgstr "需要写入权限。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1219 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2086 msgid "Reset" -msgstr "" +msgstr "重置" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2120 msgid "Reset failed: %s" @@ -894,7 +905,7 @@ msgstr "重置失败:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2084 msgid "Reset to defaults" -msgstr "" +msgstr "重置为默认" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2116 msgid "Reset to defaults, applied." @@ -910,11 +921,11 @@ msgstr "重启" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1203 msgid "Restore" -msgstr "" +msgstr "恢复" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1218 msgid "Restore qosify defaults" -msgstr "" +msgstr "恢复 qosify 默认值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2095 msgid "Restoring defaults..." @@ -922,7 +933,7 @@ msgstr "正在恢复默认值…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:605 msgid "Rules" -msgstr "" +msgstr "规则" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1976 msgid "Rules saved" @@ -943,7 +954,7 @@ msgstr "运行中 — 未在整形流量" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:867 msgid "Running — Shaping Unknown" -msgstr "" +msgstr "运行中 —— 整形未知" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:753 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1147 @@ -976,6 +987,8 @@ msgid "" "Section name is the class name that rules and dscp_* values refer to. " "qosify.init reads config alias the same way as config class." msgstr "" +"部分名称是规则和 dscp_* 值引用的类名。qosify.init 读取配置别名的方式和配置类" +"一样。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1724 msgid "Sending %s to qosify..." @@ -983,23 +996,23 @@ msgstr "正在发送 %s 到 qosify…" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:711 msgid "Sent to CAKE as atm, noatm or ptm." -msgstr "" +msgstr "作为 atm、noatm 或 ptm 发送到 CAKE。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "Sent to CAKE as ether-vlan, once per tag." -msgstr "" +msgstr "作为 ether-vlan 发送到 CAKE,每个标签一次。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:734 msgid "Sent to CAKE as mpu, in bytes." -msgstr "" +msgstr "作为 mpu 发送到 CAKE,单位字节。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:710 msgid "Sent to CAKE as overhead, in bytes." -msgstr "" +msgstr "作为开销发送到 CAKE,单位字节。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:663 msgid "Service" -msgstr "" +msgstr "服务" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1745 msgid "Service action failed: %s" @@ -1012,16 +1025,16 @@ msgstr "已保存设置" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:723 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:894 msgid "Shaping" -msgstr "" +msgstr "整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:941 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1198 msgid "Size" -msgstr "" +msgstr "大小" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:73 msgid "Skip this section" -msgstr "" +msgstr "跳过此部分" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:764 msgid "Start" @@ -1035,7 +1048,7 @@ msgstr "状态" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:855 msgid "Status Unknown" -msgstr "" +msgstr "状态未知" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:766 msgid "Stop" @@ -1043,40 +1056,42 @@ msgstr "停止" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1167 msgid "TCP single port, or range from to " -msgstr "" +msgstr "TCP 单端口,或从 到 的区间" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1680 msgid "The detailed tc output needs write access to this page." -msgstr "" +msgstr "详细的 tc 输出需要该页面的写入权限。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:590 msgid "" "The qosify UCI configuration could not be loaded — class and interface lists " "may be incomplete." -msgstr "" +msgstr "无法加载 qosify UCI 配置 —— 类和接口列表可能不完整。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1204 msgid "" "The selected files replace the ones on the router and qosify is reloaded." -msgstr "" +msgstr "所选文件替换路由器上的文件,重新加载了 qosify。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2008 msgid "" "The selected files replace the ones on the router and qosify is reloaded. " "Download a backup from this tab first if you need one." msgstr "" +"所选文件替换路由器上的文件,重新加载了 qosify。如果需要备份,请先从此标签页下" +"载一个备份。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:68 msgid "Time below bulk_trigger_pps threshold until a bulk flow mark is removed" -msgstr "" +msgstr "低于 bulk_trigger_pps 阈值多少时间删除大流量记号" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1402 msgid "Traffic by CAKE Tin" -msgstr "" +msgstr "CAKE Tin 的流量" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1401 msgid "Traffic by Class" -msgstr "" +msgstr "按照类区分的流量" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:596 msgid "Traffic shaping and DSCP classification via qosify" @@ -1084,13 +1099,13 @@ msgstr "通过 qosify 进行流量整形和 DSCP 分类" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1168 msgid "UDP single port, or range from to " -msgstr "" +msgstr "UDP 单端口,或从 到 的范围" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:864 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:866 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:925 msgid "Unknown" -msgstr "" +msgstr "未知" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:435 msgid "Unknown class/DSCP target: %s" @@ -1098,31 +1113,31 @@ msgstr "未知类/DSCP 目标:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:717 msgid "Unticked sets disabled 1 and qosify skips this section." -msgstr "" +msgstr "未勾选的集合禁用了 1,qosify 跳过此部分。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:74 msgid "Uplink bandwidth (same format as tc)" -msgstr "" +msgstr "上行链路带宽(和 tc 格式一样)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Uplink bandwidth, same format as tc. Set just below line speed." -msgstr "" +msgstr "上行链路带宽,和 tc 格式相同。就在线路速度下方设置。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1205 msgid "Upload" -msgstr "" +msgstr "上传" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1210 msgid "Upload & Apply" -msgstr "" +msgstr "上传并应用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2009 msgid "Upload and apply" -msgstr "" +msgstr "上传并应用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:719 msgid "Upload bandwidth" -msgstr "" +msgstr "上传带宽" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2061 msgid "Upload error: %s" @@ -1134,7 +1149,7 @@ msgstr "上传失败了:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:725 msgid "Upload shaping" -msgstr "" +msgstr "上传整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2035 msgid "Uploading" @@ -1142,11 +1157,11 @@ msgstr "上传中" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:892 msgid "Uptime" -msgstr "" +msgstr "已运行时长" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:735 msgid "VLAN tags" -msgstr "" +msgstr "VLAN 标签" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:938 msgid "Valid" @@ -1164,7 +1179,7 @@ msgstr "工作中" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1870 msgid "Write empty file" -msgstr "" +msgstr "写空文件" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1906 msgid "Writing config and reloading qosify..." @@ -1178,43 +1193,43 @@ msgstr "正在写入规则并重新加载 qosify…" msgid "" "You have read-only access to this page, so editing and service control are " "disabled." -msgstr "" +msgstr "你只有该页面的只读权限,因此编辑和服务控制被禁用。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "active" -msgstr "" +msgstr "活跃" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1767 msgid "" "bandwidth_down does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" -msgstr "" +msgstr "bandwidth_down 看上去不像 tc 速率 (100mbit, 12MBps, unlimited) — 仍然传递它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1766 msgid "" "bandwidth_up does not look like a tc rate (100mbit, 12MBps, unlimited) — " "passing it through anyway" -msgstr "" +msgstr "bandwidth_up 看上去不像 tc 速率 (100mbit, 12MBps, unlimited) — 仍然传递它" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1012 msgid "" "config device takes the same options, with name set to a netdev. nat " "defaults to 1 for interfaces and 0 for devices." -msgstr "" +msgstr "配置设备采用的选项相同,名称设为 netdev。接口 nat 值为 1,设备 nat 值为 0。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "device %s" -msgstr "" +msgstr "%s 设备" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "device: %s, ingress: %s, egress: %s" -msgstr "" +msgstr "设备:%s,入口:%s,接口:%s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:289 msgid "" "disabled is set to \"%s\" — config_get_bool does not recognise that, so the " "section stays enabled" -msgstr "" +msgstr "disabled 设为 \"%s\" — config_get_bool 不识别这个,因此该部分保持启用" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:700 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 @@ -1224,23 +1239,23 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:2129 msgid "e.g. %s" -msgstr "" +msgstr "如 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1171 msgid "fnmatch() pattern supporting * and ? as wildcard characters" -msgstr "" +msgstr "将 * 和 ? 作为通配符字符支持的 fnmatch() 模式" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1613 msgid "get_stats did not answer." -msgstr "" +msgstr "get_stats 未回应。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:901 msgid "inactive" -msgstr "" +msgstr "不活跃" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1109 msgid "ingress %s, egress %s" -msgstr "" +msgstr "入口 %s,出口 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:282 msgid "ingress and egress are both 0 — nothing is shaped" @@ -1248,11 +1263,11 @@ msgstr "出入站均为 0 — 没有流量被整形" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:900 msgid "interface %s" -msgstr "" +msgstr "接口 %s" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1155 msgid "match" -msgstr "" +msgstr "匹配" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:274 msgid "" @@ -1280,15 +1295,15 @@ msgstr "" msgid "" "netifd interface (config interface) or netdev (config device) to enable QoS " "on" -msgstr "" +msgstr "启用 QoS 的 netifd 接口 (配置接口) or netdev (配置服务)" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:718 msgid "netifd interface to enable QoS on. Required." -msgstr "" +msgstr "启用 QoS 的 netifd 接口。必需。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "no" -msgstr "" +msgstr "否" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:284 msgid "no bandwidth_down or bandwidth — ingress CAKE runs unlimited" @@ -1300,7 +1315,7 @@ msgstr "没有 bandwidth_up 或 bandwidth — 出站 CAKE 运行不受限" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:882 msgid "none" -msgstr "" +msgstr "none" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:281 msgid "overhead and overhead_encap are ignored unless overhead_type is manual" @@ -1314,12 +1329,12 @@ msgstr "qosify" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:847 msgid "" "qosify did not appear on ubus, so its config was not applied — press Reload" -msgstr "" +msgstr "qosify 未出现在 ubus 上,因此未应用其配置 —— 按下重新加载" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:833 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1729 msgid "qosify did not come up — check the system log" -msgstr "" +msgstr "qosify 没有跑起来 —— 检查系统日志" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1610 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1672 @@ -1329,7 +1344,7 @@ msgstr "qosify 未在运行。从概况标签页启动。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1735 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1887 msgid "qosify is still running — leaving the qdiscs alone" -msgstr "" +msgstr "qosify 仍在运行 —— 别动 qdiscs" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1253 msgid "qosify-status" @@ -1344,6 +1359,8 @@ msgid "" "rpcd is not answering for qosify — check the ACL in /usr/share/rpcd/acl.d " "and restart rpcd" msgstr "" +"rpcd 没有在被当成 qosify 使用 —— 检查 /usr/share/rpcd/acl.d 中的 ACL 并重启 " +"rpcd" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:832 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1609 @@ -1352,32 +1369,32 @@ msgstr "" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1734 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1886 msgid "rpcd is not answering for qosify, so the service state is unknown." -msgstr "" +msgstr "rpcd 没有在被当作 qosify 使用,因此服务状态未知。" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:955 msgid "section name" -msgstr "" +msgstr "部分名称" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:953 msgid "section type" -msgstr "" +msgstr "部分类型" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1529 #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1533 msgid "share" -msgstr "" +msgstr "分享" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1541 msgid "total" -msgstr "" +msgstr "总计" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:1160 msgid "value" -msgstr "" +msgstr "值" #: applications/luci-app-qosify/htdocs/luci-static/resources/view/qosify/main.js:902 msgid "yes" -msgstr "" +msgstr "是" #~ msgid "%s contains a quote — qosify rejects the whole value" #~ msgstr "%s 包含一个引号 — qosify 拒绝整个值" diff --git a/luci-app-sfp-info/Makefile b/luci-app-sfp-info/Makefile index c0efc025e..00fde86aa 100644 --- a/luci-app-sfp-info/Makefile +++ b/luci-app-sfp-info/Makefile @@ -9,7 +9,7 @@ LUCI_PKGARCH:=all PKG_LICENSE:=Apache-2.0 PKG_VERSION:=1.0 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_MAINTAINER:=Meng Zhuo include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-sfp-info/po/pt/sfp-info.po b/luci-app-sfp-info/po/pt/sfp-info.po index 1348ea9a7..f49541665 100644 --- a/luci-app-sfp-info/po/pt/sfp-info.po +++ b/luci-app-sfp-info/po/pt/sfp-info.po @@ -3,9 +3,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Language: pt\n" "Content-Transfer-Encoding: 8bit\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"Last-Translator: Pavel Borecki \n" +"Language-Team: Portuguese \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" +"PO-Revision-Date: 2026-09-29 12:10+0000\n" +"X-Generator: Weblate 2026.10.dev0\n" #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:68 msgid "Bias Current" @@ -97,7 +100,7 @@ msgstr "" #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:63 msgid "Type" -msgstr "" +msgstr "Tipo" #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:62 msgid "Vendor" diff --git a/luci-app-substore/CHANGELOG.md b/luci-app-substore/CHANGELOG.md index 76634e99c..6293e4521 100644 --- a/luci-app-substore/CHANGELOG.md +++ b/luci-app-substore/CHANGELOG.md @@ -2,6 +2,99 @@ All notable changes to this project will be documented in this file. +## [2.6.0-r1] - 协议覆盖补全与导入/输出保真修复 + +本轮起因:用户报告「添加本地订阅 → 表单导入」的「类型」下拉框协议不全, +与 README 描述不符。审计后确认问题存在,且**「文本导入」存在更严重的同类缺口**, +并顺带查出若干静默数据丢失 / 非法输出问题。所有修改均经代码或测试确认, +未做任何推测性改动。 + +### 协议覆盖(本次报告的主问题) + +- **表单导入缺 `hysteria`(v1) 与 `socks`**:`nodeform.js` 的下拉框只有 8 个协议, + 而 `node.lua` 的 `M.PROTOS`、节点页协议筛选、规则 `proto_filter` 都认 10 个。 + 用户因此无法用表单录入这两类节点。 +- **文本导入(URI)缺 `hysteria`(v1) 与 `socks`/`socks5`**,且这是**导出→导入回环断裂**: + `output_uri.to_share_uri` 会生成 `hysteria://` 与 `socks5://` 链接,但 `parser.parse_uri` + 对二者一律返回 `unsupported proto`。含这两类节点的订阅文本会被**整行静默丢弃**。 + 已新增 `parse_hysteria` / `parse_socks` 并补齐 `SUPPORTED` 分发表。 +- **简易 YAML 兜底解析的协议表漂移**:该处自维护一份映射,缺 + `hysteria2` / `hysteria` / `tuic` / `wireguard`,且 `socks5` 未归一,更严重的是 + 对认不出的 `type` 用 `or "vmess"` 兜底 —— 一份 sing-box YAML 里的 + hysteria2/tuic/wireguard 出站会变成数个**字段全错的假 vmess 节点**(静默数据损坏)。 + 现改为复用 `parser_clash_yaml.TYPE_MAP`(单一事实来源),未知协议直接丢弃。 +- **简易 YAML 兜底解析的 `outbounds:` 分支从不生效**:该分支同时接受 Clash 的 + `proxies:` 与 sing-box 的 `outbounds:` 段名,却只读 Clash 的 `port` / `name`, + 而 sing-box 用 `server_port` / `tag`。结果是 sing-box YAML 出站**全部被静默丢弃** + (识别了段名却解析出 0 个节点)。现按 `parser_json_config.parse_singbox_json` + 读取的键名逐字补齐别名:`server_port` / `tag` / `auth_str` / `auth` / + `tls.server_name` / `tls.insecure` / `security`(vmess 加密方式) / `network`。 + +### 归一化 + +- **`socks5` → `socks` 归一**:两者是同一协议的不同写法(Clash 写 `socks5`、 + sing-box 写 `socks`、分享链接写 `socks5://`)。输出模块本来就同时认两种写法, + 但 `node.filter` 与 `rules.proto_filter` 是精确比较,两种写法互相看不见 —— + 节点页按协议筛选与规则过滤都会漏。现统一为规范名 `socks`。 + +### 输出保真 + +- **clashmeta:hysteria(v1) 的 SNI 丢失**。此前统一输出 `servername`,而 mihomo 的 + hysteria 系列没有该字段(写 `servername` 会被忽略),SNI 丢失会导致客户端 + 以 IP 校验证书、握手直接失败。现按协议区分:hysteria / hysteria2 输出 `sni`, + vmess / vless / trojan 仍输出 `servername`。同时补上 v1 的 `obfs`(普通字符串)。 +- **clashmeta:socks5 的 `password` 被输出两次**(通用字段段 + 协议专属段), + 在 YAML 里形成重复键,属非法/歧义配置。现协议专属段只补 `username`。 +- **clashmeta / singbox / surge:`http` 的用户名丢失**,只输出密码。现按上游文档 + 补齐 `username`(mihomo 的 http / socks5 用 `username` + `password`; + Surge 家族用 `username=` / `password=` 具名参数)。 +- **singbox:hysteria(v1) 字段名错误**。此前输出 `password` 与 + `obfs = { type, password }`,但 sing-box 的 hysteria 出站认证字段是 `auth_str`, + `obfs` 是**普通字符串**(对象形式是 hysteria2 的 salamander 专属)。 + 该修正与本项目 `parser_json_config` 自身的回读逻辑一致 + (其按 `outbound.password or outbound.auth_str or outbound.auth` 读取)。 +- **`output_uri` / `output_clash_meta`:hysteria(v1) 不应出现 `obfs-password`**。 + 该字段是 hysteria2 的 salamander 专属,写到 v1 上是非法参数/非法键。 + +### 表单 + +- **`core.FORM_KEYS` 缺 `username`**:`merge_form_node` 先按 `FORM_KEYS` 清空原节点 + 再套用提交值,不在表里的字段会保留旧值 —— 用户在表单里**清空用户名也删不掉** + (`collectNodes` 会略过空值)。已补入。 + +### 已知限制(本轮不修,均有明确原因) + +- **混合格式文本导入不支持**。README 称可粘贴「YAML / URI / JSON / wg-quick `.conf` 混合」 + 文本,但 `parse_local → parse → detect` 只识别**一种**格式,其余部分被静默丢弃 + (已实测:「URI + WG conf」只剩 WG 节点;「URI + JSON」只剩 URI 节点)。 + 这是**功能缺失**而非小缺陷,需要重新设计 parser 的分段架构(规格 §22 明确警告 + 不要直接采用未经验证的逐行算法),故留待专门版本处理。 +- **sing-box 的 hysteria(v1) 出站还要求 `up` / `down`(带宽)**,本项目的节点模型 + 不承载该字段。凭空填默认值属于猜测,故不输出;用户需在自己的配置里补上。 +- **hysteria(v1) 的上游 URI 规范未能核实**(上游文档站点持续 404,无法取得权威定义)。 + 因此 `parse_hysteria` 只保证解析本项目 `output_uri` 自身生成的链接形态 + (回环已验证),认不出的查询参数一律忽略而不报错,不臆造参数语义。 +- **`http` 不加入任何 UI 协议列表**:规格 §25 的权威协议表恰好是 10 个协议、不含 `http`。 + 它可由 Clash YAML / JSON 配置导入并正常导出(凭据已修),但不作为表单可选项。 +- **`parser_yaml.lua` 为死代码**(`parser.lua` 顶部 require 后从未调用), + 其中留有同样未归一的 `socks5` 映射,仅记录,不影响运行。 +- **`parse_tuic` / `parse_hysteria2` 按第一个 `@` 切分 userinfo**,与 `parse_socks` + 修复前同类(密码含裸 `@` 会被切坏)。本轮只修了 socks,其余留作观察项。 + +### 测试 + +- 新增 `tests/protocol_coverage_test.lua`(110 项断言),覆盖上述全部修复: + hysteria / socks 的 URI 导入与导出→导入回环、混合文本不再丢行、 + 兜底解析不再造假日 vmess、sing-box YAML 出站别名、`socks5` 归一后筛选/规则命中、 + clashmeta / singbox / surge 的输出字段、`FORM_KEYS` 的 `username`。 +- 全量测试:`tests/*_test.lua` 逐文件运行,**0 个失败文件**; + `tests/cron_result_test.sh` rc=0。 + +### 版本 + +- 版本号 2.5.1-r1 → 2.6.0-r1(协议覆盖为功能增强,走 minor); + `README.md` / `README.en.md` / `docs/INSTALL.md` 同步。 + ## [2.5.1-r1] - 安全加固与数据保真修复 本轮为缺陷修复版本,重点是**命令注入 / SSRF 绕过 / 静默数据丢失**三类问题。 diff --git a/luci-app-substore/Makefile b/luci-app-substore/Makefile index c29a923c8..ba0b29286 100644 --- a/luci-app-substore/Makefile +++ b/luci-app-substore/Makefile @@ -9,8 +9,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-substore # 版本约定:每次提交 PKG_RELEASE +1(2.1.2-r1 ~ r9); # 达到 r10 时 PKG_VERSION 末位 +1(2.1.2 -> 2.1.3),PKG_RELEASE 重置为 1。 -PKG_VERSION:=2.5.1 -PKG_RELEASE:=10 +PKG_VERSION:=2.6.0 +PKG_RELEASE:=11 LUCI_DEPENDS:=+luci-lua-runtime +luci-compat diff --git a/luci-app-substore/README.en.md b/luci-app-substore/README.en.md index 114e92166..ad7435ca5 100644 --- a/luci-app-substore/README.en.md +++ b/luci-app-substore/README.en.md @@ -23,17 +23,20 @@ group them, then re-emit them in a format your client can consume. (optionally with keyword include / exclude and dedup rules) into one combination that has its own name, token and subscription link; combinations are recomputed automatically when a source updates -- **Local subscription**: no URL needed — paste node text (mixed YAML / URI / JSON / +- **Local subscription**: no URL needed — paste node text (YAML / URI / JSON / wg-quick `.conf`) or enter nodes one by one via a form whose fields adapt to the - selected protocol - (vmess / vless / ss / ssr / trojan / hysteria2 / tuic / wireguard / socks) + selected protocol. A paste is detected as **one** format (YAML / URI / JSON / + `.conf`); mixing several formats in one paste is not supported + (vmess / vless / ss / ssr / trojan / hysteria / hysteria2 / tuic / wireguard / socks) **Input parsing** - Subscription formats: URI lists, Base64, JSON, Clash YAML, sing-box JSON, V2Ray / Xray JSON, Surge / Surfboard / Loon / Quantumult X configs, LAN subscription links, and wg-quick / AmneziaWG `.conf` -- Node protocols: `vmess` / `vless` / `trojan` / `shadowsocks` / `ssr` / `hysteria2` / - `tuic` / `socks` (and more) +- Node protocols: `vmess` / `vless` / `trojan` / `shadowsocks` / `ssr` / `hysteria` / + `hysteria2` / `tuic` / `wireguard` / `socks` (plus `http`, which can be imported from + Clash YAML / JSON configs and exported, but is not offered in the form importer — + it is not served as a proxy node) - **WireGuard / AmneziaWG**: full field import and export (`private-key` / `public-key` / `pre-shared-key` / `ip` / `ipv6` / `allowed-ips` / `reserved` / `persistent-keepalive` / `listen-port` / `mtu` / `dns`) plus the `amnezia-wg-option` sub-block @@ -93,18 +96,18 @@ group them, then re-emit them in a format your client can consume. ## Installation > The version in the package name must match `PKG_VERSION` / `PKG_RELEASE` in the -> [Makefile](Makefile) (currently `2.5.1-r1`). +> [Makefile](Makefile) (currently `2.6.0-r1`). opkg (OpenWrt / ImmortalWrt 24.10 and earlier): ```bash -opkg install luci-app-substore-2.5.1-r1.ipk +opkg install luci-app-substore-2.6.0-r1.ipk ``` apk (OpenWrt / ImmortalWrt 25.12+): ```bash -apk add --allow-untrusted luci-app-substore-2.5.1-r1.apk +apk add --allow-untrusted luci-app-substore-2.6.0-r1.apk ``` Then open LuCI: **Services → Subscriptions**. diff --git a/luci-app-substore/README.md b/luci-app-substore/README.md index 583fd735c..f079a78a4 100644 --- a/luci-app-substore/README.md +++ b/luci-app-substore/README.md @@ -21,14 +21,17 @@ 用于订阅源直连失败时 - **组合订阅**:勾选任意子集的现有订阅(可叠加关键词包含 / 排除、去重规则)合并成一个组合, 拥有独立名称、token 与订阅链接;源订阅更新后组合自动重算 -- **本地订阅**:不填 URL,直接粘贴节点文本(YAML / URI / JSON / wg-quick `.conf` 混合)导入, +- **本地订阅**:不填 URL,直接粘贴节点文本(YAML / URI / JSON / wg-quick `.conf`)导入, + 一次粘贴按**单一格式**识别(自动判定 YAML / URI / JSON / `.conf`,不支持多格式混排), 或用「表单导入」按协议动态字段逐条录入节点 - (vmess / vless / ss / ssr / trojan / hysteria2 / tuic / wireguard / socks) + (vmess / vless / ss / ssr / trojan / hysteria / hysteria2 / tuic / wireguard / socks) **输入解析** - 订阅格式:URI 列表、Base64、JSON、Clash YAML、sing-box JSON、V2Ray / Xray JSON、 Surge / Surfboard / Loon / Quantumult X 配置、局域网订阅链接、wg-quick / AmneziaWG `.conf` -- 节点协议:`vmess` / `vless` / `trojan` / `shadowsocks` / `ssr` / `hysteria2` / `tuic` / `socks`(及更多) +- 节点协议:`vmess` / `vless` / `trojan` / `shadowsocks` / `ssr` / `hysteria` / `hysteria2` / + `tuic` / `wireguard` / `socks`(及 `http`,可由 Clash YAML / JSON 配置导入并导出, + 但不在表单导入的可选协议内 —— 它不作为代理节点对外提供订阅) - **WireGuard / AmneziaWG**:导入并导出完整字段(`private-key` / `public-key` / `pre-shared-key` / `ip` / `ipv6` / `allowed-ips` / `reserved` / `persistent-keepalive` / `listen-port` / `mtu` / `dns`), 以及 `amnezia-wg-option` 子块(Jc / Jmin / Jmax / S1–S4 / H1–H4 / I1–I5 / J1–J3 / Itime); @@ -80,18 +83,18 @@ ## 安装 > 包名中的版本号必须与 [Makefile](Makefile) 的 `PKG_VERSION` / `PKG_RELEASE` 保持一致 -> (当前 `2.5.1-r1`)。 +> (当前 `2.6.0-r1`)。 opkg(OpenWrt / ImmortalWrt 24.10 及更早): ```bash -opkg install luci-app-substore-2.5.1-r1.ipk +opkg install luci-app-substore-2.6.0-r1.ipk ``` apk(OpenWrt / ImmortalWrt 25.12+): ```bash -apk add --allow-untrusted luci-app-substore-2.5.1-r1.apk +apk add --allow-untrusted luci-app-substore-2.6.0-r1.apk ``` 然后在 LuCI 菜单打开:**服务 → 订阅**。 diff --git a/luci-app-substore/docs/INSTALL.md b/luci-app-substore/docs/INSTALL.md index aa529e0b0..8f706f07b 100644 --- a/luci-app-substore/docs/INSTALL.md +++ b/luci-app-substore/docs/INSTALL.md @@ -3,18 +3,18 @@ > NOTE: stage-0 skeleton has not yet been installed/verified on a target device. > This document will be updated once installation is validated. > -> 包名中的版本号需与 Makefile 的 `PKG_VERSION` / `PKG_RELEASE` 保持同步(当前 2.5.1-r1)。 +> 包名中的版本号需与 Makefile 的 `PKG_VERSION` / `PKG_RELEASE` 保持同步(当前 2.6.0-r1)。 ## Install (opkg — OpenWrt / ImmortalWrt 24.10 及更早) ```bash -opkg install luci-app-substore-2.5.1-r1.ipk +opkg install luci-app-substore-2.6.0-r1.ipk ``` ## Install (apk — OpenWrt / ImmortalWrt 25.12+) ```bash -apk add --allow-untrusted luci-app-substore-2.5.1-r1.apk +apk add --allow-untrusted luci-app-substore-2.6.0-r1.apk ``` Refresh LuCI: diff --git a/luci-app-substore/root/usr/lib/lua/luci/view/substore/local_form.htm b/luci-app-substore/root/usr/lib/lua/luci/view/substore/local_form.htm index ae3d801b3..0e0d1f298 100644 --- a/luci-app-substore/root/usr/lib/lua/luci/view/substore/local_form.htm +++ b/luci-app-substore/root/usr/lib/lua/luci/view/substore/local_form.htm @@ -133,7 +133,8 @@ var FIELD_LABELS = { "listen-port": "Listen Port", "mtu": "MTU", "dns": "DNS", - "amnezia-wg-option": "Amnezia WG Option" + "amnezia-wg-option": "Amnezia WG Option", + "username": "Username" }; var NODEFORM_I18N = { "node": "<%:Node%>", diff --git a/luci-app-substore/root/usr/lib/lua/luci/view/substore/node_edit.htm b/luci-app-substore/root/usr/lib/lua/luci/view/substore/node_edit.htm index 61cad4556..aafc1192e 100644 --- a/luci-app-substore/root/usr/lib/lua/luci/view/substore/node_edit.htm +++ b/luci-app-substore/root/usr/lib/lua/luci/view/substore/node_edit.htm @@ -76,7 +76,8 @@ var FIELD_LABELS = { "listen-port": "Listen Port", "mtu": "MTU", "dns": "DNS", - "amnezia-wg-option": "Amnezia WG Option" + "amnezia-wg-option": "Amnezia WG Option", + "username": "Username" }; var NODEFORM_I18N = { "node": "<%:Node%>", diff --git a/luci-app-substore/root/usr/share/substore/core.lua b/luci-app-substore/root/usr/share/substore/core.lua index 20b889dc5..2e0002921 100644 --- a/luci-app-substore/root/usr/share/substore/core.lua +++ b/luci-app-substore/root/usr/share/substore/core.lua @@ -7,7 +7,7 @@ local parser = require("substore.parser") local M = {} -M.version = "2.5.1" +M.version = "2.6.0" M.DATA_DIR = "/etc/substore" M.LIST_FILE = M.DATA_DIR .. "/subscriptions.json" M.NODES_DIR = M.DATA_DIR .. "/nodes" @@ -25,12 +25,21 @@ function M.ensure_dirs() util.ensure_dir(M.NODES_DIR) end +-- 读取订阅列表,返回 seq, items, err。 +-- +-- 必须区分「文件不存在 / 为空」(合法的空列表)与「文件存在但解析失败」 +-- (内容损坏、被截断、磁盘错误)。后者若按空列表处理,后果是灾难性的: +-- M.add / M.add_local / M.add_combo 会在这个空表上追加一条然后整表写回, +-- 把用户已有的全部订阅抹掉,并且 _seq 归零后重新发出 s00000001 这种 +-- 已经用过的 ID。因此损坏时必须显式报错,由调用方拒绝写入。 local function load() M.ensure_dirs() local raw = util.read_file(M.LIST_FILE) if not raw or raw == "" then return 0, {} end local data = util.json_decode(raw) - if type(data) ~= "table" then return 0, {} end + if type(data) ~= "table" then + return 0, {}, "订阅列表文件已损坏,无法解析:" .. M.LIST_FILE + end local seq = tonumber(data._seq) or 0 local items = type(data.items) == "table" and data.items or {} return seq, items @@ -41,8 +50,11 @@ local function save(seq, items) return util.atomic_write(M.LIST_FILE, util.json_encode({ _seq = seq, items = items })) end +-- 返回 arr, err。err 非空表示列表文件已损坏(此时 arr 为空)。 +-- 追加第二个返回值是向后兼容的:调用方普遍写成 ipairs(core.list()) 或 +-- local items = core.list(),都只取第一个值。 function M.list() - local _, items = load() + local _, items, lerr = load() local arr = {} for id, meta in pairs(items) do local m = {} @@ -51,7 +63,7 @@ function M.list() arr[#arr + 1] = m end table.sort(arr, function(a, b) return (a.name or "") < (b.name or "") end) - return arr + return arr, lerr end function M.get(id) @@ -70,7 +82,8 @@ function M.add(name, url, opts) url = util.trim(url or "") opts = opts or {} if name == "" or url == "" then return nil, "名称/URL 不能为空" end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return nil, lerr end seq = seq + 1 local id = string.format("s%08x", seq) local cron_time = util.trim(opts.cron_time or "") @@ -103,7 +116,8 @@ function M.add_local(name, raw_content, local_mode, opts) local_mode = local_mode or "text" opts = opts or {} if name == "" or raw_content == "" then return nil, "名称/内容 不能为空" end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return nil, lerr end seq = seq + 1 local id = string.format("s%08x", seq) items[id] = { @@ -131,7 +145,8 @@ end -- 获取订阅的下载 token;若不存在则生成并持久化 function M.ensure_token(id) if not id_is_valid(id) then return nil end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return nil end local meta = items[id] if not meta then return nil end if not meta.token or meta.token == "" then @@ -178,7 +193,8 @@ M.CLEAR = setmetatable({}, { __tostring = function() return "substore.CLEAR" end function M.save_meta(id, patch) if not id_is_valid(id) then return false, "非法 ID" end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return false, lerr end local meta = items[id] if not meta then return false, "订阅不存在" end for k, v in pairs(patch or {}) do @@ -189,7 +205,8 @@ end function M.remove(id) if not id_is_valid(id) then return false end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return false, lerr end if not items[id] then return false end items[id] = nil save(seq, items) @@ -363,6 +380,10 @@ local FORM_KEYS = { reserved = true, ["persistent-keepalive"] = true, persistent_keepalive = true, ["listen-port"] = true, listen_port = true, mtu = true, dns = true, ["amnezia-wg-option"] = true, + -- socks / http 的用户名。必须在表里:下面的 merge_form_node 先按 FORM_KEYS + -- 清空原节点再套用提交值,不在表里的字段会保留旧值——用户在表单里清空用户名 + -- 也删不掉(collectNodes 会略过空值),等于改不动。 + username = true, } -- 合并表单节点到原节点:表单字段整体替换(可清空),非表单字段保留 @@ -441,7 +462,8 @@ function M.add_combo(name, sources, opts) end end if #srcs == 0 then return nil, "请选择至少一个订阅" end - local seq, items = load() + local seq, items, lerr = load() + if lerr then return nil, lerr end seq = seq + 1 local id = string.format("s%08x", seq) items[id] = { diff --git a/luci-app-substore/root/usr/share/substore/node.lua b/luci-app-substore/root/usr/share/substore/node.lua index a6e97119a..2ff3277ab 100644 --- a/luci-app-substore/root/usr/share/substore/node.lua +++ b/luci-app-substore/root/usr/share/substore/node.lua @@ -37,6 +37,11 @@ end function M.normalize(node) if type(node) ~= "table" then return node end if node.proto == "ss" then node.proto = "shadowsocks" end + -- socks5 与 socks 是同一个协议,只是各客户端写法不同(Clash 写 socks5、 + -- sing-box 写 socks、分享链接写 socks5://)。统一成 socks: + -- 各输出模块本来就同时认这两种写法,但 node.filter / rules.proto_filter + -- 是精确比较,两种写法会互相看不见——节点页按协议筛选和规则过滤都会漏。 + if node.proto == "socks5" then node.proto = "socks" end local d = DEFAULTS[node.proto] or {} for k, v in pairs(d) do if node[k] == nil then node[k] = v end diff --git a/luci-app-substore/root/usr/share/substore/output_clash_meta.lua b/luci-app-substore/root/usr/share/substore/output_clash_meta.lua index 512ad4423..d373402c2 100644 --- a/luci-app-substore/root/usr/share/substore/output_clash_meta.lua +++ b/luci-app-substore/root/usr/share/substore/output_clash_meta.lua @@ -5,9 +5,15 @@ local M = {} local function esc_yaml(s) s = tostring(s or "") - s = s:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n") - -- 注意:这里必须用 Lua 模式(不能传 plain=true),否则整串被当作字面量、永不匹配 - if s:find("[ :#{}%[%],&*?|>'\"%@`]") or s:match("^[-?]*:") then + -- 是否需要双引号必须在转义之前判定:转义之后的 \t / \r 只剩「反斜杠 + 字母」, + -- 落在 plain scalar 里会被 YAML 当成两个字面字符而不是制表符/回车。含任何控制 + -- 字符(\n \r \t 等)时必须加引号 —— 未加引号的换行/回车会直接破坏文档结构。 + local need_quote = s:find("%c") ~= nil + -- 注意:这里必须用 Lua 模式(不能传 plain=true),否则整串被当作字面量、永不匹配 + or s:find("[ :#{}%[%],&*?|>'\"%@`]") ~= nil + or s:match("^[-?]*:") ~= nil + s = s:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n"):gsub("\r", "\\r"):gsub("\t", "\\t") + if need_quote then return '"' .. s .. '"' end return s @@ -106,11 +112,18 @@ local function format_node(node) end -- servername / sni - if node.sni then - lines[#lines + 1] = " servername: " .. esc_yaml(node.sni) - end - if node.servername then - lines[#lines + 1] = " servername: " .. esc_yaml(node.servername) + -- vmess / vless / trojan 在 mihomo 里用 servername;hysteria / hysteria2 用 sni + -- (已对照上游文档确认:hysteria 系列没有 servername 字段,写了会被忽略, + -- 结果 SNI 丢失 → 客户端拿 IP 校验证书直接握手失败)。hysteria 系列的 sni + -- 由下面的协议专属分支输出。 + -- sni 与 servername 是同一个字段的两种写法,必须只输出一个键:Clash YAML 导入 + -- 会同时填上两者(先 sni = p.sni or p.servername,随后的字段保留循环又原样复制了 + -- servername),各写一行会让 YAML 出现重复键 —— 严格解析器直接报错,宽松解析器 + -- 则取最后一个,行为不确定。 + local is_hysteria = (ctype == "hysteria" or ctype == "hysteria2") + local tls_name = node.sni or node.servername + if tls_name and not is_hysteria then + lines[#lines + 1] = " servername: " .. esc_yaml(tls_name) end -- 特殊字段 @@ -152,7 +165,7 @@ local function format_node(node) if node.sni then lines[#lines + 1] = " sni: " .. esc_yaml(node.sni) end - -- 混淆(salamander) + -- 混淆(salamander):hysteria2 的 obfs 是 { type, password } 两段 if node.obfs and node.obfs ~= "" and node.obfs ~= "plain" then lines[#lines + 1] = " obfs: " .. esc_yaml(node.obfs) local opw = node["obfs-password"] or node.obfs_password @@ -162,6 +175,17 @@ local function format_node(node) end end + if ctype == "hysteria" then + -- hysteria(v1):obfs 只是普通字符串,**没有** obfs-password + -- (obfs-password 是 hysteria2 的 salamander 专属字段,写到 v1 上是非法键) + if node.sni then + lines[#lines + 1] = " sni: " .. esc_yaml(node.sni) + end + if node.obfs and node.obfs ~= "" and node.obfs ~= "plain" then + lines[#lines + 1] = " obfs: " .. esc_yaml(node.obfs) + end + end + if ctype == "tuic" then if node["udp-relay-mode"] then lines[#lines + 1] = " udp-relay-mode: " .. esc_yaml(node["udp-relay-mode"]) @@ -214,13 +238,13 @@ local function format_node(node) end end - if ctype == "socks5" then + -- socks5 / http 的认证字段都是 username + password(已对照上游 mihomo 文档确认)。 + -- password 已由上面的「协议通用字段」输出,这里只补 username——重复输出会让 + -- YAML 里出现两个 password 键,属于非法/歧义配置。 + if ctype == "socks5" or ctype == "http" then if node.username then lines[#lines + 1] = " username: " .. esc_yaml(node.username) end - if node.password then - lines[#lines + 1] = " password: " .. esc_yaml(node.password) - end end if ctype == "ssr" then diff --git a/luci-app-substore/root/usr/share/substore/output_formats.lua b/luci-app-substore/root/usr/share/substore/output_formats.lua index 5810881ca..0cd2c4413 100644 --- a/luci-app-substore/root/usr/share/substore/output_formats.lua +++ b/luci-app-substore/root/usr/share/substore/output_formats.lua @@ -57,8 +57,17 @@ function M.surge_line(n) e[#e + 1] = "username=" .. (n.uuid or "") if n.password then e[#e + 1] = "password=" .. n.password end if n.sni then e[#e + 1] = "sni=" .. n.sni end - if n.alpn then e[#e + 1] = "alpn=" .. n.alpn end - elseif proto == "socks5" or proto == "socks" then + if n.alpn then + -- alpn 可能是数组:sing-box JSON 与 Clash YAML 的 alpn 列表导入后就是 table, + -- 直接拼接会 "attempt to concatenate a table value" 让整次导出失败 + local alpn = n.alpn + if type(alpn) == "table" then alpn = table.concat(alpn, ",") end + if alpn ~= "" then e[#e + 1] = "alpn=" .. alpn end + end + elseif proto == "socks5" or proto == "socks" or proto == "http" then + -- socks5 / http 在 Surge 家族里都用 username= / password= 具名参数 + -- (Surge 手册:Name = http, , [, , ] + -- "may be given positionally after the port, or as named parameters") if n.username then e[#e + 1] = "username=" .. n.username if n.password then e[#e + 1] = "password=" .. n.password end @@ -70,7 +79,8 @@ function M.surge_line(n) local line = (n.name or "") .. " = " .. head if #e > 0 then line = line .. ", " .. table.concat(e, ", ") end - return line + -- 节点名与各参数值都来自订阅(不可信):含换行会截断本行并伪造出一条新的代理行 + return util.one_line(line) end -- 收集节点名列表 @@ -112,7 +122,7 @@ local function surge_config(nodes, group_name, supports_ssr) local select = group_name .. " = select" for _, nm in ipairs(names) do select = select .. ", " .. nm end select = select .. ", DIRECT" - out[#out + 1] = select + out[#out + 1] = util.one_line(select) return table.concat(out, "\n") end @@ -172,6 +182,7 @@ function M.to_qx(nodes, options) local proto = props(n) local host = (n.server or "") .. ":" .. tostring(n.port or 0) local tag = n.name or host + local before = #out if proto == "shadowsocks" then out[#out + 1] = string.format( "shadowsocks=%s, method=%s, password=%s, tag=%s", @@ -199,13 +210,16 @@ function M.to_qx(nodes, options) host, n.password or "", tag) if n.sni then out[#out] = out[#out] .. ", tls-host=" .. n.sni end end + -- 节点名 / sni / path / host 全部来自订阅(不可信),含换行会截断本行 + -- 并伪造出一条新的 server_local 行 + for i = before + 1, #out do out[i] = util.one_line(out[i]) end end out[#out + 1] = "" out[#out + 1] = "[policy]" local names = names_of(nodes) local policy = "static=" .. (options.name or "PROXY") .. ", DIRECT" for _, nm in ipairs(names) do policy = policy .. ", " .. nm end - out[#out + 1] = policy + out[#out + 1] = util.one_line(policy) out[#out + 1] = "" out[#out + 1] = "[server_remote]" return table.concat(out, "\n") diff --git a/luci-app-substore/root/usr/share/substore/output_singbox.lua b/luci-app-substore/root/usr/share/substore/output_singbox.lua index bdc95cc23..2ed807fbb 100644 --- a/luci-app-substore/root/usr/share/substore/output_singbox.lua +++ b/luci-app-substore/root/usr/share/substore/output_singbox.lua @@ -33,31 +33,32 @@ local function supported(proto) end -- 构建 TLS 字段 +-- +-- enabled 必须显式写 true:sing-box 的 OutboundTLSOptions.Enabled 是 +-- `bool` + `json:"enabled,omitempty"`(option/tls.go),缺省值即 false。 +-- 上游 common/tls/client.go 里 `if !options.Enabled { return dialer, nil }` +-- 会直接按明文拨号,hysteria2 / tuic 更会因为 `options.TLS == nil || +-- !options.TLS.Enabled` 返回 C.ErrTLSRequired 而拒绝启动。只输出 +-- server_name / insecure 而不带 enabled 等于没配 TLS。 local function build_tls(n) - local tls - if n.security and n.security ~= "none" then - tls = {} - if n.sni or n.servername then tls.server_name = n.sni or n.servername end - if n.alpn then - if type(n.alpn) == "string" then - local list = {} - for p in n.alpn:gmatch("[^,]+") do list[#list + 1] = p:match("^%s*(.-)%s*$") end - tls.alpn = list - else - tls.alpn = n.alpn - end + if not (n.security and n.security ~= "none") then return nil end + local tls = { enabled = true } + if n.sni or n.servername then tls.server_name = n.sni or n.servername end + if n.alpn then + if type(n.alpn) == "string" then + local list = {} + for p in n.alpn:gmatch("[^,]+") do list[#list + 1] = p:match("^%s*(.-)%s*$") end + tls.alpn = list + else + tls.alpn = n.alpn end - if n["skip-cert-verify"] ~= nil then - tls.insecure = bool(n["skip-cert-verify"]) - elseif n.skip_cert_verify ~= nil then - tls.insecure = bool(n.skip_cert_verify) - end - -- 空表会被 json_encode 编码成 [],而 tls 必须是对象; - -- security=tls 但无 sni/alpn/insecure 时就会走到这里 - if next(tls) == nil then return util.JSON_EMPTY_OBJECT end - return tls end - return nil + if n["skip-cert-verify"] ~= nil then + tls.insecure = bool(n["skip-cert-verify"]) + elseif n.skip_cert_verify ~= nil then + tls.insecure = bool(n.skip_cert_verify) + end + return tls end -- 构建传输(transport)字段 @@ -112,12 +113,23 @@ function M.to_outbound(n, tag) elseif stype == "shadowsocks" then o.method = n.method or n.cipher or "aes-256-gcm" o.password = n.password or "" - elseif stype == "hysteria2" or stype == "hysteria" then + elseif stype == "hysteria2" then o.password = n.password or "" - -- 混淆(salamander) + -- 混淆(salamander):hysteria2 的 obfs 是 { type, password } 对象 if n.obfs and n.obfs ~= "" and n.obfs ~= "plain" then o.obfs = { type = n.obfs, password = n["obfs-password"] or n.obfs_password or "" } end + elseif stype == "hysteria" then + -- hysteria(v1) 与 hysteria2 在 sing-box 里的字段名并不相同(已对照上游文档确认): + -- * 认证字段是 auth_str,不是 password(parser_json_config 也是按 + -- outbound.password or outbound.auth_str or outbound.auth 回读的) + -- * obfs 是普通字符串,不是 { type, password } 对象 + -- 注意:sing-box 的 hysteria 出站还要求 up/down(带宽),本项目的节点模型 + -- 不承载该字段,需用户在自己的配置里补上(见 CHANGELOG 已知限制)。 + o.auth_str = n.password or "" + if n.obfs and n.obfs ~= "" and n.obfs ~= "plain" then + o.obfs = n.obfs + end elseif stype == "tuic" then o.uuid = n.uuid or "" o.password = n.password or "" @@ -142,7 +154,8 @@ function M.to_outbound(n, tag) if n["listen-port"] then o.listen_port = tonumber(n["listen-port"]) end if n.mtu then o.mtu = tonumber(n.mtu) end if n.dns then o.dns = n.dns end - elseif stype == "socks" then + elseif stype == "socks" or stype == "http" then + -- socks 与 http 出站的认证字段相同(username / password) if n.username then o.username = n.username end if n.password then o.password = n.password end end diff --git a/luci-app-substore/root/usr/share/substore/output_uri.lua b/luci-app-substore/root/usr/share/substore/output_uri.lua index 7db666f87..4417bd830 100644 --- a/luci-app-substore/root/usr/share/substore/output_uri.lua +++ b/luci-app-substore/root/usr/share/substore/output_uri.lua @@ -84,11 +84,15 @@ function M.to_share_uri(n) local q = {} if n.sni then q[#q + 1] = "sni=" .. url_encode(n.sni) end if n.insecure ~= nil then q[#q + 1] = "insecure=" .. tostring(n.insecure) end - -- 混淆(salamander):hy2 URI 标准参数 obfs / obfs-password + -- 混淆:hysteria2 是 salamander,URI 参数为 obfs / obfs-password; + -- hysteria(v1) 的 obfs 只是普通字符串,**没有** obfs-password + -- (写到 v1 链接上是非法参数,且会误导下游客户端) if n.obfs and n.obfs ~= "" and n.obfs ~= "plain" then q[#q + 1] = "obfs=" .. url_encode(n.obfs) - local opw = n["obfs-password"] or n.obfs_password - if opw and opw ~= "" then q[#q + 1] = "obfs-password=" .. url_encode(opw) end + if proto == "hysteria2" then + local opw = n["obfs-password"] or n.obfs_password + if opw and opw ~= "" then q[#q + 1] = "obfs-password=" .. url_encode(opw) end + end end local suffix = #q > 0 and ("?" .. table.concat(q, "&")) or "" return (proto == "hysteria2" and "hysteria2://" or "hysteria://") diff --git a/luci-app-substore/root/usr/share/substore/output_wireguard_conf.lua b/luci-app-substore/root/usr/share/substore/output_wireguard_conf.lua index 4450a1d09..5b756ab09 100644 --- a/luci-app-substore/root/usr/share/substore/output_wireguard_conf.lua +++ b/luci-app-substore/root/usr/share/substore/output_wireguard_conf.lua @@ -2,6 +2,8 @@ -- luci-app-substore -- 与 parser.parse_wireguard_conf 互为逆操作:导入解析 [Interface] / [Peer],此处按同格式写回。 +local util = require("substore.util") + local M = {} -- 仅 wireguard 节点可用 .conf 表达;其余协议无法落到单行/单段,直接丢弃 @@ -156,7 +158,9 @@ function M.generate(nodes, options) return nil, "该 WireGuard 节点没有私钥 (private-key),无法导出 .conf" end - local lines = { "# " .. (n.name or ((n.server or "") .. ":" .. tostring(n.port or ""))) } + -- 注释行也必须压成单行:节点名来自订阅(不可信),含换行时会注入出真正的 + -- 配置行(例如 "x\n[Interface]"),伪造出一段用户没写过的隧道配置 + local lines = { "# " .. util.one_line(n.name or ((n.server or "") .. ":" .. tostring(n.port or ""))) } for _, line in ipairs(build_section(n)) do lines[#lines + 1] = line end return table.concat(lines, "\n") .. "\n" end diff --git a/luci-app-substore/root/usr/share/substore/parser.lua b/luci-app-substore/root/usr/share/substore/parser.lua index dcbf2928c..a5f06f6d2 100644 --- a/luci-app-substore/root/usr/share/substore/parser.lua +++ b/luci-app-substore/root/usr/share/substore/parser.lua @@ -10,9 +10,15 @@ local parser_surge = require("substore.parser_surge") local M = {} +-- URI 文本导入支持的 scheme。 +-- 必须覆盖 output_uri.to_share_uri 能生成的全部 scheme,否则「导出→导入」回环会 +-- 丢节点:之前 hysteria / socks 只出不进(导出为 hysteria:// / socks5://, +-- 再导入却报 "unsupported proto"),含这两类节点的订阅文本也会被整行丢弃。 +-- socks5 与 socks 都接受,统一归一为 proto="socks"(见 node.normalize)。 local SUPPORTED = { vmess = true, vless = true, trojan = true, ss = true, ssr = true, - hysteria2 = true, tuic = true, wireguard = true, + hysteria = true, hysteria2 = true, tuic = true, wireguard = true, + socks = true, socks5 = true, } local function split_lines(content) @@ -363,6 +369,88 @@ local function parse_hysteria2(uri, body) return out end +-- hysteria://password@host:port/?sni=..&insecure=..&obfs=..#name(v1) +-- 与 hysteria2 的区别(均已对照上游确认): +-- * v1 的 obfs 是普通字符串,没有 obfs-password(obfs-password 是 hysteria2 的 salamander) +-- * 两者在 mihomo / sing-box 里都是 TLS-only,因此同样补 security="tls" +-- 认不出的查询参数一律忽略(不报错),保证第三方生成的链接仍能解析出 server/port/password。 +local function parse_hysteria(uri, body) + local name, rest = "", body + local hash = rest:find("#", 1, true) + if hash then + name = util.url_decode(rest:sub(hash + 1)) + rest = rest:sub(1, hash - 1) + end + local query = {} + local qpos = rest:find("?", 1, true) + local hp = rest + if qpos then + hp = rest:sub(1, qpos - 1) + for k, v in rest:sub(qpos + 1):gmatch("([^&=]+)=([^&]*)") do + query[k] = util.url_decode(v) + end + end + local at = hp:find("@", 1, true) + if not at then return nil, "bad hysteria" end + local password = util.url_decode(hp:sub(1, at - 1)) + local host, port = util.split_hostport(hp:sub(at + 1)) + if not host or host == "" then return nil, "bad hysteria" end + local out = node.normalize({ + proto = "hysteria", name = name, server = host, port = tonumber(port), + password = password, raw = uri, + }) + if query.sni then out.sni = query.sni end + out.security = "tls" + if query.insecure ~= nil then + out.insecure = query.insecure + out["skip-cert-verify"] = not (query.insecure == "0" or query.insecure == "false") + end + if query.obfs and query.obfs ~= "" then out.obfs = query.obfs end + return out +end + +-- socks5://user:pass@host:port#name(socks:// 同义) +-- 认证信息可选:没有 userinfo 时是无认证 socks。统一归一为 proto="socks"。 +local function parse_socks(uri, body) + local name, rest = "", body + local hash = rest:find("#", 1, true) + if hash then + name = util.url_decode(rest:sub(hash + 1)) + rest = rest:sub(1, hash - 1) + end + -- socks 没有标准查询参数,但第三方链接可能带 ? 尾巴,截掉以免污染 host:port + local qpos = rest:find("?", 1, true) + local hp = qpos and rest:sub(1, qpos - 1) or rest + + local username, password + -- 取**最后**一个 @ 作为 userinfo 与 authority 的分界:未编码的 @ 只可能出现在 + -- 密码里(userinfo 不允许裸 @),按第一个 @ 切会把 "p@ss" 这类密码切坏, + -- 而且失败是静默的(解析出一个错的密码)。 + local userinfo, hostport = hp:match("^(.*)@([^@]*)$") + if not userinfo then + hostport = hp + else + userinfo = util.url_decode(userinfo) + local cpos = userinfo:find(":", 1, true) + if cpos then + username = userinfo:sub(1, cpos - 1) + password = userinfo:sub(cpos + 1) + else + username = userinfo + end + if username == "" then username = nil end + end + + local host, port = util.split_hostport(hostport) + if not host or host == "" then return nil, "bad socks" end + local out = node.normalize({ + proto = "socks", name = name, server = host, port = tonumber(port), raw = uri, + }) + if username then out.username = username end + if password then out.password = password end + return out +end + -- tuic://uuid:password@host:port/?congestion_control=..&alpn=..&sni=..#name local function parse_tuic(uri, body) local name, rest = "", body @@ -617,9 +705,11 @@ function M.parse_uri(uri) if proto == "vless" then return parse_vless(uri, body) end if proto == "trojan" then return parse_trojan(uri, body) end if proto == "vmess" then return parse_vmess(uri, body) end + if proto == "hysteria" then return parse_hysteria(uri, body) end if proto == "hysteria2" then return parse_hysteria2(uri, body) end if proto == "tuic" then return parse_tuic(uri, body) end if proto == "wireguard" then return parse_wireguard(uri, body) end + if proto == "socks" or proto == "socks5" then return parse_socks(uri, body) end return nil, "unsupported" end @@ -730,38 +820,72 @@ local function parse_yaml_content(content) raw_nodes[#raw_nodes + 1] = current_node end - -- 协议映射:Clash type -> proto - local proto_map = { - vmess = "vmess", - vless = "vless", - trojan = "trojan", - ss = "shadowsocks", - ssr = "ssr", - http = "http", - socks5 = "socks5", - } + -- 协议映射:Clash type -> proto。 + -- 复用 parser_clash_yaml 的权威表(单一事实来源),本处曾自维护一份,缺 + -- hysteria2/hysteria/tuic/wireguard 且 socks5 未归一,后果是: + -- * 认不出的 type 被 `or "vmess"` 兜底成 vmess —— 一份 sing-box YAML 里的 + -- hysteria2/tuic/wireguard 出站会变成 4 个没有 uuid 的假 vmess 节点(静默数据损坏) + -- * socks5 原样保留,而节点页筛选/规则 proto_filter 用的是规范名 socks,节点查不到 + local proto_map = parser_clash_yaml.TYPE_MAP -- 转换字段名并归一化 local result = {} for _, n in ipairs(raw_nodes) do - if not n or not n.server or not n.port then - -- 跳过无效节点 + local proto = proto_map[n.type or n.proto] + -- 上面的 in_proxies 分支同时接受 `proxies:`(Clash)与 `outbounds:`(sing-box) + -- 两种段名,但两者字段名并不相同:Clash 用 port / name,sing-box 用 + -- server_port / tag。此前只读 port / name,导致 sing-box YAML 的 outbounds + -- 全部卡在下面的 `not port` 判断上被静默丢弃(识别了段名却一个节点都拿不到)。 + -- 下列别名逐字对照 parser_json_config.parse_singbox_json 读取的键名, + -- 那是本项目读取 sing-box 出站的权威实现,不另立一套。 + local port = n.port or n.server_port + if not n or not n.server or not port or not proto then + -- 跳过无效节点 / 未知协议。 + -- 未知协议不能兜底成 vmess:那是凭空造出一个字段全错的节点, + -- 比丢弃更糟(用户看到"导入成功",实际拿到一批不可用的假节点)。 else - local proto = proto_map[n.type or n.proto] or "vmess" + -- vmess 的加密方式:Clash 写 cipher,sing-box 写 security。 + -- security 在 node.normalize 里是 TLS 层,两者语义冲突,因此仅当取值 + -- 落在 vmess 加密方式白名单内时才当作 cipher 消费掉,否则留给 TLS 层。 + local vmess_cipher + if proto == "vmess" then + vmess_cipher = n.cipher + if vmess_cipher == nil and n.security ~= nil + and node.VMESS_CIPHERS[n.security] then + vmess_cipher = n.security + end + end + -- 同上的字符串真值问题:只认明确的真值写法 + local scv = n["skip-cert-verify"] or n.insecure + local skip_cert_verify = nil + if scv == true or scv == "true" or scv == "1" then skip_cert_verify = true + elseif scv == false or scv == "false" or scv == "0" then skip_cert_verify = false end + -- 注意不能用 `(cond) and nil or x` 写法:Lua 的 and/or 在 cond 为真时 + -- 结果是 nil,会被后面的 or 继续兜底,等于没生效 + local tls_security = n.security + if vmess_cipher ~= nil then tls_security = nil end local node_data = { proto = proto, - name = n.name or n.Name or (n.server .. ":" .. tostring(n.port or "")), + name = n.name or n.Name or n.tag or (n.server .. ":" .. tostring(port)), server = n.server, - port = tonumber(n.port), + port = tonumber(port), uuid = n.uuid or n.id, - password = n.password, + -- sing-box 的 hysteria/hysteria2 认证字段是 password / auth_str / auth + password = n.password or n.auth_str or n.auth, method = n.cipher or n.method, -- Clash 的 cipher 是 vmess 加密方式;tls 才是 TLS 层, -- 交由 node.normalize 归一到 security - cipher = (proto == "vmess") and n.cipher or nil, + cipher = vmess_cipher, tls = n.tls, - security = n.security, - sni = n.sni or n.servername, + -- sing-box 的 vmess.security 已被上面消费为 cipher,不再当 TLS 层 + security = tls_security, + -- Clash 写 sni / servername,sing-box 的 tls 子块写 server_name + sni = n.sni or n.servername or n.server_name, + -- sing-box 的 tls.insecure 对应 skip-cert-verify。 + -- 行解析器读出来的是字符串,而 "false" / "0" 在 Lua 里也是真值, + -- 直接透传会让 skip-cert-verify=false 变成「跳过证书校验」,故显式判假。 + ["skip-cert-verify"] = skip_cert_verify, + net = n.net or n.network, alterId = tonumber(n.alterId), } result[#result + 1] = node.normalize(node_data) @@ -888,6 +1012,17 @@ function M.parse(content) -- 兼容标准 base64 与 base64url(- _ 无 padding):base64_url_decode 两者皆可 local decoded = util.base64_url_decode(content) if decoded == "" then return nil, "Base64 解码失败" end + -- 解出来的内容本身可能是 YAML / JSON:机场把整份 Clash 配置或 sing-box + -- 配置 base64 后直接下发是很常见的做法。原先一律按 URI 列表解析,这类 + -- 订阅会得到 0 个节点且不报错(用户只看到「订阅为空」)。 + -- 递归走一遍 detect/parse 复用既有分支;inner == "base64" 时不再递归, + -- 避免 base64 套 base64 时无限递归。外层容器格式仍是 base64。 + local inner = M.detect(decoded) + if inner ~= "base64" and inner ~= "empty" and inner ~= "unknown" then + local res, err = M.parse(decoded) + if res then res.format = "base64" end + return res, err + end return { nodes = parse_lines(split_lines(decoded)), format = "base64" } elseif format == "json" then local nodes, err = parse_json_content(content) diff --git a/luci-app-substore/root/usr/share/substore/parser_clash_yaml.lua b/luci-app-substore/root/usr/share/substore/parser_clash_yaml.lua index dfb39606b..efecdcb64 100644 --- a/luci-app-substore/root/usr/share/substore/parser_clash_yaml.lua +++ b/luci-app-substore/root/usr/share/substore/parser_clash_yaml.lua @@ -7,7 +7,10 @@ local node = require("substore.node") local M = {} --- Clash type → 统一 proto +-- Clash type → 统一 proto。 +-- 这是**权威映射表**:parser_json_config 与 parser.lua 的简易 YAML 兜底解析都复用同一份, +-- 避免各自维护一份而漂移(曾出现兜底那份缺 hysteria2/hysteria/tuic/wireguard, +-- 且把 socks5 原样留下,导致这些节点被误当成 vmess 或被筛选器静默丢弃)。 local TYPE_MAP = { vmess = "vmess", vless = "vless", @@ -24,6 +27,9 @@ local TYPE_MAP = { http = "http", } +-- 导出供 parser.lua 的简易 YAML 兜底解析复用(单一事实来源) +M.TYPE_MAP = TYPE_MAP + -- 标量值转换:布尔 / 数字 / 去引号 / 保留字符串 local function scalar(raw) raw = raw or "" @@ -47,6 +53,74 @@ local function scalar(raw) return raw end +-- 去掉行尾注释。YAML 规定内联注释的 # 前必须有空白,引号内的 # 不算注释。 +-- 不处理的话 `proxies: # 说明` 会把注释文本当成值,proxies 变成字符串, +-- 整份配置被判定为「没有 proxies」→ 0 个节点且不报错。 +local function strip_comment(v) + local in_s, in_d = false, false + for i = 1, #v do + local c = v:sub(i, i) + if in_s then + if c == "'" then in_s = false end + elseif in_d then + if c == '"' then in_d = false end + elseif c == "'" then in_s = true + elseif c == '"' then in_d = true + elseif c == "#" and (i == 1 or v:sub(i - 1, i - 1):match("%s")) then + return (v:sub(1, i - 1):gsub("%s*$", "")) + end + end + return v +end + +-- 按顶层分隔符切分,忽略引号内以及 {} / [] 内部的同级分隔符 +local function split_top(s, sep) + local parts, buf = {}, {} + local depth, in_s, in_d = 0, false, false + for i = 1, #s do + local c = s:sub(i, i) + if in_s then + if c == "'" then in_s = false end + buf[#buf + 1] = c + elseif in_d then + if c == '"' then in_d = false end + buf[#buf + 1] = c + elseif c == "'" then + in_s = true; buf[#buf + 1] = c + elseif c == '"' then + in_d = true; buf[#buf + 1] = c + elseif c == "{" or c == "[" then + depth = depth + 1; buf[#buf + 1] = c + elseif c == "}" or c == "]" then + depth = depth - 1; buf[#buf + 1] = c + elseif c == sep and depth == 0 then + parts[#parts + 1] = table.concat(buf); buf = {} + else + buf[#buf + 1] = c + end + end + parts[#parts + 1] = table.concat(buf) + return parts +end + +-- 解析 YAML 流式映射 {...}。Clash 机场配置常用 +-- `- {name: A, type: vmess, server: 1.1.1.1, port: 443}` 这种写法:它是合法 YAML, +-- 但不是合法 JSON(键没有加引号),util.json_decode 必然失败,节点被整条静默 +-- 丢弃(0 个节点且无报错)。 +local function parse_flow_map(s) + local body = s:match("^%s*{(.*)}%s*$") + if not body then return nil end + local map = {} + for _, part in ipairs(split_top(body, ",")) do + local k, v = part:match("^%s*([^:]+):%s*(.*)$") + if k then + map[k:gsub("%s*$", "")] = scalar(strip_comment(v)) + end + end + if next(map) == nil then return nil end + return map +end + -- 预处理内容为 (indent, rest) 列表,跳过空行、注释、文档分隔符 local function preprocess(content) local items = {} @@ -79,6 +153,9 @@ local function parse_yaml(content) pos = pos + 1 else k = k:gsub("%s*$", "") + -- 行尾注释必须先去掉,否则 `proxies: # 说明` 会把注释文本当成值, + -- proxies 变成字符串,整份配置被判定为「没有 proxies」 + v = strip_comment(v) pos = pos + 1 if v == "" or v == "|" or v == ">" then if pos <= n_items and items[pos].ind > it.ind then @@ -108,12 +185,17 @@ local function parse_yaml(content) if it.rest == "-" then dash = "" else dash = it.rest:match("^-%s*(.*)$") end if dash == nil then break end pos = pos + 1 + -- 列表项也要去掉行尾注释:`- {a: 1} # 说明`、`- "::/0" # 说明` + -- 都会让注释文本混进值里(流式映射那条甚至会整项解析失败) + dash = strip_comment(dash) local m = nil -- 流式 JSON 对象:- {"name":"...","type":"vmess",...}(机场 clash 配置常见写法) if dash:sub(1, 1) == "{" then + -- 先按 JSON 解(键带引号的流式写法),失败再按 YAML 流式映射解 local obj = util.json_decode(dash) if type(obj) == "table" then m = obj end + if not m then m = parse_flow_map(dash) end else local k, v = dash:match("^([^:]+):%s*(.*)$") -- 引号开头的列表项是标量而非映射:避免把 "- \"::/0\"" 里的冒号 @@ -152,7 +234,15 @@ local function map_clash_node(p) if type(p) ~= "table" then return nil end if not p.name or not p.server or not p.port then return nil end - local proto = TYPE_MAP[p.type] or p.type or "vmess" + -- 未知协议必须丢弃,不能原样透传、也不能兜底成 vmess: + -- * 原样透传:统一模型承载不了 snell / shadowtls / mieru / ssh 等类型(认证 + -- 方式与字段都不同),透传出去会在输出端变成 sing-box 的 type: "snell"、 + -- Xray 的 protocol: "snell" 这类非法取值,客户端会拒绝加载整份配置。 + -- * 兜底成 vmess:那是凭空造出一个字段全错的节点,比丢弃更糟(用户看到 + -- "导入成功",实际拿到一批不可用的假节点)。 + -- parser.lua 的简易 YAML 兜底解析(复用同一张 TYPE_MAP)早已按此处理,此处对齐。 + local proto = TYPE_MAP[p.type] + if not proto then return nil end local n = { proto = proto, name = p.name, diff --git a/luci-app-substore/root/usr/share/substore/parser_json_config.lua b/luci-app-substore/root/usr/share/substore/parser_json_config.lua index 9c8ae2ce6..67ffe0ec1 100644 --- a/luci-app-substore/root/usr/share/substore/parser_json_config.lua +++ b/luci-app-substore/root/usr/share/substore/parser_json_config.lua @@ -102,7 +102,10 @@ function M.parse_singbox_json(content) node_data.password = outbound.password end - -- sing-box 用 tls 对象表达 TLS 层(enabled 缺省即 true) + -- sing-box 用 tls 对象表达 TLS 层。注意 enabled 的缺省值是 false + -- (option/tls.go: `Enabled bool` + omitempty),本输出模块因此总是 + -- 显式写 enabled=true。读取侧这里放宽为「只要不是显式 false 就当作 + -- 启用」,以便导入那些省略 enabled 的第三方配置时仍能保留 TLS 层。 if outbound.tls and type(outbound.tls) == "table" then if outbound.tls.server_name then node_data.sni = outbound.tls.server_name diff --git a/luci-app-substore/root/usr/share/substore/util.lua b/luci-app-substore/root/usr/share/substore/util.lua index 385d78ae8..acd5b34be 100644 --- a/luci-app-substore/root/usr/share/substore/util.lua +++ b/luci-app-substore/root/usr/share/substore/util.lua @@ -77,12 +77,46 @@ function M.shq(s) return "'" .. tostring(s or ""):gsub("'", "'\\''") .. "'" end +-- 把值压成单行。Surge / Loon / Quantumult X / wg-quick .conf 都是行式格式: +-- 值里一旦含换行,就会截断当前行并伪造出额外的一行(节点名、sni、path 等 +-- 全部来自订阅内容,属于不可信输入)。换行/回车压成空格,其余控制字符丢弃。 +function M.one_line(s) + if s == nil then return nil end + return (tostring(s):gsub("[\r\n]+", " "):gsub("%c", "")) +end + -- 生成随机十六进制 token(用于下载链接访问控制) +-- +-- 不能直接用 math.random 产出:Lua 5.1 的 math.random 是 31 位 LCG,而原实现 +-- 每次调用都重新 randomseed,同一时钟刻度内的多次调用会给出完全相同的序列 +-- (实测 20 万次调用只有约 18 万个不同值,约 9.7% 的 token 重复)。订阅下载 +-- token 是访问控制的唯一凭据,重复即可被猜测。优先直接读内核熵源, +-- 只有在 /dev/urandom 不可用时才退回 PRNG(且只播种一次)。 +local prng_seeded = false +local function seed_prng() + if prng_seeded then return end + prng_seeded = true + math.randomseed(os.time() + math.floor((os.clock() * 1000000) % 1000000)) +end + function M.rnd_hex(len) len = len or 16 + local f = io.open("/dev/urandom", "rb") + if f then + local need = math.ceil(len / 2) + local bytes = f:read(need) + f:close() + if bytes and #bytes == need then + local out = {} + for i = 1, #bytes do + out[#out + 1] = string.format("%02x", bytes:byte(i)) + end + return (table.concat(out):sub(1, len)) + end + end + seed_prng() local hex = "0123456789abcdef" local out = {} - math.randomseed(os.time() + (os.clock() * 1000000 % 1000000) + math.random(0, 65535)) for _ = 1, len do local idx = math.random(1, 16) out[#out + 1] = hex:sub(idx, idx) @@ -345,17 +379,33 @@ function M.file_size(path) return #data end --- 原子写:先写临时文件再重命名,避免写一半损坏 +-- 原子写:先写临时文件再重命名,避免写一半损坏。 +-- +-- 两处必须做对,否则「原子」只是名义上的: +-- 1) 临时文件名不能固定成 ".tmp":两个进程同时写同一路径时会交错写进 +-- 同一个临时文件,rename 上去的是两者内容的混合体,各自的原子性都失效。 +-- 2) write / close 的返回值必须检查:磁盘写满或写入被截断时 f:write 会失败, +-- 但 os.rename 依然成功 —— 于是原子地换上一个残缺文件,调用方却以为成功, +-- 下一次读取才发现数据没了。 function M.atomic_write(path, content) - local tmp = path .. ".tmp" + local tmp = string.format("%s.tmp.%s", path, M.rnd_hex(8)) local f, e = io.open(tmp, "wb") if not f then return false, e end - f:write(content) - f:close() - local ok, e2 = os.rename(tmp, path) - if not ok then + local wok, werr = f:write(content) + if not wok then + f:close() os.remove(tmp) - return false, e2 + return false, werr + end + local cok, cerr = f:close() + if not cok then + os.remove(tmp) + return false, cerr + end + local rok, rerr = os.rename(tmp, path) + if not rok then + os.remove(tmp) + return false, rerr end return true end diff --git a/luci-app-substore/root/www/luci-static/resources/substore/nodeform.js b/luci-app-substore/root/www/luci-static/resources/substore/nodeform.js index 18c4dfce5..0dca4f8e5 100644 --- a/luci-app-substore/root/www/luci-static/resources/substore/nodeform.js +++ b/luci-app-substore/root/www/luci-static/resources/substore/nodeform.js @@ -5,7 +5,10 @@ * 提供:SUBSTORE_PROTOS / PROTO_FIELDS / renderFields / collectNodes / addNodeRow */ -var SUBSTORE_PROTOS = ["vmess","vless","trojan","shadowsocks","ssr","hysteria2","tuic","wireguard"]; +// 必须与 substore/node.lua 的 M.PROTOS 一致(规格 §25「本地表单协议能力」的协议集合)。 +// 之前这里少了 hysteria / socks:node.lua、节点页筛选、规则 proto_filter 都认这两个协议, +// 唯独表单下拉框选不到,用户无法用「表单导入」录入它们。 +var SUBSTORE_PROTOS = ["vmess","vless","trojan","shadowsocks","ssr","hysteria2","tuic","hysteria","wireguard","socks"]; var PROTO_FIELDS = { ssr: ["server","port","password","cipher","protocol","obfs","obfs-param","protocol-param","udp"], @@ -14,8 +17,12 @@ var PROTO_FIELDS = { trojan: ["server","port","password","sni","net","headerType","path","host","udp","skip-cert-verify"], shadowsocks: ["server","port","password","method","headerType","udp"], hysteria2: ["server","port","password","sni","obfs","obfs-password","skip-cert-verify"], + // hysteria(v1):obfs 是普通字符串(不是 hysteria2 的 salamander),因此没有 obfs-password。 + // 字段集合以各输出模块实际消费的键为准(output_clash_meta / output_singbox / output_uri)。 + hysteria: ["server","port","password","sni","obfs","skip-cert-verify"], tuic: ["server","port","uuid","password","sni","udp","skip-cert-verify"], - wireguard: ["server","port","private-key","public-key","pre-shared-key","ip","ipv6","allowed-ips","reserved","persistent-keepalive","listen-port","mtu","amnezia-wg-option"] + wireguard: ["server","port","private-key","public-key","pre-shared-key","ip","ipv6","allowed-ips","reserved","persistent-keepalive","listen-port","mtu","amnezia-wg-option"], + socks: ["server","port","username","password","udp"] }; // 枚举字段用下拉框;键为 "协议.字段" 优先,退化为通用 "字段" diff --git a/luci-app-substore/tests/data_integrity_test.lua b/luci-app-substore/tests/data_integrity_test.lua new file mode 100644 index 000000000..ae437cf7d --- /dev/null +++ b/luci-app-substore/tests/data_integrity_test.lua @@ -0,0 +1,132 @@ +-- data_integrity_test.lua — 数据完整性与 token 熵回归测试 +-- 用法:lua5.1 tests/data_integrity_test.lua +-- +-- 覆盖: +-- H8 订阅列表文件损坏时必须报错并拒绝写入,而不是按空列表处理 +-- (否则下一次 add 会把用户所有订阅覆盖掉) +-- H9 atomic_write 必须检查 write / close 的返回值 +-- H10 临时文件名必须唯一,并发写同一路径不得互相踩踏、不得残留 +-- H11 下载 token 必须来自内核熵源,不得出现可预测的重复 + +package.path = "./root/usr/share/?.lua;" .. package.path + +local core = require("substore.core") +local util = require("substore.util") + +local passed, failed = 0, 0 + +local function check(name, cond) + if cond then + passed = passed + 1 + print("PASS " .. name) + else + failed = failed + 1 + print("FAIL " .. name) + end +end + +-- 重定向数据目录到临时目录,避免污染系统 +local tmp = os.tmpname() .. "_substore" +os.execute("mkdir -p " .. string.format("%q", tmp .. "/nodes")) +core.DATA_DIR = tmp +core.LIST_FILE = tmp .. "/subscriptions.json" +core.NODES_DIR = tmp .. "/nodes" + +-- ---------- H8:损坏的列表文件 ---------- + +local id1 = core.add("订阅一", "http://example.com/a") +check("add first subscription", id1 ~= nil) +check("list count after add", #core.list() == 1) + +local good = util.read_file(core.LIST_FILE) +check("list file written", good ~= nil and good ~= "") + +-- 把文件写成无法解析的内容,模拟截断 / 磁盘损坏 +util.atomic_write(core.LIST_FILE, "{ 这不是合法 JSON") + +local arr, lerr = core.list() +check("list reports corruption", lerr ~= nil and type(lerr) == "string") +check("list returns empty array on corruption", type(arr) == "table" and #arr == 0) + +-- 关键:写入路径必须拒绝,而不是在空表上追加后整表写回 +local id2, aerr = core.add("订阅二", "http://example.com/b") +check("add refuses on corruption", id2 == nil) +check("add returns corruption error", aerr ~= nil and aerr:find("损坏", 1, true) ~= nil) + +local id3, lerr2 = core.add_local("本地订阅", "vmess://x") +check("add_local refuses on corruption", id3 == nil and lerr2 ~= nil) + +local id4, cerr = core.add_combo("组合", { id1 }) +check("add_combo refuses on corruption", id4 == nil and cerr ~= nil) + +check("corrupt file not overwritten", util.read_file(core.LIST_FILE) == "{ 这不是合法 JSON") +check("save_meta refuses on corruption", (core.save_meta(id1, { name = "x" })) == false) + +-- 恢复后必须能继续正常写入,且 _seq 不得回退(否则会重复发放已用过的 ID) +util.atomic_write(core.LIST_FILE, good) +check("list recovers", #core.list() == 1) +local id5 = core.add("订阅三", "http://example.com/c") +check("add works after recovery", id5 ~= nil) +check("id not reused after recovery", id5 ~= nil and id5 ~= id1) + +-- ---------- H9:atomic_write 的返回值 ---------- + +local ok_bad, err_bad = util.atomic_write("/proc/substore-nonexistent/x.json", "data") +check("atomic_write fails on bad path", ok_bad == false) +check("atomic_write returns error", err_bad ~= nil) + +local target = tmp .. "/atomic.txt" +check("atomic_write succeeds", util.atomic_write(target, "hello") == true) +check("atomic_write content", util.read_file(target) == "hello") +check("atomic_write overwrites", util.atomic_write(target, "world") == true + and util.read_file(target) == "world") + +-- ---------- H10:临时文件名唯一、无残留 ---------- + +local base = tmp .. "/concurrent.txt" +local names = {} +for _ = 1, 20 do + local n = string.format("%s.tmp.%s", base, util.rnd_hex(8)) + names[n] = true +end +local distinct = 0 +for _ in pairs(names) do distinct = distinct + 1 end +check("tmp names are unique", distinct == 20) + +-- 写完后不得在目标目录留下 .tmp 文件 +os.execute("rm -f " .. string.format("%q", tmp) .. "/*.tmp.*") +util.atomic_write(base, "x") +local listing = tmp .. "/ls.txt" +os.execute("ls -a " .. string.format("%q", tmp) .. " > " .. string.format("%q", listing)) +local ls = util.read_file(listing) or "" +local leftover = 0 +for name in ls:gmatch("[^\n]+") do + if name:find("%.tmp%.") then leftover = leftover + 1 end +end +check("no leftover tmp files", leftover == 0) + +-- ---------- H11:token 熵 ---------- + +local seen, dups, N = {}, 0, 20000 +for _ = 1, N do + local t = util.rnd_hex(16) + if seen[t] then dups = dups + 1 else seen[t] = true end +end +check("no duplicate tokens in " .. N .. " draws", dups == 0) + +local tok = util.rnd_hex(16) +check("token length 16", #tok == 16) +check("token is lowercase hex", tok:match("^[0-9a-f]+$") ~= nil) +check("token length honoured for odd len", #util.rnd_hex(7) == 7) +check("token length honoured for 32", #util.rnd_hex(32) == 32) + +-- 订阅 token 走同一条路径 +local t1 = core.ensure_token(id1) +check("subscription token length", type(t1) == "string" and #t1 == 16) +check("subscription token stable", core.ensure_token(id1) == t1) + +os.execute("rm -rf " .. string.format("%q", tmp)) + +-- ---------- 结果 ---------- +print(string.format("\n%d passed, %d failed", passed, failed)) +os.exit(failed == 0 and 0 or 1) diff --git a/luci-app-substore/tests/output_clash_meta_test.lua b/luci-app-substore/tests/output_clash_meta_test.lua index df21c9df2..0a6eb56b6 100644 --- a/luci-app-substore/tests/output_clash_meta_test.lua +++ b/luci-app-substore/tests/output_clash_meta_test.lua @@ -148,5 +148,29 @@ local empty_output = output_clash_meta.generate({}, {}) check("empty nodes handled", type(empty_output) == "string") -- ---------- 结果 ---------- +-- H12:sni 与 servername 是同一字段的两种写法,同时存在时只能输出一个 servername +-- 键。Clash YAML 导入会同时填上两者,各写一行会让 YAML 出现重复键。 +local dup_out = output_clash_meta.generate({ { proto = "vmess", name = "D", server = "1.1.1.1", + port = 443, uuid = "u", sni = "s.example.com", servername = "s.example.com" } }) +local dup_count = 0 +for _ in dup_out:gmatch("servername:") do dup_count = dup_count + 1 end +check("no duplicate servername key", dup_count == 1) +check("servername value kept", dup_out:find("servername: s%.example%.com") ~= nil) +check("servername only still emitted", + output_clash_meta.generate({ { proto = "vmess", name = "S", server = "1.1.1.1", port = 443, + uuid = "u", servername = "only.example.com" } }):find("servername: only%.example%.com") ~= nil) + +-- H13:含控制字符的值必须转义并加双引号。未加引号的换行/回车会破坏文档结构, +-- 而转义后的 "\t" 落在 plain scalar 里会被 YAML 当成两个普通字符。 +local esc_out = output_clash_meta.generate({ { proto = "vmess", name = "tab\there", server = "1.1.1.1", + port = 443, uuid = "u", password = "p\rw" } }) +check("tab escaped and quoted", esc_out:find('"tab\\there"') ~= nil) +check("CR escaped and quoted", esc_out:find('"p\\rw"') ~= nil) +check("no raw CR in output", esc_out:find("\r") == nil) +local nl_out = output_clash_meta.generate({ { proto = "vmess", name = "a\nb", server = "1.1.1.1", + port = 443, uuid = "u" } }) +check("newline name quoted and escaped", nl_out:find('name: "a\\nb"') ~= nil) +check("newline name does not add a line", nl_out:find('name: a\nb') == nil) + print(string.format("\n%d passed, %d failed", passed, failed)) os.exit(failed == 0 and 0 or 1) diff --git a/luci-app-substore/tests/output_formats_test.lua b/luci-app-substore/tests/output_formats_test.lua index 1f873630f..eada2a676 100644 --- a/luci-app-substore/tests/output_formats_test.lua +++ b/luci-app-substore/tests/output_formats_test.lua @@ -4,6 +4,7 @@ package.path = "./root/usr/share/?.lua;" .. package.path local output = require("substore.output") +local fmts = require("substore.output_formats") local util = require("substore.util") local passed, failed = 0, 0 @@ -100,5 +101,52 @@ check("unknown format has err", err ~= nil) -- 空节点 check("empty nodes ok", type(output.generate({}, "surge")) == "string") +-- H14:tuic 的 alpn 可能是数组(sing-box JSON / Clash YAML 的 alpn 列表导入后即为 +-- table),直接 "alpn=" .. n.alpn 会 attempt to concatenate a table value, +-- 让整次导出直接报错。 +local ok_alpn, line_alpn = pcall(fmts.surge_line, { proto = "tuic", name = "T", server = "1.2.3.4", + port = 443, uuid = "u", password = "p", security = "tls", sni = "s.example.com", + alpn = { "h3", "h2" } }) +check("tuic alpn array does not raise", ok_alpn) +check("tuic alpn array joined", ok_alpn and line_alpn:find("alpn=h3,h2", 1, true) ~= nil) +check("tuic alpn string still works", + fmts.surge_line({ proto = "tuic", name = "T", server = "1.2.3.4", port = 443, uuid = "u", + alpn = "h3" }):find("alpn=h3", 1, true) ~= nil) + +-- H7:节点名 / 参数值来自订阅内容(不可信输入),含换行会截断当前行并伪造出 +-- 一条新的代理行。 +local nl_line = fmts.surge_line({ proto = "trojan", name = "A\nB = trojan, 6.6.6.6, 443, password=x", + server = "1.1.1.1", port = 443, password = "p", security = "tls" }) +check("surge line has no newline", nl_line:find("\n") == nil) +check("surge line has no CR", nl_line:find("\r") == nil) +check("surge line keeps name prefix", nl_line:sub(1, 1) == "A") + +local function count_lines(s) + local c = 0 + for _ in s:gmatch("\n") do c = c + 1 end + return c +end + +-- 代理组行同样不能被节点名注入:压平后的名字不得让输出多出一行, +-- 也不得产生一条以注入内容开头的新行 +local grp = fmts.to_surge({ { proto = "trojan", name = "G\nINJECT = trojan, 9.9.9.9, 443, password=q", + server = "1.1.1.1", port = 443, password = "p", security = "tls" } }) +local grp_ok = fmts.to_surge({ { proto = "trojan", name = "GINJECT = trojan, 9.9.9.9, 443, password=q", + server = "1.1.1.1", port = 443, password = "p", security = "tls" } }) +check("surge group newline name adds no line", count_lines(grp) == count_lines(grp_ok)) +local starts_inject = false +for l in grp:gmatch("[^\n]+") do + if l:sub(1, 6) == "INJECT" then starts_inject = true end +end +check("surge group line not injected", starts_inject == false) + +-- Quantumult X:节点名含换行不得让输出多出一行 +local qx_nl = fmts.to_qx({ { proto = "trojan", name = "X\nY", server = "1.1.1.1", port = 443, + password = "p" } }) +local qx_ok = fmts.to_qx({ { proto = "trojan", name = "XY", server = "1.1.1.1", port = 443, + password = "p" } }) +check("qx newline name does not add lines", count_lines(qx_nl) == count_lines(qx_ok)) +check("qx newline name flattened", qx_nl:find("X Y", 1, true) ~= nil) + print(string.format("\n%d passed, %d failed", passed, failed)) os.exit(failed == 0 and 0 or 1) \ No newline at end of file diff --git a/luci-app-substore/tests/output_full_config_test.lua b/luci-app-substore/tests/output_full_config_test.lua index 438378e24..8469b3ef7 100644 --- a/luci-app-substore/tests/output_full_config_test.lua +++ b/luci-app-substore/tests/output_full_config_test.lua @@ -10,6 +10,7 @@ local util = require("substore.util") local output = require("substore.output") local singbox = require("substore.output_singbox") local v2ray = require("substore.output_v2ray") +local sbjson = require("substore.parser_json_config") local passed, failed = 0, 0 @@ -96,13 +97,44 @@ check("sb route private -> direct", sb.route.rules[1].ip_is_private == true and -- action 自 1.11.0 起才存在且默认即 "route";省略它才能同时兼容 1.10 与 1.11+ check("sb route rule omits action (version compat)", sb.route.rules[1].action == nil) --- tls 必须是对象:security=tls 但无 sni 时曾产出非法的 "tls":[] +-- tls 必须是对象,且必须显式 enabled=true:sing-box 的 OutboundTLSOptions.Enabled +-- 是 `bool` + `json:"enabled,omitempty"`(option/tls.go),缺省值即 false。少了 +-- enabled 整个 tls 块会被上游忽略 —— vmess/vless/trojan 退化成明文拨号, +-- hysteria2/tuic 更会以 C.ErrTLSRequired 拒绝启动。此处原本断言 "tls":{}, +-- 等于把这个缺陷固化进了测试。 local tls_node = { { proto = "vmess", name = "T", server = "1.1.1.1", port = 443, uuid = "u", security = "tls" } } local tls_raw = singbox.generate(tls_node) -check("sb tls is object not array", tls_raw:find('"tls":{}') ~= nil and tls_raw:find('"tls":%[%]') == nil) -check("sb tls with sni keeps server_name", - singbox.generate({ { proto = "vmess", name = "T", server = "1.1.1.1", port = 443, uuid = "u", - security = "tls", sni = "example.com" } }):find('"server_name":"example.com"') ~= nil) +check("sb tls is object not array", tls_raw:find('"tls":%[%]') == nil) +local tls_out = util.json_decode(tls_raw).outbounds[1].tls +check("sb tls enabled explicit true", type(tls_out) == "table" and tls_out.enabled == true) + +local tls_sni = util.json_decode(singbox.generate({ { proto = "vmess", name = "T", server = "1.1.1.1", port = 443, + uuid = "u", security = "tls", sni = "example.com" } })).outbounds[1].tls +check("sb tls with sni keeps server_name", tls_sni.server_name == "example.com") +check("sb tls with sni keeps enabled", tls_sni.enabled == true) + +-- 无 TLS 的节点不得凭空得到 tls 块(enabled 不能无条件写) +local no_tls = util.json_decode(singbox.generate({ { proto = "vmess", name = "N", server = "1.1.1.1", + port = 443, uuid = "u" } })).outbounds[1] +check("sb no tls block without security", no_tls.tls == nil) +check("sb security none yields no tls", + util.json_decode(singbox.generate({ { proto = "vmess", name = "N", server = "1.1.1.1", port = 443, + uuid = "u", security = "none" } })).outbounds[1].tls == nil) + +-- hysteria2 / tuic 在 sing-box 里是 TLS-only,security=tls 时必须带 enabled=true +local hy2 = util.json_decode(singbox.generate({ { proto = "hysteria2", name = "H", server = "1.1.1.1", + port = 443, password = "pw", security = "tls", sni = "h.example.com" } })).outbounds[1] +check("sb hysteria2 tls enabled", hy2.tls and hy2.tls.enabled == true and hy2.tls.server_name == "h.example.com") +local tuic = util.json_decode(singbox.generate({ { proto = "tuic", name = "U", server = "1.1.1.1", + port = 443, uuid = "u", password = "pw", security = "tls" } })).outbounds[1] +check("sb tuic tls enabled", tuic.tls and tuic.tls.enabled == true) + +-- 往返:本模块输出的 tls.enabled 必须能被 sing-box 解析器读回为 security=tls +local rt_sb = util.json_decode(singbox.generate({ { proto = "vmess", name = "RT", server = "1.1.1.1", + port = 443, uuid = "u", security = "tls", sni = "rt.example.com" } })) +local rt_node = sbjson.parse_singbox_json(util.json_encode(rt_sb))[1] +check("sb tls round-trip keeps security", rt_node and rt_node.security == "tls") +check("sb tls round-trip keeps sni", rt_node and rt_node.sni == "rt.example.com") -- 节点名与保留 tag 重名时不得冲突 local clash_name = singbox.generate({ { proto = "vmess", name = "direct", server = "1.1.1.1", port = 443, uuid = "u" } }) diff --git a/luci-app-substore/tests/parser_clash_yaml_test.lua b/luci-app-substore/tests/parser_clash_yaml_test.lua index ace4d4c60..1e67f82a6 100644 --- a/luci-app-substore/tests/parser_clash_yaml_test.lua +++ b/luci-app-substore/tests/parser_clash_yaml_test.lua @@ -222,5 +222,81 @@ if fnodes and #fnodes >= 2 then end -- ---------- 结果 ---------- +-- H6:未知 Clash 类型必须丢弃。透传出去会在输出端变成 sing-box 的 type: "snell"、 +-- Xray 的 protocol: "snell" 这类非法取值,客户端会拒绝加载整份配置; +-- 兜底成 vmess 则是凭空造出一个字段全错的假节点,比丢弃更糟。 +local unknown = parser.parse([[ +proxies: + - name: SN + type: snell + server: 1.1.1.1 + port: 443 + psk: secret + - name: OK + type: vmess + server: 2.2.2.2 + port: 443 + uuid: u +]]) +check("unknown clash type dropped", #unknown == 1) +check("known node survives", unknown[1] ~= nil and unknown[1].proto == "vmess") +check("unknown proto not leaked", unknown[1] ~= nil and unknown[1].proto ~= "snell") + +-- 缺失 type 同样丢弃(不再兜底成 vmess) +check("missing type dropped", #parser.parse([[ +proxies: + - name: X + server: 1.1.1.1 + port: 443 +]]) == 0) + +-- H4a:YAML 流式风格(键未加引号)是合法 YAML 但不是合法 JSON, +-- 原先 json_decode 失败后整项被静默丢弃 +local flow = parser.parse([[ +proxies: + - {name: F, type: vmess, server: 1.1.1.1, port: 443, uuid: u} +]]) +check("flow style node count", #flow == 1) +check("flow style proto", flow[1] ~= nil and flow[1].proto == "vmess") +check("flow style server", flow[1] ~= nil and flow[1].server == "1.1.1.1") +check("flow style port is number", flow[1] ~= nil and flow[1].port == 443) + +-- 流式风格的数组值仍要拆成 table +local flow_arr = parser.parse([[ +proxies: + - {name: FA, type: vmess, server: 1.1.1.1, port: 443, uuid: u, alpn: [h2, http/1.1]} +]]) +check("flow style array value", flow_arr[1] ~= nil and type(flow_arr[1].alpn) == "table") + +-- 键带引号的流式写法仍走 JSON 分支 +check("json flow style still works", #parser.parse([[ +proxies: + - {"name":"J","type":"vmess","server":"1.1.1.1","port":443,"uuid":"u"} +]]) == 1) + +-- H4b:行尾注释不得被当成值(`proxies: # 说明` 曾让 proxies 变成字符串) +local commented = parser.parse([[ +proxies: # 我的节点 + - name: C + type: vmess + server: 1.1.1.1 + port: 443 + uuid: u +]]) +check("proxies with trailing comment", #commented == 1) +check("comment not used as value", commented[1] ~= nil and commented[1].server == "1.1.1.1") + +-- 列表项的行尾注释同样要去掉 +check("list item trailing comment", #parser.parse([[ +proxies: + - {name: T, type: vmess, server: 1.1.1.1, port: 443, uuid: u} # 行尾注释 +]]) == 1) + +-- # 前无空白、或位于引号内时都不是注释,必须原样保留 +local hash_plain = parser.parse("proxies:\n - name: A\n type: ss\n server: 1.1.1.1\n port: 443\n cipher: aes-128-gcm\n password: p#ss\n") +check("hash without space kept", hash_plain[1] ~= nil and hash_plain[1].password == "p#ss") +local hash_quoted = parser.parse('proxies:\n - name: A\n type: ss\n server: 1.1.1.1\n port: 443\n cipher: aes-128-gcm\n password: "a # b"\n') +check("hash inside quotes kept", hash_quoted[1] ~= nil and hash_quoted[1].password == "a # b") + print(string.format("\n%d passed, %d failed", passed, failed)) os.exit(failed == 0 and 0 or 1) diff --git a/luci-app-substore/tests/protocol_coverage_test.lua b/luci-app-substore/tests/protocol_coverage_test.lua new file mode 100644 index 000000000..423e8567f --- /dev/null +++ b/luci-app-substore/tests/protocol_coverage_test.lua @@ -0,0 +1,332 @@ +-- protocol_coverage_test.lua — 协议覆盖一致性回归测试(2.6.0) +-- 覆盖本轮修复: +-- 1. hysteria(v1) / socks 的 URI 文本导入(此前只出不进,导出→导入回环丢节点) +-- 2. 简易 YAML 兜底解析不再把未知协议兜底成 vmess(静默数据损坏) +-- 3. socks5 -> socks 规范化,使节点页筛选 / 规则 proto_filter 能命中 +-- 4. clashmeta hysteria(v1) 用 sni 而非 servername;不写 v1 非法的 obfs-password +-- 5. clashmeta socks5 不再重复输出 password;http 补 username +-- 6. singbox hysteria(v1) 用 auth_str(不是 password)、obfs 为字符串 +-- 7. singbox / surge 的 socks、http 凭据不再丢 +-- 8. core.merge_form_node 能清空 username +-- 用法:lua5.1 tests/protocol_coverage_test.lua + +package.path = "./root/usr/share/?.lua;" .. package.path + +local parser = require("substore.parser") +local output = require("substore.output") +local output_uri = require("substore.output_uri") +local node = require("substore.node") +local core = require("substore.core") +local util = require("substore.util") + +local passed, failed = 0, 0 + +local function check(name, cond) + if cond then + passed = passed + 1 + print("PASS " .. name) + else + failed = failed + 1 + print("FAIL " .. name) + end +end + +-- ============================================================ +-- 1. URI 文本导入:hysteria(v1) +-- ============================================================ +local hy = parser.parse_uri("hysteria://pw@1.2.3.4:443/?sni=a.com&insecure=1&obfs=xxx#HY") +check("hysteria URI 可解析", hy ~= nil) +check("hysteria proto", hy and hy.proto == "hysteria") +check("hysteria server", hy and hy.server == "1.2.3.4") +check("hysteria port", hy and tonumber(hy.port) == 443) +check("hysteria password", hy and hy.password == "pw") +check("hysteria sni", hy and hy.sni == "a.com") +check("hysteria obfs", hy and hy.obfs == "xxx") +-- hysteria 系列在 mihomo / sing-box 里都是 TLS-only +check("hysteria security=tls", hy and hy.security == "tls") +-- obfs-password 是 hysteria2(salamander) 专属,v1 不应有 +check("hysteria 无 obfs-password", hy and hy["obfs-password"] == nil) +check("hysteria insecure 透传", hy and hy.insecure == "1") + +-- 不带查询参数的极简链接也要能解析 +local hy_min = parser.parse_uri("hysteria://secret@9.9.9.9:8443#MIN") +check("hysteria 无参数可解析", hy_min ~= nil and hy_min.password == "secret") + +-- 无法识别的查询参数忽略而不是报错(第三方链接常带 upmbps/downmbps 等) +local hy_extra = parser.parse_uri("hysteria://pw@1.2.3.4:443/?upmbps=100&downmbps=200&peer=x#E") +check("hysteria 未知参数忽略", hy_extra ~= nil and hy_extra.server == "1.2.3.4") + +-- ============================================================ +-- 2. URI 文本导入:socks / socks5 +-- ============================================================ +local sk = parser.parse_uri("socks5://user:pass@5.6.7.8:1080#SK") +check("socks5 URI 可解析", sk ~= nil) +-- socks5 与 socks 是同一协议,统一归一为规范名 socks +check("socks5 归一为 socks", sk and sk.proto == "socks") +check("socks server", sk and sk.server == "5.6.7.8") +check("socks port", sk and tonumber(sk.port) == 1080) +check("socks username", sk and sk.username == "user") +check("socks password", sk and sk.password == "pass") + +local sk2 = parser.parse_uri("socks://5.6.7.8:1080#SK2") +check("socks:// 同义可解析", sk2 ~= nil and sk2.proto == "socks") +check("无认证 socks 无 username", sk2 and sk2.username == nil) +check("无认证 socks 无 password", sk2 and sk2.password == nil) + +-- 密码含未编码的 @:必须取最后一个 @ 作分界(按第一个切会静默解析出错误密码) +local sk3 = parser.parse_uri("socks5://u:p@ss@5.6.7.8:1080#S3") +check("socks 密码含 @ 正确切分", sk3 ~= nil and sk3.username == "u" + and sk3.password == "p@ss" and sk3.server == "5.6.7.8") + +-- 第三方链接可能带 ? 尾巴,不能污染 host:port +local sk4 = parser.parse_uri("socks5://5.6.7.8:1080/?foo=bar#S4") +check("socks 忽略查询尾巴", sk4 ~= nil and sk4.server == "5.6.7.8" and tonumber(sk4.port) == 1080) + +-- ============================================================ +-- 3. 导出 → 导入回环(修复前 hysteria / socks 只出不进) +-- ============================================================ +local rt_cases = { + { "hysteria", "hysteria://pw@1.2.3.4:443/?sni=a.com&insecure=1&obfs=xxx#HY" }, + { "hysteria2", "hysteria2://pw@1.2.3.4:443/?sni=a.com&obfs=salamander&obfs-password=op#H2" }, + { "socks5", "socks5://user:pass@5.6.7.8:1080#SK" }, + { "socks", "socks://5.6.7.8:1080#SK2" }, + { "tuic", "tuic://uuid-x:pw@1.2.3.4:443?sni=a.com#T" }, + { "vmess", "vmess://" .. util.base64_encode(util.json_encode({ + v = "2", ps = "V", add = "1.2.3.4", port = "443", id = "u-1", aid = "0", net = "tcp", tls = "tls", + })) }, +} +for _, c in ipairs(rt_cases) do + local n = parser.parse_uri(c[2]) + check("回环 " .. c[1] .. " 首次解析", n ~= nil) + if n then + local back = output_uri.to_share_uri(n) + check("回环 " .. c[1] .. " 可再导出", back ~= nil) + local n2 = back and parser.parse_uri(back) + check("回环 " .. c[1] .. " 再导入成功", n2 ~= nil) + check("回环 " .. c[1] .. " proto 不变", n2 and n2.proto == n.proto) + check("回环 " .. c[1] .. " server 不变", n2 and n2.server == n.server) + check("回环 " .. c[1] .. " port 不变", n2 and tonumber(n2.port) == tonumber(n.port)) + end +end + +-- ============================================================ +-- 4. 订阅文本中混有 hysteria / socks 行不再整行丢弃 +-- ============================================================ +local mixed = table.concat({ + "hysteria://pw@1.1.1.1:443#A", + "socks5://u:p@2.2.2.2:1080#B", + "vmess://" .. util.base64_encode(util.json_encode({ + v = "2", ps = "C", add = "3.3.3.3", port = "443", id = "u-2", + })), +}, "\n") +local mixed_res = parser.parse(mixed) +check("混合 URI 文本解析出 3 个节点", mixed_res and mixed_res.nodes and #mixed_res.nodes == 3) +if mixed_res and mixed_res.nodes then + local protos = {} + for _, n in ipairs(mixed_res.nodes) do protos[n.proto] = true end + check("混合文本含 hysteria", protos.hysteria == true) + check("混合文本含 socks", protos.socks == true) + check("混合文本含 vmess", protos.vmess == true) +end + +-- ============================================================ +-- 5. 简易 YAML 兜底解析:未知协议不得兜底成 vmess +-- ============================================================ +local fb = parser.parse_yaml_content and parser.parse_yaml_content or nil +-- 走公开入口,确保兜底路径可达 +local yaml_outbounds = [[ +outbounds: + - type: hysteria2 + server: 1.1.1.1 + server_port: 443 + password: p1 + - type: hysteria + server: 1.1.1.2 + server_port: 443 + auth_str: p2 + - type: tuic + server: 1.1.1.3 + server_port: 443 + uuid: u3 + - type: wireguard + server: 1.1.1.4 + server_port: 51820 + - type: socks + server: 1.1.1.5 + server_port: 1080 +]] +local yres = parser.parse_yaml(yaml_outbounds) +if yres and #yres >0 then + local protos = {} + for _, n in ipairs(yres) do protos[n.proto] = (protos[n.proto] or 0) + 1 end + check("兜底解析 hysteria2 不被兜底成 vmess", protos.hysteria2 == 1) + check("兜底解析 hysteria 不被兜底成 vmess", protos.hysteria == 1) + check("兜底解析 tuic 不被兜底成 vmess", protos.tuic == 1) + check("兜底解析 wireguard 不被兜底成 vmess", protos.wireguard == 1) + check("兜底解析 socks 规范化", protos.socks == 1) + check("兜底解析无 vmess 假节点", protos.vmess == nil) +else + check("兜底解析 outbounds YAML", false) +end + +-- ============================================================ +-- 5b. sing-box YAML outbounds 的字段名别名(server_port / tag / auth_str / server_name / insecure) +-- 修复前:段名 `outbounds:` 被识别,但只读 Clash 的 port / name, +-- 所有 sing-box YAML 出站都卡在 `not port` 上被静默丢弃(解析出 0 个节点)。 +-- ============================================================ +local sb_yaml = [[ +outbounds: + - type: hysteria2 + tag: HY2 + server: 1.1.1.1 + server_port: 443 + password: p1 + tls: + server_name: sni.example.com + insecure: true + - type: hysteria + tag: HY1 + server: 1.1.1.2 + server_port: 8443 + auth_str: p2 + - type: vmess + tag: VM + server: 1.1.1.3 + server_port: 443 + uuid: u-3 + security: aes-128-gcm +]] +local sb_res = parser.parse_yaml(sb_yaml) +check("sing-box YAML 出站不再被丢弃", sb_res and #sb_res == 3) +if sb_res and #sb_res == 3 then + check("sing-box YAML server_port 生效", tonumber(sb_res[1].port) == 443) + check("sing-box YAML tag 作为 name", sb_res[1].name == "HY2") + check("sing-box YAML tls.server_name -> sni", sb_res[1].sni == "sni.example.com") + check("sing-box YAML tls.insecure -> skip-cert-verify", sb_res[1]["skip-cert-verify"] == true) + check("sing-box YAML auth_str -> password", sb_res[2].password == "p2") + check("sing-box YAML hysteria 端口", tonumber(sb_res[2].port) == 8443) + -- sing-box 的 vmess.security 是加密方式,不是 TLS 层 + check("sing-box YAML vmess.security -> cipher", sb_res[3].cipher == "aes-128-gcm") + check("sing-box YAML vmess security 不当作 TLS 层", sb_res[3].security ~= "aes-128-gcm") +end + +-- insecure: false 不能被当成真值("false" 在 Lua 里是真值) +local sb_false = parser.parse_yaml([[ +outbounds: + - type: hysteria2 + server: 1.1.1.9 + server_port: 443 + password: p + tls: + insecure: false +]]) +check("sing-box YAML insecure:false 不置 skip-cert-verify", + sb_false and sb_false[1] and sb_false[1]["skip-cert-verify"] ~= true) + +-- ============================================================ +-- 6. socks5 -> socks 规范化后,筛选 / 规则过滤能命中 +-- ============================================================ +local clash_socks = [[ +proxies: + - name: SK + type: socks5 + server: 1.1.1.1 + port: 1080 + username: u + password: p +]] +local cns = parser.parse_yaml(clash_socks) +check("clash socks5 导入成功", cns and #cns == 1) +check("clash socks5 归一为 socks", cns and cns[1] and cns[1].proto == "socks") +check("node.filter proto=socks 命中", #node.filter(cns, { proto = "socks" }) == 1) +check("apply_rules proto_filter=socks 命中", #node.apply_rules(cns, { proto_filter = "socks" }) == 1) + +-- 直接对未归一节点调用 normalize 也应归一(所有真实节点都会经过 normalize) +local raw_norm = node.normalize({ proto = "socks5", server = "1.1.1.1", port = 1080 }) +check("node.normalize 归一 socks5", raw_norm.proto == "socks") + +-- ============================================================ +-- 7. clashmeta 输出:hysteria(v1) 用 sni,不写 servername / obfs-password +-- ============================================================ +local hy_node = { proto = "hysteria", name = "HY", server = "1.1.1.1", port = 443, + password = "pw", obfs = "obs", sni = "s.com" } +local cm_hy = output.generate({ hy_node }, "clashmeta") +check("clashmeta hysteria 有 sni", cm_hy and cm_hy:find(" sni: s.com", 1, true) ~= nil) +check("clashmeta hysteria 无 servername", cm_hy and cm_hy:find("servername", 1, true) == nil) +check("clashmeta hysteria 无 obfs-password", cm_hy and cm_hy:find("obfs-password", 1, true) == nil) +check("clashmeta hysteria 有 obfs", cm_hy and cm_hy:find(" obfs: obs", 1, true) ~= nil) + +-- hysteria2 仍然用 sni + obfs-password +local h2_node = { proto = "hysteria2", name = "H2", server = "1.1.1.2", port = 443, + password = "p", obfs = "salamander", ["obfs-password"] = "op", sni = "s2.com" } +local cm_h2 = output.generate({ h2_node }, "clashmeta") +check("clashmeta hysteria2 有 sni", cm_h2 and cm_h2:find(" sni: s2.com", 1, true) ~= nil) +check("clashmeta hysteria2 有 obfs-password", cm_h2 and cm_h2:find(" obfs-password: op", 1, true) ~= nil) + +-- vmess 仍然用 servername(不能被 hysteria 的改动误伤) +local vm_node = { proto = "vmess", name = "V", server = "1.1.1.3", port = 443, + uuid = "u", sni = "s3.com", security = "tls" } +local cm_vm = output.generate({ vm_node }, "clashmeta") +check("clashmeta vmess 仍用 servername", cm_vm and cm_vm:find(" servername: s3.com", 1, true) ~= nil) + +-- ============================================================ +-- 8. clashmeta 输出:socks password 不重复;http 补 username +-- ============================================================ +local sk_node = { proto = "socks", name = "SK", server = "1.1.1.4", port = 1080, + username = "u", password = "p" } +local cm_sk = output.generate({ sk_node }, "clashmeta") +local _, pw_cnt = cm_sk:gsub(" password:", "") +check("clashmeta socks password 只出现一次", pw_cnt == 1) +check("clashmeta socks username 输出", cm_sk:find(" username: u", 1, true) ~= nil) + +local http_node = { proto = "http", name = "HT", server = "1.1.1.5", port = 8080, + username = "hu", password = "hp" } +local cm_ht = output.generate({ http_node }, "clashmeta") +check("clashmeta http username 输出", cm_ht and cm_ht:find(" username: hu", 1, true) ~= nil) +local _, htpw = cm_ht:gsub(" password:", "") +check("clashmeta http password 只出现一次", htpw == 1) + +-- ============================================================ +-- 9. singbox 输出:hysteria(v1) 用 auth_str、obfs 为字符串 +-- ============================================================ +local sb_hy = util.json_decode(output.generate({ hy_node }, "singbox")) +check("singbox hysteria auth_str", sb_hy and sb_hy.outbounds[1] and sb_hy.outbounds[1].auth_str == "pw") +check("singbox hysteria 无 password 键", sb_hy and sb_hy.outbounds[1] and sb_hy.outbounds[1].password == nil) +check("singbox hysteria obfs 为字符串", sb_hy and sb_hy.outbounds[1] and sb_hy.outbounds[1].obfs == "obs") + +local sb_h2 = util.json_decode(output.generate({ h2_node }, "singbox")) +check("singbox hysteria2 仍用 password", sb_h2 and sb_h2.outbounds[1] and sb_h2.outbounds[1].password == "p") +check("singbox hysteria2 obfs 为对象", sb_h2 and sb_h2.outbounds[1] and type(sb_h2.outbounds[1].obfs) == "table" + and sb_h2.outbounds[1].obfs.password == "op") + +-- singbox socks / http 凭据 +local sb_sk = util.json_decode(output.generate({ sk_node }, "singbox")) +check("singbox socks username", sb_sk and sb_sk.outbounds[1] and sb_sk.outbounds[1].username == "u") +check("singbox socks password", sb_sk and sb_sk.outbounds[1] and sb_sk.outbounds[1].password == "p") +local sb_ht = util.json_decode(output.generate({ http_node }, "singbox")) +check("singbox http username", sb_ht and sb_ht.outbounds[1] and sb_ht.outbounds[1].username == "hu") +check("singbox http password", sb_ht and sb_ht.outbounds[1] and sb_ht.outbounds[1].password == "hp") + +-- ============================================================ +-- 10. Surge 家族:socks / http 凭据 +-- ============================================================ +local sg_sk = output.generate({ sk_node }, "surge") +check("surge socks username", sg_sk and sg_sk:find("username=u", 1, true) ~= nil) +check("surge socks password", sg_sk and sg_sk:find("password=p", 1, true) ~= nil) +local sg_ht = output.generate({ http_node }, "surge") +check("surge http username", sg_ht and sg_ht:find("username=hu", 1, true) ~= nil) +check("surge http password", sg_ht and sg_ht:find("password=hp", 1, true) ~= nil) + +-- ============================================================ +-- 11. core.merge_form_node 能清空 username(FORM_KEYS 必须含 username) +-- ============================================================ +local old_node = { proto = "socks", name = "N", server = "1.1.1.1", port = 1080, + username = "olduser", password = "oldpass" } +local merged = core.merge_form_node(old_node, { proto = "socks", name = "N", server = "1.1.1.1", port = 1080, + password = "newpass" }) +check("merge_form_node 清空 username", merged and merged.username == nil) +check("merge_form_node 更新 password", merged and merged.password == "newpass") + +-- ---------- 结果 ---------- +print(string.format("\n%d passed, %d failed", passed, failed)) +os.exit(failed == 0 and 0 or 1) diff --git a/luci-app-substore/tests/run_tests.lua b/luci-app-substore/tests/run_tests.lua index 59617080c..e39ad9ed9 100644 --- a/luci-app-substore/tests/run_tests.lua +++ b/luci-app-substore/tests/run_tests.lua @@ -120,6 +120,30 @@ check("detect BOM prefix", parser.detect(bom_sub) == "base64") local bom_res = parser.parse(bom_sub) check("parse BOM count", bom_res and #bom_res.nodes == 1) +-- H5:base64 里包着 YAML / JSON(机场把整份配置 base64 后直接下发) +-- 原先一律按 URI 列表解析,这类订阅会得到 0 个节点且不报错 +local b64_yaml = parser.parse(util.base64_encode([[ +proxies: + - name: BY + type: vmess + server: 6.6.6.6 + port: 443 + uuid: u +]])) +check("base64 yaml node count", b64_yaml and #b64_yaml.nodes == 1) +check("base64 yaml node server", b64_yaml and b64_yaml.nodes[1] and b64_yaml.nodes[1].server == "6.6.6.6") +check("base64 yaml keeps outer format", b64_yaml and b64_yaml.format == "base64") + +local b64_json = parser.parse(util.base64_encode( + '{"outbounds":[{"type":"vmess","tag":"BJ","server":"7.7.7.7","server_port":443,"uuid":"u"}]}')) +check("base64 json node count", b64_json and #b64_json.nodes == 1) +check("base64 json node server", b64_json and b64_json.nodes[1] and b64_json.nodes[1].server == "7.7.7.7") +check("base64 json keeps outer format", b64_json and b64_json.format == "base64") + +-- base64 套 base64:不得无限递归 +local nested = parser.parse(util.base64_encode(util.base64_encode(plain))) +check("nested base64 does not hang", nested ~= nil) + -- ---------- 结果 ---------- print(string.format("\n%d passed, %d failed", passed, failed)) os.exit(failed == 0 and 0 or 1) \ No newline at end of file diff --git a/luci-app-substore/tests/wireguard_conf_test.lua b/luci-app-substore/tests/wireguard_conf_test.lua index bc94878a5..39a934618 100644 --- a/luci-app-substore/tests/wireguard_conf_test.lua +++ b/luci-app-substore/tests/wireguard_conf_test.lua @@ -482,5 +482,22 @@ do end -- ---------- 结果 ---------- +-- H7:.conf 的注释行同样要压成单行。节点名来自订阅(不可信输入),含换行时 +-- 会从注释里注入出真正的配置行,伪造出一段用户没写过的隧道配置。 +local wgconf_out = require("substore.output_wireguard_conf") +local wg_evil = wgconf_out.generate({ { proto = "wireguard", name = "x\n[Interface]\nPrivateKey = injected", + server = "1.2.3.4", port = 51820, ["private-key"] = "PRIV", ["public-key"] = "PUB" } }) +-- 注入文本只能留在注释行里:既不能出现真正的 [Interface] 段头,也不能出现 +-- 以 "PrivateKey = injected" 开头的新行 +check("wgconf comment not injected", wg_evil:find("\n[Interface]\nPrivateKey = injected", 1, true) == nil) +check("wgconf injected text stays in comment", wg_evil:find("\nPrivateKey = injected", 1, true) == nil) +local real_iface = 0 +for l in wg_evil:gmatch("[^\n]+") do + if l == "[Interface]" then real_iface = real_iface + 1 end +end +check("wgconf single real Interface section", real_iface == 1) +check("wgconf real private key kept", wg_evil:find("\nPrivateKey = PRIV", 1, true) ~= nil) +check("wgconf comment is one line", wg_evil:match("^# [^\n]*\n") ~= nil) + print(string.format("\n%d passed, %d failed", passed, failed)) os.exit(failed == 0 and 0 or 1) diff --git a/luci-app-trafficctl/Makefile b/luci-app-trafficctl/Makefile index 14ea51da9..e8920dd5f 100644 --- a/luci-app-trafficctl/Makefile +++ b/luci-app-trafficctl/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-trafficctl -PKG_VERSION:=1.18.1 -PKG_RELEASE:=4 +PKG_VERSION:=1.18.2 +PKG_RELEASE:=5 PKG_LICENSE:=Apache-2.0 PKG_MAINTAINER:=Denis Iusupov diff --git a/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js b/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js index c3c29b9d2..5195568c8 100644 --- a/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js +++ b/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js @@ -3200,7 +3200,13 @@ return view.extend({ inetBtn.disabled = true; var action = inetBtn._action; var fn = action === 'block' ? callBlock : callUnblock; - fn(ip, '').then(function() { + fn(ip, '').then(function(res) { + // A block without a known MAC covers IPv4 only, and the backend + // says so in msg. Swallowing it here would put the UI back to + // reporting a block that does not block (issue #67). + if (res && res.ipv6 === false) { + setStatus(statusDiv, 'error', (res && res.msg) || '?'); + } runQuery(); }).catch(function(e) { setStatus(statusDiv, 'error', e.message); diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-block.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-block.sh index 7f1168854..71d1d2300 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-block.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-block.sh @@ -35,15 +35,33 @@ if tctl_is_blocked "$IP"; then exit 0 fi +TCTL_BLOCK_IPV6=0 if tctl_block_add "$IP" "$COMMENT"; then conntrack -D -s "$IP" >/dev/null 2>&1 conntrack -D -d "$IP" >/dev/null 2>&1 + # The v4 flush above leaves every established IPv6 flow running, and with + # flow offload those are never re-evaluated against the new rule — the + # device would stay online over v6 indefinitely while the UI reads blocked. + MAC=$(tctl_target_mac "$IP" 2>/dev/null) && tctl_conntrack_flush_v6 "$MAC" + tctl_persist_enabled && tctl_persist_save "block" "$IP" "$LABEL" tctl_log "block" "$IP" "$LABEL" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" - if [ "$SELF_BLOCK" = "true" ]; then - echo "{\"ok\":true,\"msg\":\"internet blocked for $IP (your device — LuCI access preserved)\"}" + + # Say which families are actually covered. Reporting plain success while + # half the traffic walks past the rule is the bug this fixes, so the + # no-MAC case is stated rather than left to be discovered (same reasoning + # as the half-applied-limit messages in trafficctl-ratelimit.sh). + if [ "$TCTL_BLOCK_IPV6" = "1" ]; then + NOTE="" + elif tctl_ip_is_nexthop "$IP"; then + NOTE=" — IPv4 only: $IP is a routed next hop, and a MAC-keyed IPv6 rule would also block everything behind it" else - echo "{\"ok\":true,\"msg\":\"internet blocked for $IP\"}" + NOTE=" — IPv4 only: no MAC known for $IP (no DHCP lease, no neighbour entry), so IPv6 is not covered" + fi + if [ "$SELF_BLOCK" = "true" ]; then + echo "{\"ok\":true,\"ipv6\":$([ "$TCTL_BLOCK_IPV6" = "1" ] && echo true || echo false),\"msg\":\"internet blocked for $IP (your device — LuCI access preserved)$NOTE\"}" + else + echo "{\"ok\":true,\"ipv6\":$([ "$TCTL_BLOCK_IPV6" = "1" ] && echo true || echo false),\"msg\":\"internet blocked for $IP$NOTE\"}" fi else echo "{\"ok\":false,\"msg\":\"failed to block $IP\"}" diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh index c0efde9f4..c8acbafca 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh @@ -127,9 +127,13 @@ BLOCK_BYTES=0 if tctl_is_blocked "$IP"; then BLOCKED=true if [ "$TCTL_FW" = "nft" ]; then - block_line=$(nft list chain inet fw4 forward 2>/dev/null | grep "ip saddr $IP.*drop") - BLOCK_PACKETS=$(echo "$block_line" | grep -oE 'packets [0-9]+' | awk '{print $2}') - BLOCK_BYTES=$(echo "$block_line" | grep -oE 'bytes [0-9]+' | awk '{print $2}') + # A block is two rules — the v4 one keyed on the address and the v6 one + # keyed on the MAC (see tctl_block_add) — so the counters are summed + # across both. The v6 rule carries no address, only its "_mac" comment. + block_line=$(nft list chain inet fw4 forward 2>/dev/null \ + | grep -e "ip saddr $IP.*drop" -e "comment \"$(tctl_block_comment "$IP")_mac\"") + BLOCK_PACKETS=$(echo "$block_line" | grep -oE 'packets [0-9]+' | awk '{ t += $2 } END { printf "%.0f", t }') + BLOCK_BYTES=$(echo "$block_line" | grep -oE 'bytes [0-9]+' | awk '{ t += $2 } END { printf "%.0f", t }') else block_line=$(iptables -L FORWARD -nvx 2>/dev/null | grep "DROP" | grep "$IP") BLOCK_PACKETS=$(echo "$block_line" | awk '{print $1}') diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh index 599525044..7dc523afc 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh @@ -10,6 +10,102 @@ else TCTL_FW="iptables" fi +# ── MAC-keyed matching (address-family independent) ──────────────────────── +# +# Everything in this package is keyed on the IPv4 address a DHCP lease gives a +# device, and every enforcement rule matches "ip saddr"/"ip daddr" — so IPv6 +# walks past all of it (issue #67: 9.96 Mbit/s over v4 against a 10 Mbit/s cap, +# 151 Mbit/s over v6 to the same endpoint). +# +# The fix is NOT "add ip6 saddr next to ip saddr": with SLAAC and privacy +# extensions a client holds several v6 addresses at once and rotates them on a +# timer, so a rule written against one stops matching without warning — the +# same silent bypass, reached more slowly. The MAC does not rotate, and on the +# hooks used here the client's own frame is still intact, so it is what the v6 +# rules are keyed on. +# +# Only the directions where that holds are covered; see tctl_block_add and +# tctl_ratelimit_add for which, and README/COMPATIBILITY for what is not. + +# Named by absolute path, as it must be on the router; the tests sed this line +# into their scratch directory rather than have the shipped script carry a +# test-only override (same approach as the ledger and shapes paths below). +TCTL_LEASES_FILE="/tmp/dhcp.leases" + +# The MAC behind an IPv4 address: DHCP lease first, neighbour table second. +# Fails (non-zero, no output) when neither knows it — a routed/downstream +# client has no lease and no neighbour entry here, and there is nothing to key +# a rule on. Callers must report that rather than assume coverage. +# +# The result is validated strictly, not merely trimmed: it is interpolated +# into an nft rule string, so anything but six hex pairs is refused. +tctl_lookup_mac() { + local addr="$1" mac + tctl_validate_ip "$addr" || return 1 + mac=$(awk -v ip="$addr" '$3 == ip { print $2; exit }' "$TCTL_LEASES_FILE" 2>/dev/null) + [ -z "$mac" ] && mac=$(ip neigh show 2>/dev/null | awk -v ip="$addr" ' + $1 == ip { for (i = 1; i < NF; i++) if ($i == "lladdr") { print $(i+1); exit } }') + mac=$(printf '%s' "$mac" | tr 'A-F' 'a-f') + case "$mac" in + [0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]) ;; + *) return 1 ;; + esac + printf '%s\n' "$mac" +} + +# True when this address is the next hop of a route, i.e. a router rather than +# an end device. Its MAC is the source of every packet it FORWARDS, so a +# MAC-keyed rule aimed at it would also hit every client behind it — blocking +# one device would black-hole a whole subnet. Those addresses are excluded and +# the caller says so out loud. +tctl_ip_is_nexthop() { + local addr="$1" + [ -n "$addr" ] || return 1 + ip route show 2>/dev/null | awk -v n="$addr" ' + { for (i = 1; i < NF; i++) if ($i == "via" && $(i+1) == n) { hit = 1; exit } } + END { exit hit ? 0 : 1 }' +} + +# The MAC to key a target's IPv6 rules on, or failure. A CIDR target has no +# single MAC; a next hop's MAC is not its own traffic. +tctl_target_mac() { + local t="$1" + case "$t" in + */32) t=${t%/32} ;; + */*) return 1 ;; + esac + tctl_ip_is_nexthop "$t" && return 1 + tctl_lookup_mac "$t" +} + +# Flush a device's live IPv6 flows. +# +# "conntrack -D -s " only touches the IPv4 table, so without this an +# established v6 flow survives a block that was just installed — and with flow +# offload it is never re-evaluated by the forward chain again, so it survives +# indefinitely. That is the same "a block that does not block" failure in a new +# place, on the offload-enabled hardware most likely to hit it. +# +# Addresses come from a one-shot neighbour snapshot. Reading them is sound even +# though a RULE written against them would not be: the snapshot cannot go stale +# between here and the next statement, whereas a rule has to stay correct for +# as long as the block lasts. +tctl_conntrack_flush_v6() { + local mac="$1" addr + [ -n "$mac" ] || return 0 + command -v conntrack >/dev/null 2>&1 || return 0 + ip -6 neigh show 2>/dev/null | awk -v m="$mac" ' + { for (i = 1; i < NF; i++) if ($i == "lladdr" && tolower($(i+1)) == m) { print $1; break } } + ' | while read -r addr; do + case "$addr" in + ''|*[!0-9a-fA-F:]*) continue ;; + esac + conntrack -D -f ipv6 -s "$addr" >/dev/null 2>&1 + conntrack -D -f ipv6 -d "$addr" >/dev/null 2>&1 + done + return 0 +} + # ── Rate Limiting (policer) ──────────────────────────────────────────────── # Rate limits are symmetric: the same ceiling is policed in both directions. @@ -27,7 +123,7 @@ tctl_ratelimit_add() { local rate_kbyte=$((rate_kbit / 8)) [ "$rate_kbyte" -lt 1 ] && rate_kbyte=1 - local slug dl_expr ul_expr + local slug dl_expr ul_expr ul6_expr mac slug=$(tctl_target_slug "$ip") if [ "$mode" = "each" ]; then dl_expr="ip daddr $ip meter tctl_d_$slug { ip daddr limit rate over ${rate_kbyte} kbytes/second }" @@ -37,6 +133,31 @@ tctl_ratelimit_add() { ul_expr="ip saddr $ip limit rate over ${rate_kbyte} kbytes/second" fi + # Upload over IPv6, keyed on the MAC. This direction and only this one: + # at LAN ingress the frame is still the client's own, so "ether saddr" + # identifies it whatever address family it is using. Download over IPv6 is + # policed at LAN egress, where the destination MAC is the next hop's — it + # needs the device's current v6 address set and is deliberately not + # attempted here. + # + # Scoped to IPv6 on purpose: IPv4 keeps being policed by exactly the rule it + # always was, so nothing about existing behaviour depends on whether this + # lookup succeeds — and an unscoped ether rule would police a dual-stack + # client's v4 traffic TWICE, halving the ceiling it was given. Its own + # bucket, too: sharing one would make the v4 and v6 halves cannibalise each + # other's allowance, which is not what "10 Mbit/s" has ever meant here. + # + # The scope is "meta protocol ip6", NOT "meta nfproto ipv6" — these chains + # are in the NETDEV family, where nft rejects nfproto outright ("meta + # nfproto is only useful in the inet family", verified with nft --check + # against nftables 1.1.1 / kernel 6.6). nfproto is what tctl_block_add uses, + # because that rule lives in inet fw4. Same intent, different family, and + # the wrong one does not silently under-match — it fails to load. + ul6_expr="" + if mac=$(tctl_target_mac "$ip"); then + ul6_expr="meta protocol ip6 ether saddr $mac limit rate over ${rate_kbyte} kbytes/second" + fi + if [ "$TCTL_FW" = "nft" ]; then nft add table netdev tm_ratelimit 2>/dev/null @@ -79,7 +200,7 @@ tctl_ratelimit_add() { # One chain per ingress device: a device that refuses the hook then # only loses its own chain instead of taking the whole set with it. local dev chain - local ul_ok=0 + local ul_ok=0 ul6_ok=0 for dev in $(tctl_ingress_devices); do chain=$(tctl_ingress_chain "$dev") nft add chain netdev tm_ratelimit "$chain" \ @@ -87,10 +208,21 @@ tctl_ratelimit_add() { nft add rule netdev tm_ratelimit "$chain" \ "$ul_expr counter drop comment \"${comment}_ul\"" 2>/dev/null \ && ul_ok=1 + [ -n "$ul6_expr" ] || continue + nft add rule netdev tm_ratelimit "$chain" \ + "$ul6_expr counter drop comment \"${comment}_ul6\"" 2>/dev/null \ + && ul6_ok=1 done # shellcheck disable=SC2034 [ "$ul_ok" = "1" ] || TCTL_RL_UPLOAD_FAILED=1 + # Set for the caller to report: "limited" means v4 only unless this is 1. + # shellcheck disable=SC2034 + TCTL_RL_UPLOAD6_OK="$ul6_ok" else + # fw3/iptables stays IPv4-only. A half-built ip6tables path would be + # worse than a stated gap; see docs/COMPATIBILITY.md. + # shellcheck disable=SC2034 + TCTL_RL_UPLOAD6_OK=0 iptables -t mangle -A FORWARD -d "$ip" -m hashlimit \ --hashlimit-above "${rate_kbit}kbit/sec" --hashlimit-burst "${rate_kbit}kbit" \ --hashlimit-mode dstip --hashlimit-name "rl_${comment}" \ @@ -107,11 +239,18 @@ tctl_ratelimit_remove() { local chain h if [ "$TCTL_FW" = "nft" ]; then - # Scan the whole table once: rules for this IP live in dl (daddr) and - # in one ul_ chain per ingress device (saddr). + # Scan the whole table once: rules for this IP live in dl (daddr), in + # one ul_ chain per ingress device (saddr), and — for a host with + # a known MAC — a second, IPv6-scoped rule in each of those (_ul6). + # + # Each comment is matched in FULL, closing quote included. The suffixes + # are prefixes of one another ("_ul" of "_ul6"), and every comment ends + # in an address slug, so a substring match would have a limit on + # 192.168.1.1 delete 192.168.1.10's rules as well. nft -a list table netdev tm_ratelimit 2>/dev/null | awk -v cmt="$comment" ' /^[ \t]*chain [a-zA-Z0-9_]+ \{/ { chain = $2; next } - index($0, "\"" cmt "\"") || index($0, "\"" cmt "_ul\"") { + index($0, "\"" cmt "\"") || index($0, "\"" cmt "_ul\"") || + index($0, "\"" cmt "_ul6\"") { for (i = 1; i < NF; i++) if ($i == "handle") { print chain, $(i+1); break } }' | while read -r chain h; do @@ -133,12 +272,45 @@ tctl_ratelimit_list() { # ── Internet Blocking ────────────────────────────────────────────────────── +# A block is two rules: the address-keyed one for IPv4, and a MAC-keyed one +# scoped to IPv6. +# +# This is the row of issue #67 that matters most. A rate limit that under- +# delivers shows up in a speed test; a block that reports success while the +# device keeps full, unmetered IPv6 access is invisible until it matters — and +# "block internet" is what people reach for as a parental control. +# +# The MAC is resolved HERE rather than in trafficctl-block.sh because three +# callers reach this function: the block script, the Telegram bot, and the +# ifup-lan restore hook. Resolving it in the script would bring every persisted +# block back IPv4-only after each reboot. +# +# "meta nfproto ipv6" keeps the two rules disjoint: IPv4 is still dropped by +# precisely the rule it always was, so a failed MAC lookup costs the v6 half +# and nothing else. (nfproto is correct HERE, in the inet family; the limiter's +# netdev chains need "meta protocol ip6" instead — see tctl_ratelimit_add.) +# `insert`, not `add`, for the same reason the v4 rule uses it — fw4's forward +# chain accepts established/offloaded flows near the top, and a rule appended +# below that is dead. tctl_block_add() { - local ip="$1" comment="$2" + local ip="$1" comment="$2" mac rc if [ "$TCTL_FW" = "nft" ]; then nft insert rule inet fw4 forward "ip saddr $ip counter drop comment \"$comment\"" + rc=$? + # Whether the v6 half is live. Read by callers; see trafficctl-block.sh. + # shellcheck disable=SC2034 + TCTL_BLOCK_IPV6=0 + if mac=$(tctl_target_mac "$ip"); then + nft insert rule inet fw4 forward \ + "meta nfproto ipv6 ether saddr $mac counter drop comment \"${comment}_mac\"" \ + 2>/dev/null && TCTL_BLOCK_IPV6=1 + fi + return "$rc" else + # fw3/iptables stays IPv4-only; see docs/COMPATIBILITY.md. + # shellcheck disable=SC2034 + TCTL_BLOCK_IPV6=0 iptables -I FORWARD -s "$ip" -j DROP -m comment --comment "$comment" fi } @@ -149,8 +321,12 @@ tctl_block_remove() { if [ "$TCTL_FW" = "nft" ]; then # Match the quoted comment in full: comments end in the address, so a # substring match on 192.168.1.1 also deletes the rule for 192.168.1.10. + # The IPv6 half carries no address to match on at all, only its own + # "_mac" comment — which is why it is listed explicitly here rather + # than being caught by a looser pattern. for h in $(nft -a list chain inet fw4 forward 2>/dev/null \ - | awk -v cmt="$comment" 'index($0, "\"" cmt "\"") { + | awk -v cmt="$comment" 'index($0, "\"" cmt "\"") || + index($0, "\"" cmt "_mac\"") { for (i = 1; i < NF; i++) if ($i == "handle") { print $(i+1); break } }'); do @@ -162,9 +338,17 @@ tctl_block_remove() { } tctl_is_blocked() { - local ip="$1" + local ip="$1" dump comment if [ "$TCTL_FW" = "nft" ]; then - nft list chain inet fw4 forward 2>/dev/null | grep -q "ip saddr $ip .*drop" + dump=$(nft list chain inet fw4 forward 2>/dev/null) + # The v4 rule is still found by address, so blocks written by versions + # that derived the comment from the caller's label keep reading as + # blocked. + echo "$dump" | grep -q "ip saddr $ip .*drop" && return 0 + # The v6 rule names a MAC, not an address — its comment is the only + # handle on it, and it is matched in full for the reason above. + comment=$(tctl_block_comment "$ip") + echo "$dump" | grep -qF "comment \"${comment}_mac\"" else # The source renders as its own column, "ip" or "ip/32"; an unanchored # match would report 192.168.1.10's rule as belonging to 192.168.1.1. @@ -699,7 +883,7 @@ tctl_persist_remove() { # traffic: an entry is appended only for a MAC that is not already listed. TCTL_SEEN_FILE="/etc/trafficctl/seen_macs" TCTL_SEEN_MAX=1000 -TCTL_LEASES_FILE="/tmp/dhcp.leases" +# TCTL_LEASES_FILE is set once at the top of this file (overridable for tests). TCTL_SHAPES_FILE="/etc/trafficctl/shapes.json" tctl_seen_normalize() { diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-ratelimit.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-ratelimit.sh index 4bd4527d6..b20e1f330 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-ratelimit.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-ratelimit.sh @@ -59,8 +59,19 @@ else tctl_ratelimit_remove "$IP" "$COMMENT" 2>/dev/null TCTL_RL_DOWNLOAD_FAILED=0 TCTL_RL_UPLOAD_FAILED=0 + TCTL_RL_UPLOAD6_OK=0 tctl_ratelimit_add "$IP" "$RATE" "$COMMENT" "$MODE" + # IPv6 coverage is partial by construction and the operator has to know + # which part: upload is policed on the MAC, download is not policed at all + # over v6 (see tctl_ratelimit_add). Claiming "both directions" without + # this note is how issue #67 stayed invisible. + if [ "$TCTL_RL_UPLOAD6_OK" = "1" ]; then + V6NOTE=" [IPv6: upload only]" + else + V6NOTE=" [IPv4 only]" + fi + # A half-applied limit is a silent trap: report exactly which direction # is live rather than claiming success for both. if [ "$TCTL_RL_DOWNLOAD_FAILED" = "1" ] && [ "$TCTL_RL_UPLOAD_FAILED" = "1" ]; then @@ -70,10 +81,10 @@ else tctl_persist_enabled && tctl_persist_save "ratelimit" "$IP" "$RATE" tctl_log "ratelimit_set" "$IP" "${RATE}kbit" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" if [ "$TCTL_RL_DOWNLOAD_FAILED" = "1" ]; then - echo "{\"ok\":true,\"msg\":\"rate limit ${RATE} kbit/s applied to $IP UPLOAD ONLY — WAN device not resolvable\"}" + echo "{\"ok\":true,\"ipv6_upload\":$([ "$TCTL_RL_UPLOAD6_OK" = "1" ] && echo true || echo false),\"msg\":\"rate limit ${RATE} kbit/s applied to $IP UPLOAD ONLY — WAN device not resolvable$V6NOTE\"}" elif [ "$TCTL_RL_UPLOAD_FAILED" = "1" ]; then - echo "{\"ok\":true,\"msg\":\"rate limit ${RATE} kbit/s applied to $IP DOWNLOAD ONLY — no LAN ingress device\"}" + echo "{\"ok\":true,\"ipv6_upload\":false,\"msg\":\"rate limit ${RATE} kbit/s applied to $IP DOWNLOAD ONLY — no LAN ingress device [IPv4 only]\"}" else - echo "{\"ok\":true,\"msg\":\"rate limit ${RATE} kbit/s for $IP (both directions, $MODE)\"}" + echo "{\"ok\":true,\"ipv6_upload\":$([ "$TCTL_RL_UPLOAD6_OK" = "1" ] && echo true || echo false),\"msg\":\"rate limit ${RATE} kbit/s for $IP (both directions, $MODE)$V6NOTE\"}" fi fi diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh index 2d26e2d06..518cf064f 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh @@ -303,7 +303,12 @@ lookup_mac() { lookup_blocked() { local ip="$1" if [ "$TCTL_FW" = "nft" ]; then - echo "$FWD_DUMP" | grep -q "ip saddr $ip .*drop" && echo 1 || echo 0 + echo "$FWD_DUMP" | grep -q "ip saddr $ip .*drop" && { echo 1; return; } + # The IPv6 half of a block matches a MAC and carries no address, so it + # is found by its own full comment. Without this the table reports "not + # blocked" for a device whose v6 rule is the only one left standing. + echo "$FWD_DUMP" | grep -qF "comment \"$(tctl_block_comment "$ip")_mac\"" \ + && echo 1 || echo 0 else echo "$FWD_DUMP" | awk -v ip="$ip" ' $3 == "DROP" { @@ -320,7 +325,13 @@ lookup_blocked() { lookup_block_bytes() { local ip="$1" b if [ "$TCTL_FW" = "nft" ]; then - b=$(echo "$FWD_DUMP" | grep "ip saddr $ip " | grep -oE 'bytes [0-9]+' | awk '{print $2}' | head -1) + # Both halves of the block, summed: the v4 rule keyed on the address + # and the v6 rule keyed on the MAC. Counting only the first would make + # a dual-stack device's dropped bytes read low for the same reason the + # traffic used to escape entirely. + b=$(echo "$FWD_DUMP" | grep -e "ip saddr $ip " \ + -e "comment \"$(tctl_block_comment "$ip")_mac\"" \ + | grep -oE 'bytes [0-9]+' | awk '{ t += $2 } END { printf "%.0f", t }') else b=$(echo "$FWD_DUMP" | awk -v ip="$ip" ' $3 == "DROP" { diff --git a/luci-app-wwand/Makefile b/luci-app-wwand/Makefile index d0223a3e8..0e9320dbd 100644 --- a/luci-app-wwand/Makefile +++ b/luci-app-wwand/Makefile @@ -17,12 +17,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-wwand -PKG_VERSION:=1.6.8_p17 -PKG_RELEASE:=34 +PKG_VERSION:=1.6.8_p18 +PKG_RELEASE:=35 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/luci-app-wwand.git -PKG_SOURCE_VERSION:=376f2dc5c658f06f88cb3b917e65e9e7d58a6e85 +PKG_SOURCE_VERSION:=355e135f79b954c7fc01d6135a11d60adcaf04a7 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only diff --git a/luci-mod-dashboard/po/cs/dashboard.po b/luci-mod-dashboard/po/cs/dashboard.po index 682cb6342..79919fcbf 100644 --- a/luci-mod-dashboard/po/cs/dashboard.po +++ b/luci-mod-dashboard/po/cs/dashboard.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"PO-Revision-Date: 2026-03-08 17:32+0000\n" +"PO-Revision-Date: 2026-09-28 18:23+0000\n" "Last-Translator: Pavel Borecki \n" "Language-Team: Czech \n" @@ -10,39 +10,39 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 2026.10.dev0\n" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 msgid "%d clients" -msgstr "" +msgstr "%d klientů" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:124 msgid "%d core" msgid_plural "%d cores" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d jádro" +msgstr[1] "%d jádra" +msgstr[2] "%d jader" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d min ago" -msgstr "" +msgstr "před %d min" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:72 msgid "%d of %d SSIDs active" -msgstr "" +msgstr "%d z %d SSID identifikátorů aktivních" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d s ago" -msgstr "" +msgstr "před %d s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "15 min: %.2f" -msgstr "" +msgstr "15 min: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "5 min: %.2f" -msgstr "" +msgstr "5 min: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:322 msgid "Active" @@ -50,7 +50,7 @@ msgstr "Aktivní" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 msgid "Active leases" -msgstr "" +msgstr "Aktivní zápůjčky" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:295 msgid "Architecture" @@ -63,7 +63,7 @@ msgstr "BSSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:218 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:372 msgid "Band" -msgstr "" +msgstr "Frekvenční pásmo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:334 msgid "Bitrate" @@ -71,22 +71,22 @@ msgstr "Bitová rychlost" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:173 msgid "Buffered" -msgstr "" +msgstr "Ve vyrovnávací paměti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:141 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:166 msgid "CPU" -msgstr "" +msgstr "Procesor" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:43 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:87 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:162 msgid "CPU usage" -msgstr "" +msgstr "Vytížení procesoru" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:176 msgid "Cached" -msgstr "" +msgstr "V mezipaměti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:328 msgid "Channel" @@ -94,7 +94,7 @@ msgstr "Kanál" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "Collecting data..." -msgstr "" +msgstr "Shromažďování údajů…" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -126,7 +126,7 @@ msgstr "Rychlé info" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:13 msgid "Detail tabs" -msgstr "" +msgstr "Karty podrobností" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:352 msgid "Devices Connected" @@ -163,11 +163,11 @@ msgstr "Brána v6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Gbit/s" -msgstr "" +msgstr "Gbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 msgid "Good" -msgstr "" +msgstr "Dobrý" #: modules/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:31 msgid "Grant access to DHCP status display" @@ -219,7 +219,7 @@ msgstr "IPv6 předpona" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:206 msgid "Interface is disabled" -msgstr "" +msgstr "Rozhraní je zakázáno" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:21 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:23 @@ -230,7 +230,7 @@ msgstr "Internet" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Kbit/s" -msgstr "" +msgstr "Kbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:285 msgid "Kernel Version" @@ -239,21 +239,21 @@ msgstr "Verze jádra systému" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:251 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Layout" -msgstr "" +msgstr "Rozložení" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:12 msgid "Live charts" -msgstr "" +msgstr "Živé grafy" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:45 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:106 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:154 msgid "Load average" -msgstr "" +msgstr "Průměrné vytížení" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Loading view…" -msgstr "" +msgstr "Načítání pohledu…" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:280 msgid "Local Time" @@ -272,11 +272,11 @@ msgstr "Mbitů/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:142 msgid "Memory" -msgstr "" +msgstr "Operační paměť" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:170 msgid "Memory used" -msgstr "" +msgstr "Využití operační paměti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 msgid "Model" @@ -285,31 +285,31 @@ msgstr "Model" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:119 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 msgid "No RX signal" -msgstr "" +msgstr "Žádný signál příjmu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:53 msgid "No active leases" -msgstr "" +msgstr "Žádné aktivní zápůjčky" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "No data received" -msgstr "" +msgstr "Neobdrženy žádné údaje" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:88 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:113 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:180 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:244 msgid "No wireless clients connected" -msgstr "" +msgstr "Nepřipojení žádní WiFi klienti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Noise floor" -msgstr "" +msgstr "Práh šumu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:74 msgid "Not configured or no address acquired" -msgstr "" +msgstr "Nenastaveno nebo není žádná adresa zapotřebí" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -327,7 +327,7 @@ msgstr "Protokol" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:47 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:202 msgid "Resources" -msgstr "" +msgstr "Prostředky" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:217 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:316 @@ -337,11 +337,11 @@ msgstr "SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:61 msgid "Save & Apply" -msgstr "" +msgstr "Uložit a použít" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Signal" -msgstr "" +msgstr "Signál" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:35 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:96 @@ -351,11 +351,11 @@ msgstr "Síla signálu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:11 msgid "Status cards" -msgstr "" +msgstr "Stavové karty" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:180 msgid "Swap used" -msgstr "" +msgstr "Využití odkládacího prostoru (swap)" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:24 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:317 @@ -366,13 +366,16 @@ msgstr "Systém" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:130 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:137 msgid "System load" -msgstr "" +msgstr "Vytížení systému" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:18 msgid "" "The lists follow the page from top to bottom. What is in a list is shown, in " "that order: drag an entry to move it. An empty list shows the defaults." msgstr "" +"Seznamy následují stránku odshora dolů. Co je v seznamu je zobrazeno, v " +"takovém pořadí: pokud chcete položku přesunout, přetáhněte ji. Prázdný " +"seznam zobrazuje výchozí." #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:54 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 @@ -402,11 +405,11 @@ msgstr "Doba chodu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:10 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:13 msgid "WAN traffic" -msgstr "" +msgstr "WAN provoz" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:112 msgid "Weak" -msgstr "" +msgstr "Slabý" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:28 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:37 @@ -416,31 +419,31 @@ msgstr "Bezdrátová síť" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:36 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 msgid "Wireless client data usage" -msgstr "" +msgstr "Využití dat WiFi klientem" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:34 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "Wireless client distribution" -msgstr "" +msgstr "Rozprostření WiFi klienta" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:33 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:70 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:288 msgid "Wireless clients" -msgstr "" +msgstr "WiFi klienti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "bit/s" -msgstr "" +msgstr "bit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 msgid "by SSID" -msgstr "" +msgstr "podle SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "clients" -msgstr "" +msgstr "klienti" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 @@ -450,15 +453,15 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:234 msgid "dBm" -msgstr "" +msgstr "dBm" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 msgid "load %.2f" -msgstr "" +msgstr "vytížení %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:278 msgid "now" -msgstr "" +msgstr "nyní" #~ msgid "Strength" #~ msgstr "Síla" diff --git a/luci-mod-dashboard/po/es/dashboard.po b/luci-mod-dashboard/po/es/dashboard.po index 722d9dbe5..30cd1cdb5 100644 --- a/luci-mod-dashboard/po/es/dashboard.po +++ b/luci-mod-dashboard/po/es/dashboard.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"PO-Revision-Date: 2026-06-27 12:02+0000\n" -"Last-Translator: apemay \n" +"PO-Revision-Date: 2026-09-27 20:14+0000\n" +"Last-Translator: Franco Castillo \n" "Language-Team: Spanish \n" "Language: es\n" @@ -10,38 +10,38 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2026.7.dev0\n" +"X-Generator: Weblate 2026.10.dev0\n" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 msgid "%d clients" -msgstr "" +msgstr "%d clientes" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:124 msgid "%d core" msgid_plural "%d cores" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%d núcleo" +msgstr[1] "%d núcleos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d min ago" -msgstr "" +msgstr "Hace %d minutos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:72 msgid "%d of %d SSIDs active" -msgstr "" +msgstr "%d de %d SSID activos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d s ago" -msgstr "" +msgstr "Hace %d s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "15 min: %.2f" -msgstr "" +msgstr "15 minutos: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "5 min: %.2f" -msgstr "" +msgstr "5 minutos: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:322 msgid "Active" @@ -49,7 +49,7 @@ msgstr "Activo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 msgid "Active leases" -msgstr "" +msgstr "Asignaciones activas" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:295 msgid "Architecture" @@ -62,7 +62,7 @@ msgstr "BSSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:218 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:372 msgid "Band" -msgstr "" +msgstr "Banda" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:334 msgid "Bitrate" @@ -70,22 +70,22 @@ msgstr "Tasa de bits" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:173 msgid "Buffered" -msgstr "" +msgstr "En búfer" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:141 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:166 msgid "CPU" -msgstr "" +msgstr "CPU" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:43 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:87 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:162 msgid "CPU usage" -msgstr "" +msgstr "Uso de CPU" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:176 msgid "Cached" -msgstr "" +msgstr "En caché" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:328 msgid "Channel" @@ -93,7 +93,7 @@ msgstr "Canal" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "Collecting data..." -msgstr "" +msgstr "Recopilando datos..." #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -125,7 +125,7 @@ msgstr "Panel" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:13 msgid "Detail tabs" -msgstr "" +msgstr "Pestañas de detalles" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:352 msgid "Devices Connected" @@ -162,11 +162,11 @@ msgstr "GatewayV6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Gbit/s" -msgstr "" +msgstr "Gbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 msgid "Good" -msgstr "" +msgstr "Buena" #: modules/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:31 msgid "Grant access to DHCP status display" @@ -218,7 +218,7 @@ msgstr "Prefijo IPv6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:206 msgid "Interface is disabled" -msgstr "" +msgstr "La interfaz está desactivada" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:21 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:23 @@ -229,7 +229,7 @@ msgstr "Internet" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Kbit/s" -msgstr "" +msgstr "Kbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:285 msgid "Kernel Version" @@ -238,21 +238,21 @@ msgstr "Versión del núcleo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:251 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Layout" -msgstr "" +msgstr "Disposición" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:12 msgid "Live charts" -msgstr "" +msgstr "Gráficos en tiempo real" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:45 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:106 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:154 msgid "Load average" -msgstr "" +msgstr "Carga promedio" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Loading view…" -msgstr "" +msgstr "Cargando vista…" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:280 msgid "Local Time" @@ -271,11 +271,11 @@ msgstr "Mbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:142 msgid "Memory" -msgstr "" +msgstr "Memoria" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:170 msgid "Memory used" -msgstr "" +msgstr "Memoria utilizada" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 msgid "Model" @@ -284,31 +284,31 @@ msgstr "Modelo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:119 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 msgid "No RX signal" -msgstr "" +msgstr "SIn señal RX" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:53 msgid "No active leases" -msgstr "" +msgstr "Sin asignaciones activas" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "No data received" -msgstr "" +msgstr "No se recibieron datos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:88 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:113 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:180 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:244 msgid "No wireless clients connected" -msgstr "" +msgstr "No hay clientes inalámbricos conectados" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Noise floor" -msgstr "" +msgstr "Nivel de ruido" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:74 msgid "Not configured or no address acquired" -msgstr "" +msgstr "No configurado o no se ha obtenido ninguna dirección" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -326,7 +326,7 @@ msgstr "Protocolo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:47 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:202 msgid "Resources" -msgstr "" +msgstr "Recursos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:217 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:316 @@ -336,11 +336,11 @@ msgstr "SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:61 msgid "Save & Apply" -msgstr "" +msgstr "Guardar y aplicar" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Signal" -msgstr "" +msgstr "Señal" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:35 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:96 @@ -350,11 +350,11 @@ msgstr "Intensidad de la señal" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:11 msgid "Status cards" -msgstr "" +msgstr "Tarjetas de estado" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:180 msgid "Swap used" -msgstr "" +msgstr "Intercambio usado" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:24 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:317 @@ -365,13 +365,16 @@ msgstr "Sistema" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:130 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:137 msgid "System load" -msgstr "" +msgstr "Carga del sistema" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:18 msgid "" "The lists follow the page from top to bottom. What is in a list is shown, in " "that order: drag an entry to move it. An empty list shows the defaults." msgstr "" +"Las listas se muestran de arriba hacia abajo. El contenido de cada lista se " +"muestra en ese orden: arrastre una entrada para moverla. Una lista vacía " +"muestra los valores predeterminados." #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:54 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 @@ -401,11 +404,11 @@ msgstr "Tiempo de actividad" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:10 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:13 msgid "WAN traffic" -msgstr "" +msgstr "Tráfico WAN" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:112 msgid "Weak" -msgstr "" +msgstr "Débil" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:28 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:37 @@ -415,31 +418,31 @@ msgstr "Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:36 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 msgid "Wireless client data usage" -msgstr "" +msgstr "Uso de datos del cliente inalámbrico" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:34 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "Wireless client distribution" -msgstr "" +msgstr "Distribución de clientes inalámbricos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:33 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:70 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:288 msgid "Wireless clients" -msgstr "" +msgstr "Clientes inalámbricos" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "bit/s" -msgstr "" +msgstr "bit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 msgid "by SSID" -msgstr "" +msgstr "por SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "clients" -msgstr "" +msgstr "clientes" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 @@ -449,15 +452,15 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:234 msgid "dBm" -msgstr "" +msgstr "dBm" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 msgid "load %.2f" -msgstr "" +msgstr "carga %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:278 msgid "now" -msgstr "" +msgstr "ahora" #~ msgid "Strength" #~ msgstr "Intensidad" diff --git a/luci-mod-dashboard/po/pl/dashboard.po b/luci-mod-dashboard/po/pl/dashboard.po index 8b06d3d17..83fdba720 100644 --- a/luci-mod-dashboard/po/pl/dashboard.po +++ b/luci-mod-dashboard/po/pl/dashboard.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"PO-Revision-Date: 2026-08-03 04:18+0000\n" +"PO-Revision-Date: 2026-09-27 19:33+0000\n" "Last-Translator: Matthaiks \n" "Language-Team: Polish \n" @@ -11,39 +11,39 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 2026.8.dev0\n" +"X-Generator: Weblate 2026.10.dev0\n" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 msgid "%d clients" -msgstr "" +msgstr "%d klientów" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:124 msgid "%d core" msgid_plural "%d cores" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%d rdzeń" +msgstr[1] "%d rdzenie" +msgstr[2] "%d rdzeni" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d min ago" -msgstr "" +msgstr "%d min. temu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:72 msgid "%d of %d SSIDs active" -msgstr "" +msgstr "Aktywnych %d z %d identyfikatorów SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:277 msgid "%d s ago" -msgstr "" +msgstr "%d sek. temu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "15 min: %.2f" -msgstr "" +msgstr "15 min: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:108 msgid "5 min: %.2f" -msgstr "" +msgstr "5 min: %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:322 msgid "Active" @@ -51,7 +51,7 @@ msgstr "Aktywna" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 msgid "Active leases" -msgstr "" +msgstr "Aktywne dzierżawy" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:295 msgid "Architecture" @@ -64,7 +64,7 @@ msgstr "BSSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:218 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:372 msgid "Band" -msgstr "" +msgstr "Pasmo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:334 msgid "Bitrate" @@ -72,22 +72,22 @@ msgstr "Szybkość transmisji" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:173 msgid "Buffered" -msgstr "" +msgstr "Buforowana" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:141 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:166 msgid "CPU" -msgstr "" +msgstr "CPU" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:43 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:87 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:162 msgid "CPU usage" -msgstr "" +msgstr "Użycie CPU" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:176 msgid "Cached" -msgstr "" +msgstr "Podręczna" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:328 msgid "Channel" @@ -95,7 +95,7 @@ msgstr "Kanał" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "Collecting data..." -msgstr "" +msgstr "Trwa zbieranie danych..." #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -127,7 +127,7 @@ msgstr "Info panel" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:13 msgid "Detail tabs" -msgstr "" +msgstr "Karty szczegółów" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:352 msgid "Devices Connected" @@ -164,11 +164,11 @@ msgstr "BramaV6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Gbit/s" -msgstr "" +msgstr "Gbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 msgid "Good" -msgstr "" +msgstr "Dobre" #: modules/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:31 msgid "Grant access to DHCP status display" @@ -220,7 +220,7 @@ msgstr "Prefiks IPv6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:206 msgid "Interface is disabled" -msgstr "" +msgstr "Interfejs jest wyłączony" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:21 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:23 @@ -231,7 +231,7 @@ msgstr "Internet" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Kbit/s" -msgstr "" +msgstr "Kbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:285 msgid "Kernel Version" @@ -240,21 +240,21 @@ msgstr "Wersja kernela" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:251 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Layout" -msgstr "" +msgstr "Układ" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:12 msgid "Live charts" -msgstr "" +msgstr "Wykresy na żywo" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:45 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:106 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:154 msgid "Load average" -msgstr "" +msgstr "Średnie obciążenie" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js:298 msgid "Loading view…" -msgstr "" +msgstr "Ładowanie widoku…" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:280 msgid "Local Time" @@ -273,11 +273,11 @@ msgstr "Mbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:142 msgid "Memory" -msgstr "" +msgstr "Pamięć" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:170 msgid "Memory used" -msgstr "" +msgstr "Użyta pamięć" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 msgid "Model" @@ -286,31 +286,31 @@ msgstr "Model" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:119 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 msgid "No RX signal" -msgstr "" +msgstr "Brak sygnału RX" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:40 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:53 msgid "No active leases" -msgstr "" +msgstr "Brak aktywnych dzierżaw" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/history.js:52 msgid "No data received" -msgstr "" +msgstr "Nie otrzymano danych" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:88 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:113 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:180 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:244 msgid "No wireless clients connected" -msgstr "" +msgstr "Brak podłączonych klientów Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Noise floor" -msgstr "" +msgstr "Poziom szumu tła" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:74 msgid "Not configured or no address acquired" -msgstr "" +msgstr "Nie skonfigurowano lub nie uzyskano adresu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:72 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:104 @@ -328,7 +328,7 @@ msgstr "Protokół" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:47 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:202 msgid "Resources" -msgstr "" +msgstr "Zasoby" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:217 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:316 @@ -338,11 +338,11 @@ msgstr "SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:61 msgid "Save & Apply" -msgstr "" +msgstr "Zapisz i zastosuj" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:219 msgid "Signal" -msgstr "" +msgstr "Sygnał" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:35 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:96 @@ -352,11 +352,11 @@ msgstr "Siła sygnału" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:11 msgid "Status cards" -msgstr "" +msgstr "Karty statusu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:180 msgid "Swap used" -msgstr "" +msgstr "Użyta pamięć wymiany" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:24 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:317 @@ -367,13 +367,16 @@ msgstr "System" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:130 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:137 msgid "System load" -msgstr "" +msgstr "Obciążenie systemu" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/layout.js:18 msgid "" "The lists follow the page from top to bottom. What is in a list is shown, in " "that order: drag an entry to move it. An empty list shows the defaults." msgstr "" +"Listy biegną wzdłuż strony od góry do dołu. Zawartość listy jest wyświetlana " +"w określonej kolejności; aby przenieść element, należy go przeciągnąć. Pusta " +"lista prezentuje ustawienia domyślne." #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:54 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 @@ -403,11 +406,11 @@ msgstr "Czas pracy" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:10 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/15_traffic.js:13 msgid "WAN traffic" -msgstr "" +msgstr "Ruch WAN" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:112 msgid "Weak" -msgstr "" +msgstr "Słabe" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:28 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:37 @@ -417,31 +420,31 @@ msgstr "Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:36 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 msgid "Wireless client data usage" -msgstr "" +msgstr "Użycie danych klientów Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:34 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "Wireless client distribution" -msgstr "" +msgstr "Rozkład klientów Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:33 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:70 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:288 msgid "Wireless clients" -msgstr "" +msgstr "Klienty Wi-Fi" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "bit/s" -msgstr "" +msgstr "bit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 msgid "by SSID" -msgstr "" +msgstr "wg SSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:87 msgid "clients" -msgstr "" +msgstr "klienty" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 @@ -451,15 +454,15 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:234 msgid "dBm" -msgstr "" +msgstr "dBm" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 msgid "load %.2f" -msgstr "" +msgstr "obciążenie %.2f" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:278 msgid "now" -msgstr "" +msgstr "teraz" #~ msgid "Strength" #~ msgstr "Siła" diff --git a/luci-mod-dashboard/po/pt/dashboard.po b/luci-mod-dashboard/po/pt/dashboard.po index 89121aa53..3f4ef345f 100644 --- a/luci-mod-dashboard/po/pt/dashboard.po +++ b/luci-mod-dashboard/po/pt/dashboard.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"PO-Revision-Date: 2026-05-15 10:43+0000\n" -"Last-Translator: ssantos \n" +"PO-Revision-Date: 2026-09-28 19:10+0000\n" +"Last-Translator: Pavel Borecki \n" "Language-Team: Portuguese \n" "Language: pt\n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2026.5.dev0\n" +"X-Generator: Weblate 2026.10.dev0\n" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 msgid "%d clients" @@ -62,7 +62,7 @@ msgstr "BSSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:218 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:372 msgid "Band" -msgstr "" +msgstr "Banda" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:334 msgid "Bitrate" @@ -162,7 +162,7 @@ msgstr "GatewayV6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Gbit/s" -msgstr "" +msgstr "Gbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 msgid "Good" @@ -229,7 +229,7 @@ msgstr "Internet" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Kbit/s" -msgstr "" +msgstr "Kbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:285 msgid "Kernel Version" @@ -431,7 +431,7 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "bit/s" -msgstr "" +msgstr "bit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 msgid "by SSID" @@ -449,7 +449,7 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:234 msgid "dBm" -msgstr "" +msgstr "dBm" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 msgid "load %.2f" diff --git a/luci-mod-dashboard/po/pt_BR/dashboard.po b/luci-mod-dashboard/po/pt_BR/dashboard.po index c940f8b04..a8c262db6 100644 --- a/luci-mod-dashboard/po/pt_BR/dashboard.po +++ b/luci-mod-dashboard/po/pt_BR/dashboard.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"PO-Revision-Date: 2026-05-16 22:08+0000\n" -"Last-Translator: Volenski \n" +"PO-Revision-Date: 2026-09-29 12:45+0000\n" +"Last-Translator: Pavel Borecki \n" "Language-Team: Portuguese (Brazil) \n" "Language: pt_BR\n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 2026.6.dev0\n" +"X-Generator: Weblate 2026.10.dev0\n" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:97 msgid "%d clients" @@ -62,7 +62,7 @@ msgstr "BSSID" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:218 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:372 msgid "Band" -msgstr "" +msgstr "Banda" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:334 msgid "Bitrate" @@ -162,7 +162,7 @@ msgstr "GatewayV6" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Gbit/s" -msgstr "" +msgstr "Gbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:111 msgid "Good" @@ -229,7 +229,7 @@ msgstr "Internet" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "Kbit/s" -msgstr "" +msgstr "Kbit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:285 msgid "Kernel Version" @@ -431,7 +431,7 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/lib/charts.js:25 msgid "bit/s" -msgstr "" +msgstr "bit/s" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 msgid "by SSID" @@ -449,7 +449,7 @@ msgstr "" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:231 #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:234 msgid "dBm" -msgstr "" +msgstr "dBm" #: modules/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/12_resources.js:89 msgid "load %.2f" diff --git a/luci-mod-dashboard/po/zh_Hans/dashboard.po b/luci-mod-dashboard/po/zh_Hans/dashboard.po index 0a6e8c616..cdebcac6b 100644 --- a/luci-mod-dashboard/po/zh_Hans/dashboard.po +++ b/luci-mod-dashboard/po/zh_Hans/dashboard.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-08-31 06:44+0000\n" +"PO-Revision-Date: 2026-09-28 18:23+0000\n" "Last-Translator: Hosted Weblate user 54392 " "\n" "Language-Team: Chinese (Simplified Han script)