From 3e76c2c7683d7e5882ecac57d179a1659b23ef62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Aug 2026 08:57:58 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=B8=20Sync=202026-08-18=2008:57:58?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- amule/Makefile | 4 +- antileech/Makefile | 4 +- baidudrive/Makefile | 4 +- baidupcs-go/Makefile | 4 +- beszel-agent/Makefile | 4 +- boltbrowser/Makefile | 4 +- luci-app-bandix/Makefile | 4 +- .../resources/bandix/donate/alipay.jpg | Bin 109597 -> 0 bytes .../resources/bandix/donate/wechat-pay.png | Bin 152714 -> 0 bytes .../resources/view/bandix/settings.js | 134 +- luci-app-bandix/po/es/bandix.po | 21 - luci-app-bandix/po/fr/bandix.po | 21 - luci-app-bandix/po/ja/bandix.po | 21 - luci-app-bandix/po/pl/bandix.po | 21 - luci-app-bandix/po/ru/bandix.po | 21 - luci-app-bandix/po/zh_Hans/bandix.po | 21 - luci-app-bandix/po/zh_Hant/bandix.po | 21 - .../resources/mptcp/css/mptcp_diagnostics.css | 93 ++ .../resources/view/mptcp/mptcp_diagnostics.js | 305 ++++ .../view/mptcp/mptcp_dscp_routing.js | 18 +- luci-app-mptcp/po/de/mptcp.po | 1343 ++++++++++++---- luci-app-mptcp/po/fr/mptcp.po | 1337 ++++++++++++---- luci-app-mptcp/po/it/mptcp.po | 1322 ++++++++++++---- luci-app-mptcp/po/oc/mptcp.po | 1138 ++++++++++++-- luci-app-mptcp/po/ru/mptcp.po | 1156 ++++++++++++-- luci-app-mptcp/po/templates/mptcp.pot | 1251 +++++++++++---- luci-app-mptcp/po/zh_Hans/mptcp.po | 1380 +++++++++++++---- .../root/usr/libexec/rpcd/luci.mptcp | 393 +++++ .../usr/share/luci/menu.d/luci-app-mptcp.json | 11 + .../usr/share/rpcd/acl.d/luci-app-mptcp.json | 3 +- luci-app-passwall/Makefile | 9 +- .../cbi/passwall/client/type/6_naive.lua | 33 + .../luasrc/passwall/util_naiveproxy.lua | 42 + .../root/usr/share/passwall/app.sh | 8 + luci-theme-footstrap/Makefile | 2 +- luci-theme-footstrap/dev-sync.sh | 15 + .../htdocs/luci-static/resources/fs-chrome.js | 23 + .../htdocs/luci-static/resources/fs-fit.js | 300 +++- .../htdocs/luci-static/resources/fs-router.js | 34 +- .../htdocs/luci-static/resources/fs-select.js | 232 ++- .../htdocs/luci-static/resources/fs-sheets.js | 18 + .../luci-static/resources/fs-widgets.js | 16 +- luci-theme-footstrap/po/es/footstrap.po | 6 +- luci-theme-footstrap/po/ru/footstrap.po | 6 +- .../po/templates/footstrap.pot | 6 +- luci-theme-footstrap/styles/base/60-modal.css | 5 +- .../styles/pages/20-overview.css | 37 +- .../styles/theme/20-shell.css | 25 +- .../styles/theme/30-tables.css | 22 + luci-theme-footstrap/styles/theme/45-misc.css | 28 +- .../styles/theme/60-inputs.css | 44 +- .../styles/theme/97-print.css | 2 +- mhz/Makefile | 4 +- natflow/Makefile | 4 +- nexttrace/Makefile | 4 +- ooniprobe/Makefile | 4 +- 56 files changed, 8850 insertions(+), 2138 deletions(-) delete mode 100644 luci-app-bandix/htdocs/luci-static/resources/bandix/donate/alipay.jpg delete mode 100644 luci-app-bandix/htdocs/luci-static/resources/bandix/donate/wechat-pay.png create mode 100644 luci-app-mptcp/htdocs/luci-static/resources/mptcp/css/mptcp_diagnostics.css create mode 100644 luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua create mode 100644 luci-app-passwall/luasrc/passwall/util_naiveproxy.lua diff --git a/amule/Makefile b/amule/Makefile index e0ebd0b34..407440349 100644 --- a/amule/Makefile +++ b/amule/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=amule -PKG_VERSION:=2.3.3 -PKG_RELEASE:=3 +PKG_VERSION:=3.0.0 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/amule-project/amule/tar.gz/$(PKG_VERSION)? diff --git a/antileech/Makefile b/antileech/Makefile index 6afb004f3..ac132c1a2 100644 --- a/antileech/Makefile +++ b/antileech/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=antileech -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_DATE:=2021-12-05 PKG_SOURCE_URL:=https://github.com/persmule/amule-dlp.antiLeech.git -PKG_SOURCE_VERSION:=null +PKG_SOURCE_VERSION:=1b14ed828ed227933333de31ffb8e24e6c10451c PKG_MIRROR_HASH:=skip PKG_FIXUP:=autoreconf diff --git a/baidudrive/Makefile b/baidudrive/Makefile index 54667e5e3..ba6c37581 100644 --- a/baidudrive/Makefile +++ b/baidudrive/Makefile @@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk PKG_ARCH_BAIDUDRIVE:=$(ARCH) PKG_NAME:=baidudrive -PKG_VERSION:=1.0.4 -PKG_RELEASE:=11 +PKG_VERSION:=linkeasefull-runtime-v3.0.9 +PKG_RELEASE:=12 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/baidudrive-runtime-v$(PKG_VERSION)/ PKG_HASH:=skip diff --git a/baidupcs-go/Makefile b/baidupcs-go/Makefile index 6ef5fc3bd..2bc59e33d 100644 --- a/baidupcs-go/Makefile +++ b/baidupcs-go/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=BaiduPCS-Go -PKG_VERSION:=3.9.0 -PKG_RELEASE:=6 +PKG_VERSION:=4.0.1 +PKG_RELEASE:=7 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/qjfoidnh/BaiduPCS-Go/tar.gz/v$(PKG_VERSION)? diff --git a/beszel-agent/Makefile b/beszel-agent/Makefile index 23b877e65..4b0351f51 100644 --- a/beszel-agent/Makefile +++ b/beszel-agent/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=beszel-agent -PKG_VERSION:=0.18.7 -PKG_RELEASE:=7 +PKG_VERSION:=0.18.8 +PKG_RELEASE:=8 PKG_SOURCE:=$(PKG_NAME)_linux_$(or $(BESZEL_GOARCH),arm64).tar.gz PKG_SOURCE_URL:=https://github.com/henrygd/beszel/releases/download/v$(PKG_VERSION)/ diff --git a/boltbrowser/Makefile b/boltbrowser/Makefile index 271aa20fb..e6f62fd74 100644 --- a/boltbrowser/Makefile +++ b/boltbrowser/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=boltbrowser -PKG_RELEASE:=7 +PKG_RELEASE:=8 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/br0xen/boltbrowser.git PKG_SOURCE_DATE:=2023-05-31 -PKG_SOURCE_VERSION:=null +PKG_SOURCE_VERSION:=6ad3511ddb3c271fbaed2f22e409aa453ed89042 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-3.0-or-later diff --git a/luci-app-bandix/Makefile b/luci-app-bandix/Makefile index 5a9659b54..a7225a12a 100644 --- a/luci-app-bandix/Makefile +++ b/luci-app-bandix/Makefile @@ -10,8 +10,8 @@ LUCI_DEPENDS:=+luci-base +luci-lib-jsonc +curl +bandix PKG_MAINTAINER:=timsaya -PKG_VERSION:=0.12.9 -PKG_RELEASE:=8 +PKG_VERSION:=0.12.10 +PKG_RELEASE:=9 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-bandix/htdocs/luci-static/resources/bandix/donate/alipay.jpg b/luci-app-bandix/htdocs/luci-static/resources/bandix/donate/alipay.jpg deleted file mode 100644 index 5069c8e27ac694e66fa24d0d8a5fab6225818192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109597 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 z 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 diff --git a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js index 96ab55567..706595604 100644 --- a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js +++ b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js @@ -673,46 +673,6 @@ return view.extend({ return false; }; - // 支持作者(基本设置的最后一项) - var alipayImage = L.resource('bandix/donate/alipay.jpg'); - var wechatImage = L.resource('bandix/donate/wechat-pay.png'); - - function donationCard(title, imageUrl, altText, dotClass) { - return E('div', { 'class': 'bandix-donation-card' }, [ - E('h4', { 'class': 'bandix-donation-card-title' }, [ - E('span', { 'class': 'bandix-donation-dot ' + dotClass }), - title - ]), - E('a', { - 'class': 'bandix-donation-image-link', - 'href': imageUrl, - 'target': '_blank', - 'rel': 'noopener noreferrer', - 'title': altText - }, [ - E('img', { - 'class': 'bandix-donation-image', - 'src': imageUrl, - 'alt': altText, - 'loading': 'lazy' - }) - ]) - ]); - } - - o = s.option(form.DummyValue, '_donation_qr_codes', _('Support the Author')); - o.renderWidget = function () { - return E('div', { 'class': 'bandix-donation-content' }, [ - E('p', { 'class': 'bandix-donation-description' }, - _('If Bandix is useful to you, you can support its continued development.')), - E('div', { 'class': 'bandix-donation-grid' }, [ - donationCard(_('Alipay'), alipayImage, _('Scan with Alipay to support'), 'bandix-donation-dot-alipay'), - donationCard(_('WeChat Pay'), wechatImage, _('Scan with WeChat Pay to support'), 'bandix-donation-dot-wechat') - ]), - E('p', { 'class': 'bandix-donation-note' }, _('Donations are voluntary. Thank you for supporting Bandix.')) - ]); - }; - // 2. 流量监控设置部分 (traffic) s = m.section(form.NamedSection, 'traffic', 'traffic', _('Traffic Monitor Settings')); s.description = _('Configure traffic monitoring related parameters'); @@ -866,98 +826,6 @@ return view.extend({ // 将 view 实例关联到 form map,以便在 cfgvalue 中访问 m.view = this; - return m.render().then(function (mapEl) { - var oldStyle = document.getElementById('bandix-donation-styles'); - if (oldStyle && oldStyle.parentNode) oldStyle.parentNode.removeChild(oldStyle); - - document.head.appendChild(E('style', { 'id': 'bandix-donation-styles' }, ` - .bandix-donation-content { - text-align: center; - } - - .bandix-donation-description { - margin: 0 auto 18px; - max-width: 620px; - opacity: 0.72; - line-height: 1.6; - } - - .bandix-donation-grid { - display: grid; - grid-template-columns: repeat(2, minmax(220px, 280px)); - justify-content: center; - gap: 20px; - } - - .bandix-donation-card { - padding: 12px; - border: 1px solid rgba(107, 114, 128, 0.3); - border-radius: 10px; - background: rgba(107, 114, 128, 0.04); - box-sizing: border-box; - transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; - } - - .bandix-donation-card:hover { - border-color: rgba(59, 130, 246, 0.55); - box-shadow: 0 8px 24px rgba(15, 23, 42, 0.1); - transform: translateY(-2px); - } - - .bandix-donation-card-title { - display: flex; - align-items: center; - justify-content: center; - gap: 7px; - margin: 0 0 10px; - font-size: 1rem; - font-weight: 600; - } - - .bandix-donation-dot { - width: 9px; - height: 9px; - border-radius: 50%; - flex-shrink: 0; - } - - .bandix-donation-dot-alipay { - background: #1677ff; - } - - .bandix-donation-dot-wechat { - background: #07c160; - } - - .bandix-donation-image-link { - display: block; - border-radius: 7px; - overflow: hidden; - background: #ffffff; - line-height: 0; - } - - .bandix-donation-image { - display: block; - width: 100%; - height: auto; - } - - .bandix-donation-note { - margin: 14px 0 0; - font-size: 0.75rem; - opacity: 0.58; - } - - @media (max-width: 600px) { - .bandix-donation-grid { - grid-template-columns: minmax(200px, 280px); - gap: 14px; - } - } - `)); - - return mapEl; - }); + return m.render(); } }); diff --git a/luci-app-bandix/po/es/bandix.po b/luci-app-bandix/po/es/bandix.po index 9a12acca2..9a5e5885e 100644 --- a/luci-app-bandix/po/es/bandix.po +++ b/luci-app-bandix/po/es/bandix.po @@ -1115,27 +1115,6 @@ msgstr "Hoy" msgid "Yesterday" msgstr "Ayer" -msgid "Support the Author" -msgstr "Apoyar al autor" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "Si Bandix te resulta útil, puedes apoyar su desarrollo continuo." - -msgid "Alipay" -msgstr "Alipay" - -msgid "Scan with Alipay to support" -msgstr "Escanea con Alipay para apoyar" - -msgid "WeChat Pay" -msgstr "WeChat Pay" - -msgid "Scan with WeChat Pay to support" -msgstr "Escanea con WeChat Pay para apoyar" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "Las donaciones son voluntarias. Gracias por apoyar a Bandix." - msgid "This Week" msgstr "Esta Semana" diff --git a/luci-app-bandix/po/fr/bandix.po b/luci-app-bandix/po/fr/bandix.po index a32ab4cfe..f4dd364ce 100644 --- a/luci-app-bandix/po/fr/bandix.po +++ b/luci-app-bandix/po/fr/bandix.po @@ -1115,27 +1115,6 @@ msgstr "Aujourd'hui" msgid "Yesterday" msgstr "Hier" -msgid "Support the Author" -msgstr "Soutenir l’auteur" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "Si Bandix vous est utile, vous pouvez soutenir la poursuite de son développement." - -msgid "Alipay" -msgstr "Alipay" - -msgid "Scan with Alipay to support" -msgstr "Scannez avec Alipay pour nous soutenir" - -msgid "WeChat Pay" -msgstr "WeChat Pay" - -msgid "Scan with WeChat Pay to support" -msgstr "Scannez avec WeChat Pay pour nous soutenir" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "Les dons sont facultatifs. Merci de soutenir Bandix." - msgid "This Week" msgstr "Cette Semaine" diff --git a/luci-app-bandix/po/ja/bandix.po b/luci-app-bandix/po/ja/bandix.po index a27fc1d25..2387a50e3 100644 --- a/luci-app-bandix/po/ja/bandix.po +++ b/luci-app-bandix/po/ja/bandix.po @@ -1115,27 +1115,6 @@ msgstr "今日" msgid "Yesterday" msgstr "昨日" -msgid "Support the Author" -msgstr "作者を支援" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "Bandix が役に立った場合は、継続的な開発をご支援いただけます。" - -msgid "Alipay" -msgstr "Alipay" - -msgid "Scan with Alipay to support" -msgstr "Alipay でスキャンして支援" - -msgid "WeChat Pay" -msgstr "WeChat Pay" - -msgid "Scan with WeChat Pay to support" -msgstr "WeChat Pay でスキャンして支援" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "寄付は任意です。Bandix をご支援いただきありがとうございます。" - msgid "This Week" msgstr "今週" diff --git a/luci-app-bandix/po/pl/bandix.po b/luci-app-bandix/po/pl/bandix.po index 163cb6e2b..60f924267 100644 --- a/luci-app-bandix/po/pl/bandix.po +++ b/luci-app-bandix/po/pl/bandix.po @@ -1115,27 +1115,6 @@ msgstr "Dzisiaj" msgid "Yesterday" msgstr "Wczoraj" -msgid "Support the Author" -msgstr "Wesprzyj autora" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "Jeśli Bandix jest dla Ciebie przydatny, możesz wesprzeć jego dalszy rozwój." - -msgid "Alipay" -msgstr "Alipay" - -msgid "Scan with Alipay to support" -msgstr "Zeskanuj w Alipay, aby wesprzeć" - -msgid "WeChat Pay" -msgstr "WeChat Pay" - -msgid "Scan with WeChat Pay to support" -msgstr "Zeskanuj w WeChat Pay, aby wesprzeć" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "Darowizny są dobrowolne. Dziękujemy za wsparcie Bandix." - msgid "This Week" msgstr "Ten Tydzień" diff --git a/luci-app-bandix/po/ru/bandix.po b/luci-app-bandix/po/ru/bandix.po index d90852710..67d5b403b 100644 --- a/luci-app-bandix/po/ru/bandix.po +++ b/luci-app-bandix/po/ru/bandix.po @@ -1115,27 +1115,6 @@ msgstr "Сегодня" msgid "Yesterday" msgstr "Вчера" -msgid "Support the Author" -msgstr "Поддержать автора" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "Если Bandix полезен вам, вы можете поддержать его дальнейшую разработку." - -msgid "Alipay" -msgstr "Alipay" - -msgid "Scan with Alipay to support" -msgstr "Отсканируйте в Alipay, чтобы поддержать" - -msgid "WeChat Pay" -msgstr "WeChat Pay" - -msgid "Scan with WeChat Pay to support" -msgstr "Отсканируйте в WeChat Pay, чтобы поддержать" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "Пожертвования добровольны. Спасибо за поддержку Bandix." - msgid "This Week" msgstr "На этой неделе" diff --git a/luci-app-bandix/po/zh_Hans/bandix.po b/luci-app-bandix/po/zh_Hans/bandix.po index ee1c19451..8307d54a1 100644 --- a/luci-app-bandix/po/zh_Hans/bandix.po +++ b/luci-app-bandix/po/zh_Hans/bandix.po @@ -1118,27 +1118,6 @@ msgstr "今天" msgid "Yesterday" msgstr "昨天" -msgid "Support the Author" -msgstr "支持作者" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "如果 Bandix 对您有帮助,您可以支持项目的持续开发。" - -msgid "Alipay" -msgstr "支付宝" - -msgid "Scan with Alipay to support" -msgstr "使用支付宝扫码支持" - -msgid "WeChat Pay" -msgstr "微信支付" - -msgid "Scan with WeChat Pay to support" -msgstr "使用微信支付扫码支持" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "赞助完全自愿。感谢您对 Bandix 的支持。" - msgid "This Week" msgstr "本周" diff --git a/luci-app-bandix/po/zh_Hant/bandix.po b/luci-app-bandix/po/zh_Hant/bandix.po index 43d3a9cb7..1d6a37d25 100644 --- a/luci-app-bandix/po/zh_Hant/bandix.po +++ b/luci-app-bandix/po/zh_Hant/bandix.po @@ -1115,27 +1115,6 @@ msgstr "今天" msgid "Yesterday" msgstr "昨天" -msgid "Support the Author" -msgstr "支持作者" - -msgid "If Bandix is useful to you, you can support its continued development." -msgstr "如果 Bandix 對您有幫助,您可以支持專案的持續開發。" - -msgid "Alipay" -msgstr "支付寶" - -msgid "Scan with Alipay to support" -msgstr "使用支付寶掃碼支持" - -msgid "WeChat Pay" -msgstr "微信支付" - -msgid "Scan with WeChat Pay to support" -msgstr "使用微信支付掃碼支持" - -msgid "Donations are voluntary. Thank you for supporting Bandix." -msgstr "贊助完全自願。感謝您對 Bandix 的支持。" - msgid "This Week" msgstr "本週" diff --git a/luci-app-mptcp/htdocs/luci-static/resources/mptcp/css/mptcp_diagnostics.css b/luci-app-mptcp/htdocs/luci-static/resources/mptcp/css/mptcp_diagnostics.css new file mode 100644 index 000000000..22d69340f --- /dev/null +++ b/luci-app-mptcp/htdocs/luci-static/resources/mptcp/css/mptcp_diagnostics.css @@ -0,0 +1,93 @@ +/* ── CSS custom properties (same palette as wanstatus.css, duplicated so + this page doesn't depend on wanstatus.css having been loaded first) ── */ +:root { + --diag-bg: #ffffff; + --diag-border: #e2e6ea; + --diag-text: #1a2332; + --diag-muted: #6b7a8d; + --diag-ok: #22c55e; + --diag-warn: #f59e0b; + --diag-err: #ef4444; + --diag-ok-bg: #f0fdf4; + --diag-warn-bg: #fffbeb; + --diag-err-bg: #fef2f2; + --diag-ok-border: #bbf7d0; + --diag-warn-border:#fde68a; + --diag-err-border: #fecaca; + --diag-radius: 10px; +} + +.omrdiag-summary { + display: flex; + flex-direction: column; + gap: 10px; + margin: 10px 0 20px 0; +} + +.omrdiag-issue { + display: flex; + gap: 10px; + align-items: flex-start; + padding: 10px 14px; + border-radius: var(--diag-radius); + border: 1px solid var(--diag-border); + background: var(--diag-bg); +} +.omrdiag-issue.ok { border-color: var(--diag-ok-border); background: var(--diag-ok-bg); } +.omrdiag-issue.warning { border-color: var(--diag-warn-border); background: var(--diag-warn-bg); } +.omrdiag-issue.error { border-color: var(--diag-err-border); background: var(--diag-err-bg); } + +.omrdiag-issue .omrdiag-dot { + flex: 0 0 10px; + width: 10px; + height: 10px; + border-radius: 50%; + margin-top: 5px; + background: var(--diag-muted); +} +.omrdiag-issue.ok .omrdiag-dot { background: var(--diag-ok); } +.omrdiag-issue.warning .omrdiag-dot { background: var(--diag-warn); } +.omrdiag-issue.error .omrdiag-dot { background: var(--diag-err); } + +.omrdiag-issue .omrdiag-body { flex: 1; min-width: 0; } +.omrdiag-issue .omrdiag-message { font-weight: 700; color: var(--diag-text); } +.omrdiag-issue .omrdiag-detail { font-size: 12px; color: var(--diag-muted); margin-top: 3px; line-height: 1.5; } + +.omrdiag-wan-table, +.omrdiag-counters-table { + border-collapse: collapse; + width: 100%; + margin: 8px 0 18px 0; +} +.omrdiag-wan-table th, +.omrdiag-wan-table td, +.omrdiag-counters-table th, +.omrdiag-counters-table td { + border: 1px solid var(--diag-border); + padding: 6px 10px; + text-align: left; + font-size: 12.5px; +} +.omrdiag-wan-table th, +.omrdiag-counters-table th { + background: rgba(0,0,0,.03); + font-weight: 700; +} +.omrdiag-badge { + display: inline-block; + padding: 1px 8px; + border-radius: 999px; + font-size: 11px; + font-weight: 700; +} +.omrdiag-badge.ok { background: var(--diag-ok-bg); color: #15803d; border: 1px solid var(--diag-ok-border); } +.omrdiag-badge.warning { background: var(--diag-warn-bg); color: #b45309; border: 1px solid var(--diag-warn-border); } +.omrdiag-badge.error { background: var(--diag-err-bg); color: #b91c1c; border: 1px solid var(--diag-err-border); } + +.omrdiag-counters-table td.omrdiag-nonzero { font-weight: 700; color: #b45309; } + +.omrdiag-updated { + font-size: 11px; + color: var(--diag-muted); + margin-bottom: 6px; +} diff --git a/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js b/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js new file mode 100644 index 000000000..939c4b88e --- /dev/null +++ b/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js @@ -0,0 +1,305 @@ +'use strict'; +'require view'; +'require poll'; +'require rpc'; + +var callDiagnose = rpc.declare({ + object: 'luci.mptcp', + method: 'diagnose', + expect: { '': {} } +}); + +var COUNTER_LABELS = { + /* Initial MP_CAPABLE handshake (does this connection become MPTCP at all?) */ + MPCapableSYNTX: _('MPTCP handshake attempts sent (SYN)'), + MPCapableSYNRX: _('MPTCP handshake attempts received (SYN)'), + MPCapableSYNACKRX: _('MPTCP handshake accepted by peer (SYN/ACK)'), + MPCapableACKRX: _('MPTCP handshake completed (ACK)'), + MPCapableFallbackSYNACK: _('Fallback to TCP (SYN/ACK stripped)'), + MPCapableFallbackACK: _('Fallback to TCP (ACK stripped)'), + MPCapableSYNTXDrop: _('MPTCP handshake dropped client-side, fell back to TCP'), + MPCapableSYNTXDisabled: _('MPTCP handshake disabled client-side after past issues'), + MPCapableEndpAttempt: _('MPTCP rejected on a port-only endpoint'), + MPFallbackTokenInit: _('Could not allocate an MPTCP token, fell back to TCP'), + + /* MP_JOIN handshake (does a WAN succeed in adding a subflow?) */ + MPJoinSynTx: _('Subflow JOIN attempts sent (SYN)'), + MPJoinSynTxCreatSkErr: _('Subflow JOIN failed: could not create socket'), + MPJoinSynTxBindErr: _('Subflow JOIN failed: could not bind address'), + MPJoinSynTxConnectErr: _('Subflow JOIN failed: could not connect'), + MPJoinSynRx: _('Subflow JOIN attempts received (SYN)'), + MPJoinSynBackupRx: _('Subflow JOIN attempts received (SYN, backup)'), + MPJoinSynAckRx: _('Subflow JOIN accepted by peer (SYN/ACK)'), + MPJoinSynAckBackupRx: _('Subflow JOIN accepted by peer (SYN/ACK, backup)'), + MPJoinSynAckHMacFailure: _('JOIN SYN/ACK authentication failures'), + MPJoinAckRx: _('Subflow JOIN completed (ACK)'), + MPJoinAckHMacFailure: _('JOIN ACK authentication failures'), + MPJoinNoTokenFound: _('JOIN attempts with unknown token'), + MPJoinRejected: _('JOIN request rejected by the path manager'), + MPJoinPortSynRx: _('Subflow JOIN SYN received on a different port'), + MPJoinPortSynAckRx: _('Subflow JOIN SYN/ACK received on a different port'), + MPJoinPortAckRx: _('Subflow JOIN ACK received on a different port'), + MismatchPortSynRx: _('Subflow JOIN SYN with mismatched port'), + MismatchPortAckRx: _('Subflow JOIN ACK with mismatched port'), + + /* Data-sequence mapping / data path integrity */ + MPTCPRetrans: _('MPTCP-level retransmissions'), + DSSNotMatching: _('Data sequence mapping did not match the previous one'), + DSSCorruptionFallback: _('DSS corruption detected, fell back to plain TCP'), + DSSCorruptionReset: _('DSS corruption detected, subflow reset'), + DSSNoMatchTCP: _('Data sequence mapping did not match TCP sequence numbers'), + InfiniteMapTx: _('Infinite mapping sent (fell back to plain TCP semantics)'), + InfiniteMapRx: _('Infinite mapping received (peer fell back to plain TCP semantics)'), + DataCsumErr: _('Data checksum errors'), + NoDSSInWindow: _('Segments received outside the MPTCP mapping window'), + DuplicateData: _('Duplicate data segments discarded'), + OFOQueueTail: _('Out-of-order segments queued at tail'), + OFOQueue: _('Out-of-order segments queued'), + OFOMerge: _('Out-of-order segments merged'), + + /* Subflow lifecycle: stale/blackhole detection and removal */ + Blackhole: _('Blackhole detected on the path'), + SubflowStale: _('Subflows marked stale (possible blackhole)'), + SubflowRecover: _('Stale subflows recovered'), + RmSubflow: _('Subflows removed'), + + /* ADD_ADDR / RM_ADDR signalling (extra WAN addresses advertised to the peer) */ + AddAddr: _('ADD_ADDR signals received'), + AddAddrTx: _('ADD_ADDR signals sent'), + AddAddrTxDrop: _('ADD_ADDR signals failed to send'), + AddAddrDrop: _('ADD_ADDR signals dropped'), + EchoAdd: _('ADD_ADDR echo received'), + EchoAddTx: _('ADD_ADDR echo sent'), + EchoAddTxDrop: _('ADD_ADDR echo failed to send'), + PortAdd: _('ADD_ADDR received with a port number'), + RmAddr: _('RM_ADDR signals received'), + RmAddrTx: _('RM_ADDR signals sent'), + RmAddrTxDrop: _('RM_ADDR signals failed to send'), + RmAddrDrop: _('RM_ADDR signals dropped'), + + /* Subflow priority (MP_PRIO: backup/non-backup flag changes) */ + MPPrioTx: _('Subflow priority change sent (MP_PRIO)'), + MPPrioRx: _('Subflow priority change received (MP_PRIO)'), + + /* Connection teardown */ + MPFailTx: _('Data mapping failures sent (MP_FAIL)'), + MPFailRx: _('Data mapping failures received (MP_FAIL)'), + MPFastcloseTx: _('Fastclose sent'), + MPFastcloseRx: _('Fastclose received'), + MPRstTx: _('MPTCP resets sent'), + MPRstRx: _('MPTCP resets received'), + + /* Receive-window sharing across subflows */ + SndWndShared: _('Send window shared across subflows'), + RcvWndShared: _('Receive window shared across subflows'), + RcvWndConflictUpdate: _('Receive window conflict resolved on update'), + RcvWndConflict: _('Receive window update conflicts'), + + /* Misc: whole-connection fallback reasons, gauges */ + MPCurrEstab: _('Established MPTCP connections (current)'), + MPCapableDataFallback: _('Fell back to TCP: missing data on first established packet'), + MD5SigFallback: _('Fell back to TCP: conflicting TCP MD5SIG option'), + DssFallback: _('Fell back to TCP: bad or missing data sequence signal'), + SimultConnectFallback: _('Fell back to TCP: simultaneous connect'), + FallbackFailed: _("Couldn't fall back to TCP (connection state didn't allow it)"), + WinProbe: _('MPTCP-level zero-window probes') +}; + +return view.extend({ + load: function() { + return callDiagnose().catch(function() { return null; }); + }, + + pollData: function(container) { + poll.add(L.bind(function() { + return callDiagnose().then(L.bind(function(data) { + this.renderAll(container, data); + }, this)).catch(function() { + /* Ignore transient poll errors -- keep showing the last good snapshot */ + }); + }, this), 15); + }, + + render: function(initialData) { + if (!document.querySelector('link[href*="mptcp_diagnostics.css"]')) { + var link = document.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = L.resource('mptcp/css/mptcp_diagnostics.css'); + document.head.appendChild(link); + } + + var container = E('div', { 'id': 'omrdiag-container' }, [ + E('img', { 'src': L.resource('spinner.gif') }) + ]); + + var seeAlso = E('div', { 'class': 'cbi-section' }, [ + E('legend', {}, [ _('Related pages') ]), + E('ul', {}, [ + E('li', {}, [ E('a', { 'href': L.url('admin/system/openmptcprouter/status') }, [ _('OpenMPTCProuter Network overview / Status') ]) ]), + E('li', {}, [ E('a', { 'href': L.url('admin/network/mptcp/mptcp') }, [ _('MPTCP Settings') ]) ]), + E('li', {}, [ E('a', { 'href': L.url('admin/network/mptcp/mptcp_fullmesh') }, [ _('MPTCP Fullmesh (subflow map)') ]) ]), + E('li', {}, [ E('a', { 'href': L.url('admin/network/mptcp/mptcp_connections') }, [ _('MPTCP Established connections') ]) ]), + E('li', {}, [ E('a', { 'href': L.url('admin/network/mptcp/mptcp_monitor') }, [ _('MPTCP monitoring (raw kernel counters)') ]) ]) + ]) + ]); + + var page = E('div', {}, [ + E('h2', {}, [ _('MPTCP Diagnostics') ]), + E('div', { 'class': 'cbi-map-descr' }, [ + _('Helps explain why MPTCP might not be aggregating your WANs correctly: fallback to plain TCP, ' + + 'blackholed/stale subflows, resets, checksum errors, and WANs that never got an MPTCP endpoint ' + + 'registered at all. Refreshes automatically every 15 seconds.') + ]), + container, + seeAlso + ]); + + this.renderAll(container, initialData); + this.pollData(container); + + return page; + }, + + renderAll: function(container, data) { + if (!container) return; + var d = data || {}; + + container.textContent = ''; + container.appendChild(E('div', { 'class': 'omrdiag-updated' }, + [ _('Last updated:') + ' ' + (new Date()).toLocaleTimeString() ])); + + container.appendChild(this.renderIssues(d.issues || [])); + container.appendChild(this.renderWanTable(d.wans || [])); + container.appendChild(this.renderSettings(d.settings || {}, d.limits || {}, d.established_count)); + container.appendChild(this.renderCounters(d.counters || {})); + }, + + renderIssues: function(issues) { + var box = E('div', { 'class': 'omrdiag-summary' }); + if (!issues.length) { + box.appendChild(E('div', { 'class': 'omrdiag-issue' }, [ + E('div', { 'class': 'omrdiag-dot' }), + E('div', { 'class': 'omrdiag-body' }, [ + E('div', { 'class': 'omrdiag-message' }, [ _('No diagnostic data available yet.') ]) + ]) + ])); + return box; + } + issues.forEach(function(issue) { + var sev = issue.severity || 'warning'; + box.appendChild(E('div', { 'class': 'omrdiag-issue ' + sev }, [ + E('div', { 'class': 'omrdiag-dot' }), + E('div', { 'class': 'omrdiag-body' }, [ + E('div', { 'class': 'omrdiag-message' }, [ issue.message || '' ]), + issue.detail ? E('div', { 'class': 'omrdiag-detail' }, [ issue.detail ]) : '' + ]) + ])); + }); + return box; + }, + + renderWanTable: function(wans) { + var wrap = E('div', {}, [ E('h3', {}, [ _('Per-WAN MPTCP endpoint status') ]) ]); + if (!wans.length) { + wrap.appendChild(E('p', {}, [ _('No multipath-enabled WAN interfaces found.') ])); + return wrap; + } + var table = E('table', { 'class': 'omrdiag-wan-table' }, [ + E('tr', {}, [ + E('th', {}, [ _('WAN') ]), + E('th', {}, [ _('Device') ]), + E('th', {}, [ _('Mode') ]), + E('th', {}, [ _('MPTCP endpoint') ]), + E('th', {}, [ _('Endpoint flags') ]) + ]) + ]); + wans.forEach(function(wan) { + var ok = !!wan.has_endpoint; + table.appendChild(E('tr', {}, [ + E('td', {}, [ wan.name || '' ]), + E('td', {}, [ wan.device || '-' ]), + E('td', {}, [ wan.multipath || 'off' ]), + E('td', {}, [ + E('span', { 'class': 'omrdiag-badge ' + (ok ? 'ok' : 'error') }, + [ ok ? _('registered') : _('missing') ]) + ]), + E('td', {}, [ wan.endpoint_flags || '-' ]) + ])); + }); + wrap.appendChild(table); + return wrap; + }, + + renderSettings: function(settings, limits, establishedCount) { + // "1"/"0" mean enabled/disabled for the enabled and checksum sysctls -- + // but NOT for path_manager: on the in-kernel MPTCP sysctl layout, + // net.mptcp.pm_type is a selector between two path manager + // *implementations* (0 = in-kernel, 1 = userspace/mptcpd), not an + // on/off switch -- "0" here is the normal default, not "disabled". + // On the legacy out-of-tree sysctl layout path_manager is already a + // name (e.g. "fullmesh"), not a 0/1 code, so leave those untouched. + var formatBool = function(v) { + if (v === '1') return _('Enabled') + ' (1)'; + if (v === '0') return _('Disabled') + ' (0)'; + return v; + }; + var formatPathManager = function(v) { + if (v === '0') return _('In-kernel') + ' (0)'; + if (v === '1') return _('Userspace') + ' (1)'; + return v; + }; + var rows = [ + [ _('MPTCP enabled'), formatBool(settings.enabled) ], + [ _('Path manager'), formatPathManager(settings.path_manager) ], + [ _('Scheduler'), settings.scheduler ], + [ _('Checksum'), formatBool(settings.checksum) ], + [ _('Stale loss count threshold'), settings.stale_loss_cnt ], + [ _('Blackhole timeout (s)'), settings.blackhole_timeout ], + [ _('Add-addr timeout (s)'), settings.add_addr_timeout ], + [ _('Close timeout (s)'), settings.close_timeout ], + [ _('Subflow limit'), limits.subflows ], + [ _('Accepted ADD_ADDR limit'), limits.add_addr_accepted ], + [ _('Established MPTCP connections (right now)'), establishedCount ] + ]; + var wrap = E('div', {}, [ E('h3', {}, [ _('Kernel MPTCP configuration') ]) ]); + var table = E('table', { 'class': 'omrdiag-wan-table' }); + rows.forEach(function(r) { + if (r[1] === undefined || r[1] === null || r[1] === '') return; + table.appendChild(E('tr', {}, [ E('th', {}, [ r[0] ]), E('td', {}, [ String(r[1]) ]) ])); + }); + wrap.appendChild(table); + return wrap; + }, + + renderCounters: function(counters) { + var keys = Object.keys(counters || {}); + var wrap = E('div', {}, [ E('h3', {}, [ _('MPTCP kernel counters (since boot)') ]) ]); + if (!keys.length) { + wrap.appendChild(E('p', {}, [ _('No counters available (nstat/multipath -m returned nothing).') ])); + return wrap; + } + keys.sort(function(a, b) { + var av = counters[a] || 0, bv = counters[b] || 0; + if (av !== bv) return bv - av; + return a < b ? -1 : (a > b ? 1 : 0); + }); + var table = E('table', { 'class': 'omrdiag-counters-table' }, [ + E('tr', {}, [ E('th', {}, [ _('Counter') ]), E('th', {}, [ _('Value') ]) ]) + ]); + keys.forEach(function(key) { + var value = counters[key] || 0; + var label = COUNTER_LABELS[key] ? (COUNTER_LABELS[key] + ' (' + key + ')') : key; + table.appendChild(E('tr', {}, [ + E('td', {}, [ label ]), + E('td', { 'class': value > 0 ? 'omrdiag-nonzero' : '' }, [ String(value) ]) + ])); + }); + wrap.appendChild(table); + return wrap; + }, + + handleSave: null, + handleSaveApply: null, + handleReset: null +}); diff --git a/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js b/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js index 2c9fbc2fc..7d12ece3d 100644 --- a/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js +++ b/luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js @@ -41,6 +41,15 @@ function isEligibleIface(name) { name !== 'omrvpn' && name !== 'OWVPN' && name !== 'omr6in4'; } +// Same "multipath actually turned on" whitelist as the bandwidth page's +// _getMultipathIfaces (multipath.js) and the rpcd backend's +// multipath_bandwidth: "off"/unset doesn't count. +function isMultipathEnabledIface(name) { + var multipath = uci.get('network', name, 'multipath'); + return multipath === 'on' || multipath === 'master' || + multipath === 'backup' || multipath === 'handover'; +} + function fillIfaceOptions(option) { option.value('', _('-- not pinned --')); uci.sections('network', 'interface', function(ifc) { @@ -140,7 +149,9 @@ return L.view.extend({ if (vpsSyncEnabled) { o = s.option(form.ListValue, 'download_interface', _('Download interface'), - _('Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler (pins the VPS’s own send-side choice via dscp_remote_id) and can be a different WAN than Upload. mqvpn has no equivalent: its downlink always mirrors whichever WAN carries the class on upload, so this field has no effect on mqvpn.')); + _('Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler (pins the VPS’s own send-side choice via dscp_remote_id) and can be a different WAN than Upload.') + ' ' + + _('Leave empty to just mirror this row’s Upload interface to the gateway instead -- the same "download always follows upload" behavior mqvpn already has built in natively.') + ' ' + + _('mqvpn has no equivalent: its downlink always mirrors whichever WAN carries the class on upload, so this field has no effect on mqvpn.')); o.load = function(section_id) { fillIfaceOptions(this); return this.super('load', [section_id]); @@ -150,9 +161,10 @@ return L.view.extend({ if (showWeight) { s = m.section(form.TypedSection, 'interface', _('WAN weight'), - _('Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by mqvpn’s "Weighted RTT"/"Weighted Round Robin" schedulers -- same value, applies to both upload and download (mirrored to the gateway automatically). Unlike the DSCP pins above, weight is a single value per WAN, not per traffic class.')); + _('Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by mqvpn’s "Weighted RTT"/"Weighted Round Robin" schedulers -- same value, applies to both upload and download (mirrored to the gateway automatically). Unlike the DSCP pins above, weight is a single value per WAN, not per traffic class.') + ' ' + + _('Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the MPTCP page’s Interfaces Settings) are listed below.')); s.filter = function(section) { - return isEligibleIface(section); + return isEligibleIface(section) && isMultipathEnabledIface(section); }; o = s.option(form.Value, 'multipath_weight', _('Weight'), diff --git a/luci-app-mptcp/po/de/mptcp.po b/luci-app-mptcp/po/de/mptcp.po index e1c45fcfb..d5b90262d 100644 --- a/luci-app-mptcp/po/de/mptcp.po +++ b/luci-app-mptcp/po/de/mptcp.po @@ -12,362 +12,923 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(Fenster von %d Minuten, %d Sekunden Intervall)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(Fenster %d Minunten, %d Sekunden Intervall)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "Durchschnitt:" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 -msgid "Bandwidth" -msgstr "Bandbreite" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 -msgid "Check if MPTCP between interface and server is working." -msgstr "" -"Prüfung auf transparenten Transport von MPTCP-Paketen zwischen Anschluss und " -"Server." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Congestion Control" -msgstr "Überlauf-Steuerung" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 -msgid "Consecutive segments that should be sent for round robin" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "derzeit:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -#, fuzzy -msgid "Default is cubic" -msgstr "Voreinstellung ist 'bbr'" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -#, fuzzy -msgid "Default is fullmesh" -msgstr "Voreinstellung ist 'bbr'" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "Downstream:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 -msgid "Error" -msgstr "Fehler" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 -msgid "Established connections" -msgstr "aufgebaute Verbindungen" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 -msgid "Fill the congestion window on all subflows for round robin" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 -msgid "Fullmesh subflows for each pair of IP addresses" -msgstr "" -"Datenströme im vollvermaschter Betrieb für die jeweiligen Gegegenstellen-" -"Paare" - -#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 -msgid "Grant UCI access for luci-app-mptcp" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 msgid "" -"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " -"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " -"blocked." +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "Ankommend:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 -msgid "Interface" -msgstr "Schnittstelle" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 -msgid "Interfaces Settings" -msgstr "Anschluss-Einstellungen" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "Wird geladen" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 -msgid "MB/s" -msgstr "MByte/s" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 -msgid "MPTCP" -msgstr "MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 -msgid "MPTCP Fullmesh" -msgstr "MPTCP Vollvermaschung" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 -msgid "MPTCP Support Check" -msgstr "Prüfung auf Transparenz für MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 -msgid "MPTCP monitoring" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 -msgid "Mbit/s" -msgstr "MBit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 -msgid "Multipath Debug" -msgstr "Mehrfachausbreitungspfad-Analyse" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "Multipath TCP" -msgstr "Multipath-TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 -msgid "Multipath TCP SYN retries" -msgstr "Multipath TCP SYN Wiederholungen" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 -msgid "Multipath TCP checksum" -msgstr "Multipath TCP Prüfummen" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Multipath TCP path-manager" -msgstr "Multipath TCP Pfadkontrolle" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "Multipath TCP scheduler" -msgstr "Multpath TCP Priorisierungskontrolle" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 -#, fuzzy -#| msgid "Multipath TCP" -msgid "Multipath TCP version" -msgstr "Multipath-TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 -msgid "Netlink" -msgstr "Netlink-Layer" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." -msgstr "" -"Netzwerk-MPTCP Einstellungen. Dokumentation auf http://multipath-tcp.org/pmwiki.php/" -"Users/ConfigureMPTCP (english)." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "One interface must be set as master" -msgstr "Ein Anschluss muss als 'primär' defininiert werden." - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "Abgehend:" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "Spitze:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 -msgid "Re-create fullmesh subflows after a timeout" -msgstr "Wiederverbindungs-Wartezeit der Vollvermaschungs-Verbindungen" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "Echtzeit-Daten" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 -msgid "Settings" -msgstr "Einstellungen" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 -msgid "Test" -msgstr "Test" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 -msgid "" -"The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "Upstream:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "Warte auf Abschluss der Aufgaben" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 -msgid "backup" -msgstr "Sicherung" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "default" -msgstr "Voreinstellung" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 -msgid "disable" -msgstr "ausschalten" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 -msgid "disabled" -msgstr "aus" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 -msgid "enable" -msgstr "anschalten" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 -msgid "enabled" -msgstr "an" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kB/s" -msgstr "kBytes/s" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kbit/s" -msgstr "kBit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 -msgid "master" -msgstr "primär" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 msgid "All interfaces" msgstr "Alle Schnittstellen" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 -msgid "All interfaces – combined view" -msgstr "Alle Schnittstellen - kombinierte Ansicht" - #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 msgid "All interfaces overlaid, inbound and outbound separately" msgstr "Alle Schnittstellen überlagert, eingehend und ausgehend getrennt" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "Alle Schnittstellen - kombinierte Ansicht" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 msgid "Average" msgstr "Durchschnitt" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 +msgid "Bandwidth" +msgstr "Bandbreite" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 +msgid "Check if MPTCP between interface and server is working." +msgstr "" +"Prüfung auf transparenten Transport von MPTCP-Paketen zwischen Anschluss und " +"Server." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Congestion Control" +msgstr "Überlauf-Steuerung" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 msgid "Current" msgstr "Aktuell" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +#, fuzzy +msgid "Default is cubic" +msgstr "Voreinstellung ist 'bbr'" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +#, fuzzy +msgid "Default is fullmesh" +msgstr "Voreinstellung ist 'bbr'" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 +msgid "Error" +msgstr "Fehler" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 +msgid "Established connections" +msgstr "aufgebaute Verbindungen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "" +"Datenströme im vollvermaschter Betrieb für die jeweiligen Gegegenstellen-" +"Paare" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 msgid "In" msgstr "Eingehend" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 -msgid "Inbound – all interfaces" -msgstr "Eingehend - alle Schnittstellen" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 msgid "Inbound traffic" msgstr "Eingehender Verkehr" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "Eingehend - alle Schnittstellen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 +msgid "Interface" +msgstr "Schnittstelle" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 +msgid "Interfaces Settings" +msgstr "Anschluss-Einstellungen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"Leer lassen, um einfach die Upload-Schnittstelle dieser Zeile auf das " +"Gateway zu spiegeln -- das gleiche Verhalten \"Download folgt immer dem " +"Upload\", das mqvpn bereits nativ eingebaut hat." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 +msgid "MB/s" +msgstr "MByte/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Vollvermaschung" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 +msgid "MPTCP Support Check" +msgstr "Prüfung auf Transparenz für MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 +msgid "Mbit/s" +msgstr "MBit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 +msgid "Multipath Debug" +msgstr "Mehrfachausbreitungspfad-Analyse" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "Multipath TCP" +msgstr "Multipath-TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 +msgid "Multipath TCP SYN retries" +msgstr "Multipath TCP SYN Wiederholungen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 +msgid "Multipath TCP checksum" +msgstr "Multipath TCP Prüfummen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Multipath TCP path-manager" +msgstr "Multipath TCP Pfadkontrolle" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "Multipath TCP scheduler" +msgstr "Multpath TCP Priorisierungskontrolle" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 +#, fuzzy +msgid "Multipath TCP version" +msgstr "Multipath-TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 +msgid "Netlink" +msgstr "Netlink-Layer" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 msgid "No multipath WAN interface is currently available." msgstr "Derzeit ist keine Multipath-WAN-Schnittstelle verfügbar." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "One interface must be set as master" +msgstr "Ein Anschluss muss als 'primär' defininiert werden." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"Es werden nur WANs mit aktiviertem Multipath TCP aufgelistet (die Option " +"„Multipath TCP“ im Abschnitt „Schnittstelleneinstellungen“ der MPTCP-Seite)." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 msgid "Out" msgstr "Ausgehend" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 -msgid "Outbound – all interfaces" -msgstr "Ausgehend - alle Schnittstellen" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 msgid "Outbound traffic" msgstr "Ausgehender Verkehr" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "Ausgehend - alle Schnittstellen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 msgid "Peak" msgstr "Spitze" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Wiederverbindungs-Wartezeit der Vollvermaschungs-Verbindungen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 +msgid "Settings" +msgstr "Einstellungen" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 +msgid "Test" +msgstr "Test" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 @@ -382,6 +943,139 @@ msgstr "Gesamt eingehend" msgid "Total out" msgstr "Gesamt ausgehend" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 +msgid "backup" +msgstr "Sicherung" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 +msgid "default" +msgstr "Voreinstellung" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 +msgid "disable" +msgstr "ausschalten" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 +msgid "disabled" +msgstr "aus" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 +msgid "enable" +msgstr "anschalten" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 +msgid "enabled" +msgstr "an" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 +msgid "kB/s" +msgstr "kBytes/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 +msgid "kbit/s" +msgstr "kBit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 +msgid "master" +msgstr "primär" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 @@ -389,22 +1083,81 @@ msgstr "Gesamt ausgehend" msgid "minutes window, 1 second interval" msgstr "Minuten Zeitfenster, 1-Sekunden-Intervall" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "ndiff-Ports Verbindungs-Nummer" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" msgstr "" +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(Fenster von %d Minuten, %d Sekunden Intervall)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(Fenster %d Minunten, %d Sekunden Intervall)" + +#~ msgid "Average:" +#~ msgstr "Durchschnitt:" + +#~ msgid "Current:" +#~ msgstr "derzeit:" + +#~ msgid "Download:" +#~ msgstr "Downstream:" + +#~ msgid "Inbound:" +#~ msgstr "Ankommend:" + +#~ msgid "Loading" +#~ msgstr "Wird geladen" + +#~ msgid "" +#~ "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP for help." +#~ msgstr "" +#~ "Netzwerk-MPTCP Einstellungen. Dokumentation auf http://multipath-tcp.org/" +#~ "pmwiki.php/Users/ConfigureMPTCP (english)." + +#~ msgid "Outbound:" +#~ msgstr "Abgehend:" + +#~ msgid "Peak:" +#~ msgstr "Spitze:" + +#~ msgid "Realtime Traffic" +#~ msgstr "Echtzeit-Daten" + +#~ msgid "Upload:" +#~ msgstr "Upstream:" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "Warte auf Abschluss der Aufgaben" + #~ msgid "BLEST" #~ msgstr "Blockierungsvorhersage-Betrieb" diff --git a/luci-app-mptcp/po/fr/mptcp.po b/luci-app-mptcp/po/fr/mptcp.po index fc9c78941..417e0a3fa 100644 --- a/luci-app-mptcp/po/fr/mptcp.po +++ b/luci-app-mptcp/po/fr/mptcp.po @@ -13,82 +13,382 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.10.1\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(fenêtre de %d minute, intervalle de %d seconde)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(fenêtre de %d minutes, intervalle de %d secondes)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "Moyenne :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" +msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 +msgid "" +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 +msgid "All interfaces" +msgstr "Toutes les interfaces" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 +msgid "All interfaces overlaid, inbound and outbound separately" +msgstr "Toutes les interfaces superposées, entrant et sortant séparés" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "Toutes les interfaces - vue combinée" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 +msgid "Average" +msgstr "Moyenne" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 msgid "Bandwidth" msgstr "Bande passante" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 msgid "Check if MPTCP between interface and server is working." msgstr "Vérifiez si MPTCP entre l'interface et le serveur fonctionne." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 msgid "Congestion Control" msgstr "Contrôle de la congestion" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 msgid "Consecutive segments that should be sent for round robin" msgstr "Segments consécutifs à envoyer pour round robin" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "Actuellement :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 +msgid "Current" +msgstr "Actuel" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 msgid "Default is cubic" msgstr "La valeur par défaut est cubic" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 msgid "Default is fullmesh" msgstr "La valeur par défaut est fullmesh" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "Téléchargement :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 msgid "Error" msgstr "Erreur" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 msgid "Established connections" msgstr "Connexions établies" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 msgid "Fill the congestion window on all subflows for round robin" msgstr "" "Remplir la fenêtre de congestion de tous les sous-flux pour round robin" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Sous-flux Fullmesh pour chaque paire d'adresses IP" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + #: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 msgid "Grant UCI access for luci-app-mptcp" msgstr "Accorder l'accès UCI pour luci-app-mlvpn" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 msgid "" "If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " "MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " @@ -98,275 +398,536 @@ msgstr "" "MPTCP est pris en charge. Si il y a \"-TCPOptionMPTCPCapable\", alors il est " "bloqué." -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "Entrant :" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 -msgid "Interface" -msgstr "Interface" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 -msgid "Interfaces Settings" -msgstr "Paramètres des interfaces" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "Chargement" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 -msgid "MB/s" -msgstr "Mo/s" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 -msgid "MPTCP" -msgstr "MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 -msgid "MPTCP Fullmesh" -msgstr "MPTCP Fullmesh" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 -msgid "MPTCP Support Check" -msgstr "Vérification du support MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 -msgid "MPTCP monitoring" -msgstr "Surveillance MPTCP" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 -msgid "Mbit/s" -msgstr "Mbit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 -msgid "Multipath Debug" -msgstr "Débogage multipath" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "Multipath TCP" -msgstr "Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 -msgid "Multipath TCP SYN retries" -msgstr "Tentatives Multipath TCP SYN" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 -msgid "Multipath TCP checksum" -msgstr "Somme de contrôle Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Multipath TCP path-manager" -msgstr "Gestionnaire de chemins Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "Multipath TCP scheduler" -msgstr "Planificateur Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 -msgid "Multipath TCP version" -msgstr "Version de Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 -msgid "Netlink" -msgstr "Netlink" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." -msgstr "" -"Paramètres réseaux MPTCP. Visiter http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP pour de l'aide." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "One interface must be set as master" -msgstr "Une interface doit être configuré en temps que maître" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "Sortant :" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "Pointe :" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 -msgid "Re-create fullmesh subflows after a timeout" -msgstr "Recréer les sous-flux fullmesh après le délai d'expiration" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "Trafic temps réel" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 -msgid "Settings" -msgstr "Paramètres" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 -msgid "Test" -msgstr "Essai" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 -msgid "" -"The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" -msgstr "" -"Le nombre d'intervalles de retransmission au niveau de MPTCP sans trafic et " -"en attente de données sur un sous-flux requis pour le déclarer obsolète" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "Envoie :" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "En attente de la réponse de la commande..." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 -msgid "backup" -msgstr "remplaçant" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "default" -msgstr "Défaut" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 -msgid "disable" -msgstr "Désactive" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 -msgid "disabled" -msgstr "Désactivé" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 -msgid "enable" -msgstr "Active" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 -msgid "enabled" -msgstr "Activé" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kB/s" -msgstr "Ko/s" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kbit/s" -msgstr "kbit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 -msgid "master" -msgstr "maître" - -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 -msgid "All interfaces" -msgstr "Toutes les interfaces" - -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 -msgid "All interfaces – combined view" -msgstr "Toutes les interfaces - vue combinée" - -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 -msgid "All interfaces overlaid, inbound and outbound separately" -msgstr "Toutes les interfaces superposées, entrant et sortant séparés" - -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 -msgid "Average" -msgstr "Moyenne" - -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 -msgid "Current" -msgstr "Actuel" - #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 msgid "In" msgstr "Entrant" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 -msgid "Inbound – all interfaces" -msgstr "Entrant - toutes les interfaces" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 msgid "Inbound traffic" msgstr "Trafic entrant" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "Entrant - toutes les interfaces" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 +msgid "Interface" +msgstr "Interface" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 +msgid "Interfaces Settings" +msgstr "Paramètres des interfaces" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"Laisser vide pour simplement refléter l’interface Upload de cette ligne " +"vers la passerelle -- le même comportement \"le téléchargement suit " +"toujours l’envoi\" que mqvpn a déjà nativement." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 +msgid "MB/s" +msgstr "Mo/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 +msgid "MPTCP Support Check" +msgstr "Vérification du support MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 +msgid "MPTCP monitoring" +msgstr "Surveillance MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 +msgid "Multipath Debug" +msgstr "Débogage multipath" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "Multipath TCP" +msgstr "Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 +msgid "Multipath TCP SYN retries" +msgstr "Tentatives Multipath TCP SYN" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 +msgid "Multipath TCP checksum" +msgstr "Somme de contrôle Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Multipath TCP path-manager" +msgstr "Gestionnaire de chemins Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "Multipath TCP scheduler" +msgstr "Planificateur Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 +msgid "Multipath TCP version" +msgstr "Version de Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 +msgid "Netlink" +msgstr "Netlink" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 msgid "No multipath WAN interface is currently available." msgstr "Aucune interface WAN multipath n'est actuellement disponible." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "One interface must be set as master" +msgstr "Une interface doit être configuré en temps que maître" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"Seuls les WAN avec Multipath TCP activé (l’option « Multipath TCP » de la " +"section Configuration des interfaces de la page MPTCP) sont listés " +"ci-dessous." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 msgid "Out" msgstr "Sortant" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 -msgid "Outbound – all interfaces" -msgstr "Sortant - toutes les interfaces" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 msgid "Outbound traffic" msgstr "Trafic sortant" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "Sortant - toutes les interfaces" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 msgid "Peak" msgstr "Pointe" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Recréer les sous-flux fullmesh après le délai d'expiration" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 +msgid "Settings" +msgstr "Paramètres" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 +msgid "Test" +msgstr "Essai" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 @@ -381,6 +942,139 @@ msgstr "Total entrant" msgid "Total out" msgstr "Total sortant" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 +msgid "backup" +msgstr "remplaçant" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 +msgid "default" +msgstr "Défaut" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 +msgid "disable" +msgstr "Désactive" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 +msgid "disabled" +msgstr "Désactivé" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 +msgid "enable" +msgstr "Active" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 +msgid "enabled" +msgstr "Activé" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 +msgid "kB/s" +msgstr "Ko/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 +msgid "kbit/s" +msgstr "kbit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 +msgid "master" +msgstr "maître" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 @@ -388,19 +1082,31 @@ msgstr "Total sortant" msgid "minutes window, 1 second interval" msgstr "minutes de fenêtre, intervalle d'une seconde" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "Nombre de sous-flux ndiffports" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -"spécifie le nombre maximum de sous-options ADD_ADDR acceptées pour chaque " -"connexion MPTCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" @@ -408,6 +1114,65 @@ msgstr "" "spécifie le nombre maximum de sous-flux ADD_ADDR acceptées pour chaque " "connexion MPTCP" +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(fenêtre de %d minute, intervalle de %d seconde)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(fenêtre de %d minutes, intervalle de %d secondes)" + +#~ msgid "Average:" +#~ msgstr "Moyenne :" + +#~ msgid "Current:" +#~ msgstr "Actuellement :" + +#~ msgid "Download:" +#~ msgstr "Téléchargement :" + +#~ msgid "Inbound:" +#~ msgstr "Entrant :" + +#~ msgid "Loading" +#~ msgstr "Chargement" + +#~ msgid "" +#~ "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP for help." +#~ msgstr "" +#~ "Paramètres réseaux MPTCP. Visiter http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP pour de l'aide." + +#~ msgid "Outbound:" +#~ msgstr "Sortant :" + +#~ msgid "Peak:" +#~ msgstr "Pointe :" + +#~ msgid "Realtime Traffic" +#~ msgstr "Trafic temps réel" + +#~ msgid "" +#~ "The number of MPTCP-level retransmission intervals with no traffic and " +#~ "pending outstanding data on a given subflow required to declare it stale" +#~ msgstr "" +#~ "Le nombre d'intervalles de retransmission au niveau de MPTCP sans trafic " +#~ "et en attente de données sur un sous-flux requis pour le déclarer obsolète" + +#~ msgid "Upload:" +#~ msgstr "Envoie :" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "En attente de la réponse de la commande..." + +#~ msgid "" +#~ "specifies the maximum number of ADD_ADDR suboptions accepted for each " +#~ "MPTCP connection" +#~ msgstr "" +#~ "spécifie le nombre maximum de sous-options ADD_ADDR acceptées pour chaque " +#~ "connexion MPTCP" + #~ msgid "binder" #~ msgstr "lier" diff --git a/luci-app-mptcp/po/it/mptcp.po b/luci-app-mptcp/po/it/mptcp.po index 4e9f45f6d..52e27146b 100644 --- a/luci-app-mptcp/po/it/mptcp.po +++ b/luci-app-mptcp/po/it/mptcp.po @@ -12,355 +12,920 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(finestra di% d minuti, intervallo di% d secondi)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(finestra di% d minuti, intervallo di% d secondi)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "Media:" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 -msgid "Bandwidth" -msgstr "Larghezza banda" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 -msgid "Check if MPTCP between interface and server is working." -msgstr "Controlla se MPTCP tra l'interfaccia e il server funziona." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Congestion Control" -msgstr "Controllo della congestione" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 -msgid "Consecutive segments that should be sent for round robin" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "Corrente:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -#, fuzzy -msgid "Default is cubic" -msgstr "L'impostazione predefinita è bbr" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -#, fuzzy -msgid "Default is fullmesh" -msgstr "L'impostazione predefinita è bbr" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "Scarica:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 -msgid "Error" -msgstr "Errore" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 -msgid "Established connections" -msgstr "Connessioni stabilite" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 -msgid "Fill the congestion window on all subflows for round robin" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 -msgid "Fullmesh subflows for each pair of IP addresses" -msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" +msgstr "" -#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 -msgid "Grant UCI access for luci-app-mptcp" -msgstr "Concedi l'accesso UCI per luci-app-mptcp" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 msgid "" -"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " -"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " -"blocked." +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "In entrata:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 -msgid "Interface" -msgstr "Interfaccia" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 -msgid "Interfaces Settings" -msgstr "Impostazioni delle interfacce" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "Caricamento in corso" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 -msgid "MB/s" -msgstr "MB/s" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 -msgid "MPTCP" -msgstr "MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 -msgid "MPTCP Fullmesh" -msgstr "MPTCP Fullmesh" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 -msgid "MPTCP Support Check" -msgstr "Verifica supporto MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 -msgid "MPTCP monitoring" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 -msgid "Mbit/s" -msgstr "Mbit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 -msgid "Multipath Debug" -msgstr "Debug multipath" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "Multipath TCP" -msgstr "Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 -msgid "Multipath TCP SYN retries" -msgstr "Multipath TCP SYN riprova" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 -msgid "Multipath TCP checksum" -msgstr "Multipath TCP checksum" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Multipath TCP path-manager" -msgstr "Multipath TCP path-manager" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "Multipath TCP scheduler" -msgstr "Multipath TCP scheduler" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 -#, fuzzy -#| msgid "Multipath TCP" -msgid "Multipath TCP version" -msgstr "Multipath TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 -msgid "Netlink" -msgstr "Netlink" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "One interface must be set as master" -msgstr "Un'interfaccia deve essere impostata come master" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "Upload:" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "Picco:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 -msgid "Re-create fullmesh subflows after a timeout" -msgstr "Ricrea i flussi secondari fullmesh dopo un timeout" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "Traffico in tempo reale" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 -msgid "Settings" -msgstr "Impostazioni" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 -msgid "Test" -msgstr "Test" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 -msgid "" -"The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "Upload:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "In attesa del completamento del comando ..." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 -msgid "backup" -msgstr "backup" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "default" -msgstr "predefinito" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 -msgid "disable" -msgstr "disabilita" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 -msgid "disabled" -msgstr "disabilitato" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 -msgid "enable" -msgstr "Attivare" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 -msgid "enabled" -msgstr "Abilitato" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kB/s" -msgstr "kB/s" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kbit/s" -msgstr "kbit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 -msgid "master" -msgstr "Principale" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 msgid "All interfaces" msgstr "Tutte le interfacce" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 +msgid "All interfaces overlaid, inbound and outbound separately" +msgstr "" +"Tutte le interfacce sovrapposte, traffico in entrata e in uscita separato" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 msgid "All interfaces – combined view" msgstr "Tutte le interfacce - vista combinata" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 -msgid "All interfaces overlaid, inbound and outbound separately" -msgstr "Tutte le interfacce sovrapposte, traffico in entrata e in uscita separato" - #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 msgid "Average" msgstr "Media" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 +msgid "Bandwidth" +msgstr "Larghezza banda" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 +msgid "Check if MPTCP between interface and server is working." +msgstr "Controlla se MPTCP tra l'interfaccia e il server funziona." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Congestion Control" +msgstr "Controllo della congestione" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 msgid "Current" msgstr "Attuale" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +#, fuzzy +msgid "Default is cubic" +msgstr "L'impostazione predefinita è bbr" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +#, fuzzy +msgid "Default is fullmesh" +msgstr "L'impostazione predefinita è bbr" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 +msgid "Error" +msgstr "Errore" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 +msgid "Established connections" +msgstr "Connessioni stabilite" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "Concedi l'accesso UCI per luci-app-mptcp" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 msgid "In" msgstr "Entrata" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 -msgid "Inbound – all interfaces" -msgstr "Entrata - tutte le interfacce" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 msgid "Inbound traffic" msgstr "Traffico in entrata" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "Entrata - tutte le interfacce" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 +msgid "Interface" +msgstr "Interfaccia" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 +msgid "Interfaces Settings" +msgstr "Impostazioni delle interfacce" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"Lasciare vuoto per limitarsi a rispecchiare l’interfaccia Upload di questa " +"riga verso il gateway -- lo stesso comportamento \"il download segue sempre " +"l’upload\" che mqvpn ha già integrato nativamente." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 +msgid "MB/s" +msgstr "MB/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 +msgid "MPTCP Support Check" +msgstr "Verifica supporto MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 +msgid "Multipath Debug" +msgstr "Debug multipath" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "Multipath TCP" +msgstr "Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 +msgid "Multipath TCP SYN retries" +msgstr "Multipath TCP SYN riprova" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 +msgid "Multipath TCP checksum" +msgstr "Multipath TCP checksum" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Multipath TCP path-manager" +msgstr "Multipath TCP path-manager" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "Multipath TCP scheduler" +msgstr "Multipath TCP scheduler" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 +#, fuzzy +msgid "Multipath TCP version" +msgstr "Multipath TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 +msgid "Netlink" +msgstr "Netlink" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 msgid "No multipath WAN interface is currently available." msgstr "Nessuna interfaccia WAN multipath e attualmente disponibile." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "One interface must be set as master" +msgstr "Un'interfaccia deve essere impostata come master" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"Sono elencate qui sotto solo le WAN con Multipath TCP abilitato (l’opzione " +"“Multipath TCP” nella sezione Impostazioni interfacce della pagina MPTCP)." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 msgid "Out" msgstr "Uscita" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 -msgid "Outbound – all interfaces" -msgstr "Uscita - tutte le interfacce" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 msgid "Outbound traffic" msgstr "Traffico in uscita" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "Uscita - tutte le interfacce" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 msgid "Peak" msgstr "Picco" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Ricrea i flussi secondari fullmesh dopo un timeout" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 +msgid "Settings" +msgstr "Impostazioni" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 +msgid "Test" +msgstr "Test" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 @@ -375,6 +940,139 @@ msgstr "Totale in entrata" msgid "Total out" msgstr "Totale in uscita" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 +msgid "backup" +msgstr "backup" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 +msgid "default" +msgstr "predefinito" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 +msgid "disable" +msgstr "disabilita" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 +msgid "disabled" +msgstr "disabilitato" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 +msgid "enable" +msgstr "Attivare" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 +msgid "enabled" +msgstr "Abilitato" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 +msgid "kB/s" +msgstr "kB/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 +msgid "kbit/s" +msgstr "kbit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 +msgid "master" +msgstr "Principale" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 @@ -382,22 +1080,72 @@ msgstr "Totale in uscita" msgid "minutes window, 1 second interval" msgstr "finestra in minuti, intervallo di 1 secondo" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "ndiffports subflows number" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" msgstr "" +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(finestra di% d minuti, intervallo di% d secondi)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(finestra di% d minuti, intervallo di% d secondi)" + +#~ msgid "Average:" +#~ msgstr "Media:" + +#~ msgid "Current:" +#~ msgstr "Corrente:" + +#~ msgid "Download:" +#~ msgstr "Scarica:" + +#~ msgid "Inbound:" +#~ msgstr "In entrata:" + +#~ msgid "Loading" +#~ msgstr "Caricamento in corso" + +#~ msgid "Outbound:" +#~ msgstr "Upload:" + +#~ msgid "Peak:" +#~ msgstr "Picco:" + +#~ msgid "Realtime Traffic" +#~ msgstr "Traffico in tempo reale" + +#~ msgid "Upload:" +#~ msgstr "Upload:" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "In attesa del completamento del comando ..." + #~ msgid "BLEST" #~ msgstr "BLEST" diff --git a/luci-app-mptcp/po/oc/mptcp.po b/luci-app-mptcp/po/oc/mptcp.po index f9bd5bda5..46d5ade12 100644 --- a/luci-app-mptcp/po/oc/mptcp.po +++ b/luci-app-mptcp/po/oc/mptcp.po @@ -10,319 +10,1149 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(fenèstra de %d minuta,interval de %d segonda)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(fenèstra de %d minutas,interval de %d segondas)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "Mejana :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" +msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 +msgid "" +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 +msgid "All interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 +msgid "All interfaces overlaid, inbound and outbound separately" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 +msgid "Average" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 msgid "Bandwidth" msgstr "Benda passanta" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 msgid "Check if MPTCP between interface and server is working." msgstr "Verificar se MPTCP entre l‘interfàcia e lo servidor fonciona." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 msgid "Congestion Control" msgstr "Contraròtle de congestion" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 msgid "Consecutive segments that should be sent for round robin" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "Actualament :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 +msgid "Current" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 #, fuzzy msgid "Default is cubic" msgstr "Per defaut bbr" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 #, fuzzy msgid "Default is fullmesh" msgstr "Per defaut bbr" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "Telecargament :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 msgid "Error" msgstr "Error" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 msgid "Established connections" msgstr "Connexions establidas" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 msgid "Fill the congestion window on all subflows for round robin" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Jos flux Fullmesh per cada parelh d’adreças IP" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + #: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 msgid "Grant UCI access for luci-app-mptcp" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 msgid "" "If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " "MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " "blocked." msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "Dintrant :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 +msgid "In" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 +msgid "Inbound traffic" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 msgid "Interface" msgstr "Interfàcia" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 msgid "Interfaces Settings" msgstr "Paramètres de las interfàcias" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "Cargament" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"Daissatz void per simplament miralhar l’interfàcia Upload d’aquesta linha " +"cap a la passarèla -- lo meteis compòrtament \"lo telecargament seguís " +"totjorn l’mandadís\" que mqvpn a ja integrat nativament." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 msgid "MB/s" msgstr "Mo/s" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 #: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 msgid "MPTCP" msgstr "MPTCP" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 msgid "MPTCP Fullmesh" msgstr "MPTCP Fullmesh" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 msgid "MPTCP Support Check" msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 msgid "MPTCP monitoring" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 msgid "Mbit/s" msgstr "Mbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 msgid "Multipath Debug" msgstr "Desbugatge multipath" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 msgid "Multipath TCP SYN retries" msgstr "Ensages Multipath TCP SYN" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 msgid "Multipath TCP checksum" msgstr "Sòma de contraròtle Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 msgid "Multipath TCP path-manager" msgstr "Gestionari dels camins Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 msgid "Multipath TCP scheduler" msgstr "Planificator Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 #, fuzzy -#| msgid "Multipath TCP" msgid "Multipath TCP version" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 msgid "Netlink" msgstr "Ligam ret" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." msgstr "" -"Paramètres ret MPTCP. Consulatz http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP per d’ajuda." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 +msgid "No multipath WAN interface is currently available." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 msgid "One interface must be set as master" msgstr "Una interfàcia deu èsser configurada coma principala" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "Sortent :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"Solament los WAN amb Multipath TCP activat (l’opcion « Multipath TCP » de " +"la seccion Configuracion de las interfàcias de la pagina MPTCP) son listats " +"çai-jós." -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "Punta :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 +msgid "Out" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 +msgid "Outbound traffic" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 +msgid "Peak" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 msgid "Re-create fullmesh subflows after a timeout" msgstr "Tornar crear los jos-flus fullmesh aprèp lo relambi d’expiracion" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "Trafic dirèct" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 msgid "Settings" msgstr "Paramètres" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 msgid "Test" msgstr "Pròva" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 msgid "" "The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "Mandadís :" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "En espèra d’una responsa de la comanda..." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 +msgid "Total" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:404 +msgid "Total in" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:408 +msgid "Total out" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 msgid "backup" msgstr "subordinat" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 msgid "default" msgstr "Defaut" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 msgid "disable" msgstr "desactivar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 msgid "disabled" msgstr "desactivat" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 msgid "enable" msgstr "Activar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 msgid "enabled" msgstr "Activat" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 msgid "kB/s" msgstr "kB/s" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 msgid "master" msgstr "màger" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:674 +msgid "minutes window, 1 second interval" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "Nombre de jos-flux ndiffports" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" msgstr "" +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(fenèstra de %d minuta,interval de %d segonda)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(fenèstra de %d minutas,interval de %d segondas)" + +#~ msgid "Average:" +#~ msgstr "Mejana :" + +#~ msgid "Current:" +#~ msgstr "Actualament :" + +#~ msgid "Download:" +#~ msgstr "Telecargament :" + +#~ msgid "Inbound:" +#~ msgstr "Dintrant :" + +#~ msgid "Loading" +#~ msgstr "Cargament" + +#~ msgid "" +#~ "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP for help." +#~ msgstr "" +#~ "Paramètres ret MPTCP. Consulatz http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP per d’ajuda." + +#~ msgid "Outbound:" +#~ msgstr "Sortent :" + +#~ msgid "Peak:" +#~ msgstr "Punta :" + +#~ msgid "Realtime Traffic" +#~ msgstr "Trafic dirèct" + +#~ msgid "Upload:" +#~ msgstr "Mandadís :" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "En espèra d’una responsa de la comanda..." + #, fuzzy #~ msgid "BLEST" #~ msgstr "BLEST" diff --git a/luci-app-mptcp/po/ru/mptcp.po b/luci-app-mptcp/po/ru/mptcp.po index ddacab82c..3a56f286f 100644 --- a/luci-app-mptcp/po/ru/mptcp.po +++ b/luci-app-mptcp/po/ru/mptcp.po @@ -11,81 +11,381 @@ msgstr "" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.6.1\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(% d минутное окно,% d секундный интервал)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(% d минутное окно,% d секундный интервал)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "Среднее:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" +msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 +msgid "" +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 +msgid "All interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 +msgid "All interfaces overlaid, inbound and outbound separately" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 +msgid "Average" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 msgid "Bandwidth" msgstr "Пропускная способность" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 msgid "Check if MPTCP between interface and server is working." msgstr "Проверьте, работает ли MPTCP между интерфейсом и сервером." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 msgid "Congestion Control" msgstr "Контроль перегрузки" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 msgid "Consecutive segments that should be sent for round robin" msgstr "Последовательные сегменты, которые следует отправлять для round-robin" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "Текущая:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 +msgid "Current" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 msgid "Default is cubic" msgstr "По умолчанию кубический" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 msgid "Default is fullmesh" msgstr "По умолчанию - fullmesh" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "Загрузка:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 msgid "Error" msgstr "Ошибка" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 msgid "Established connections" msgstr "Установленные соединения" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 msgid "Fill the congestion window on all subflows for round robin" msgstr "Заполнение окна перегрузки для всех подпотоков для round-robin" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Подпотоки Fullmesh для каждой пары IP-адресов" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + #: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 msgid "Grant UCI access for luci-app-mptcp" msgstr "Предоставить доступ UCI для luci-app-mptcp" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 msgid "" "If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " "MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " @@ -94,235 +394,777 @@ msgstr "" "Если в конце вы получите «TCPOptionMPTCPCapable [...] Sender's Key», то " "MPTCP поддерживается. Если \"-TCPOptionMPTCPCapable\", то MPTCP заблокирован." -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "Входящий:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 +msgid "In" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 +msgid "Inbound traffic" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 msgid "Interface" msgstr "Интерфейс" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 msgid "Interfaces Settings" msgstr "Настройки интерфейсов" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "Загрузка" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"Оставьте пустым, чтобы просто отразить интерфейс Upload этой строки на " +"шлюз -- то же поведение \"скачивание всегда следует за отправкой\", которое " +"уже встроено в mqvpn." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 msgid "MB/s" msgstr "MB/s" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 #: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 msgid "MPTCP" msgstr "MPTCP" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 msgid "MPTCP Fullmesh" msgstr "MPTCP Fullmesh" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 msgid "MPTCP Support Check" msgstr "Проверка поддержки MPTCP" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 msgid "MPTCP monitoring" msgstr "Мониторинг MPTCP" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 msgid "Mbit/s" msgstr "Mbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 msgid "Multipath Debug" msgstr "Многоуровневая отладка" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 msgid "Multipath TCP" msgstr "Многопоточный TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 msgid "Multipath TCP SYN retries" msgstr "Попытки многопоточной TCP SYN" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 msgid "Multipath TCP checksum" msgstr "Контрольная сумма многопоточного TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 msgid "Multipath TCP path-manager" msgstr "Многопоточный TCP менеджер" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 msgid "Multipath TCP scheduler" msgstr "Планировщик многопоточного TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 #, fuzzy -#| msgid "Multipath TCP" msgid "Multipath TCP version" msgstr "Многопоточный TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 msgid "Netlink" msgstr "Netlink" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." msgstr "" -"Настройки сети MPTCP. Посетите http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP для справки." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 +msgid "No multipath WAN interface is currently available." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 msgid "One interface must be set as master" msgstr "Один интерфейс должен быть установлен как главный" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "Отправка:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"Ниже перечислены только WAN с включённым Multipath TCP (опция «Multipath " +"TCP» в разделе «Настройки интерфейсов» страницы MPTCP)." -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "Пиковое значение:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 +msgid "Out" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 +msgid "Outbound traffic" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 +msgid "Peak" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 msgid "Re-create fullmesh subflows after a timeout" msgstr "Повторно создать подпотоки fullmesh после тайм-аута" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "Трафик в реальном времени" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 msgid "Settings" msgstr "Настройки" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 msgid "Test" msgstr "Тест" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 msgid "" "The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." msgstr "" -"Количество интервалов повторной передачи MPTCP без трафика и с ожидающими данными на заданном подпотоке, необходимых для его объявления устаревшим" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "Отправка:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "Ожидание завершения команды..." +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 +msgid "Total" +msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:404 +msgid "Total in" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:408 +msgid "Total out" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 msgid "backup" msgstr "Резервирование" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 msgid "default" msgstr "По умолчанию" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 msgid "disable" msgstr "отключить" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 msgid "disabled" msgstr "отключить" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 msgid "enable" msgstr "включить" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 msgid "enabled" msgstr "Установлено" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 msgid "kB/s" msgstr "kB/s" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 msgid "master" msgstr "мастер" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:674 +msgid "minutes window, 1 second interval" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "количество подпотоков ndiffports" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -"задаёт максимальное количество подопций ADD_ADDR, принимаемых для каждого соединения MPTCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" msgstr "" -"задаёт максимальное количество дополнительных подпотоков, разрешённых для каждого соединения MPTCP" +"задаёт максимальное количество дополнительных подпотоков, разрешённых для " +"каждого соединения MPTCP" + +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(% d минутное окно,% d секундный интервал)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(% d минутное окно,% d секундный интервал)" + +#~ msgid "Average:" +#~ msgstr "Среднее:" + +#~ msgid "Current:" +#~ msgstr "Текущая:" + +#~ msgid "Download:" +#~ msgstr "Загрузка:" + +#~ msgid "Inbound:" +#~ msgstr "Входящий:" + +#~ msgid "Loading" +#~ msgstr "Загрузка" + +#~ msgid "" +#~ "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP for help." +#~ msgstr "" +#~ "Настройки сети MPTCP. Посетите http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP для справки." + +#~ msgid "Outbound:" +#~ msgstr "Отправка:" + +#~ msgid "Peak:" +#~ msgstr "Пиковое значение:" + +#~ msgid "Realtime Traffic" +#~ msgstr "Трафик в реальном времени" + +#~ msgid "" +#~ "The number of MPTCP-level retransmission intervals with no traffic and " +#~ "pending outstanding data on a given subflow required to declare it stale" +#~ msgstr "" +#~ "Количество интервалов повторной передачи MPTCP без трафика и с ожидающими " +#~ "данными на заданном подпотоке, необходимых для его объявления устаревшим" + +#~ msgid "Upload:" +#~ msgstr "Отправка:" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "Ожидание завершения команды..." + +#~ msgid "" +#~ "specifies the maximum number of ADD_ADDR suboptions accepted for each " +#~ "MPTCP connection" +#~ msgstr "" +#~ "задаёт максимальное количество подопций ADD_ADDR, принимаемых для каждого " +#~ "соединения MPTCP" diff --git a/luci-app-mptcp/po/templates/mptcp.pot b/luci-app-mptcp/po/templates/mptcp.pot index d53508f13..3107b03d7 100644 --- a/luci-app-mptcp/po/templates/mptcp.pot +++ b/luci-app-mptcp/po/templates/mptcp.pot @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: luci-app-mptcp\n" -"POT-Creation-Date: 2026-04-10 00:00+0000\n" -"PO-Revision-Date: 2026-04-10 00:00+0000\n" +"POT-Creation-Date: 2026-08-16 00:00+0000\n" +"PO-Revision-Date: 2026-08-16 00:00+0000\n" "Last-Translator: \n" "Language-Team: \n" "Language: en\n" @@ -10,351 +10,911 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 -msgid "Bandwidth" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 -msgid "Check if MPTCP between interface and server is working." -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Congestion Control" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 -msgid "Consecutive segments that should be sent for round robin" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Default is cubic" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Default is fullmesh" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 -msgid "Error" -msgstr "" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 -msgid "Established connections" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 -msgid "Fill the congestion window on all subflows for round robin" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 -msgid "Fullmesh subflows for each pair of IP addresses" -msgstr "" - -#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 -msgid "Grant UCI access for luci-app-mptcp" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 msgid "" -"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " -"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " -"blocked." +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 -msgid "Interface" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 -msgid "Interfaces Settings" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 -msgid "MB/s" -msgstr "" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 -msgid "MPTCP" -msgstr "" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 -msgid "MPTCP Fullmesh" -msgstr "" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 -msgid "MPTCP Support Check" -msgstr "" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 -msgid "MPTCP monitoring" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 -msgid "Mbit/s" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 -msgid "Multipath Debug" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "Multipath TCP" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 -msgid "Multipath TCP SYN retries" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 -msgid "Multipath TCP checksum" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Multipath TCP path-manager" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "Multipath TCP scheduler" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 -msgid "Multipath TCP version" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 -msgid "Netlink" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "One interface must be set as master" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 -msgid "Re-create fullmesh subflows after a timeout" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" msgstr "" -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 -msgid "Settings" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 -msgid "Test" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 -msgid "" -"The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 -msgid "backup" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "default" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 -msgid "disable" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 -msgid "disabled" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 -msgid "enable" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 -msgid "enabled" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kB/s" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kbit/s" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 -msgid "master" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 msgid "All interfaces" msgstr "" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 -msgid "All interfaces – combined view" -msgstr "" - #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 msgid "All interfaces overlaid, inbound and outbound separately" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 msgid "Average" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 +msgid "Bandwidth" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 +msgid "Check if MPTCP between interface and server is working." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Congestion Control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 msgid "Current" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Default is cubic" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Default is fullmesh" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 +msgid "Error" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 +msgid "Established connections" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 msgid "In" msgstr "" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 -msgid "Inbound – all interfaces" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 msgid "Inbound traffic" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 +msgid "Interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 +msgid "Interfaces Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 +msgid "MB/s" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 +msgid "MPTCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 +msgid "MPTCP Fullmesh" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 +msgid "MPTCP Support Check" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 +msgid "Mbit/s" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 +msgid "Multipath Debug" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "Multipath TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 +msgid "Multipath TCP SYN retries" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 +msgid "Multipath TCP checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Multipath TCP path-manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "Multipath TCP scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 +msgid "Multipath TCP version" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 +msgid "Netlink" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 msgid "No multipath WAN interface is currently available." msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "One interface must be set as master" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 msgid "Out" msgstr "" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 -msgid "Outbound – all interfaces" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 msgid "Outbound traffic" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 msgid "Peak" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 +msgid "Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 +msgid "Test" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 @@ -369,6 +929,139 @@ msgstr "" msgid "Total out" msgstr "" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 +msgid "backup" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 +msgid "default" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 +msgid "disable" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 +msgid "disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 +msgid "enable" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 +msgid "enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 +msgid "kB/s" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 +msgid "kbit/s" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 +msgid "master" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 @@ -376,17 +1069,31 @@ msgstr "" msgid "minutes window, 1 second interval" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 msgid "ndiffports subflows number" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 msgid "" "specifies the maximum number of additional subflows allowed for each MPTCP " "connection" diff --git a/luci-app-mptcp/po/zh_Hans/mptcp.po b/luci-app-mptcp/po/zh_Hans/mptcp.po index 044629688..4409fb983 100644 --- a/luci-app-mptcp/po/zh_Hans/mptcp.po +++ b/luci-app-mptcp/po/zh_Hans/mptcp.po @@ -10,371 +10,917 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Weblate 4.10.1\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 -msgid "(%d minute window, %d second interval)" -msgstr "(%d 分钟刷新, %d 秒钟刷新)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 -msgid "(%d minutes window, %d seconds interval)" -msgstr "(%d 分钟间隔, %d 秒钟刷新)" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 -msgid "Average:" -msgstr "平均:" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 -msgid "Bandwidth" -msgstr "带宽" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 -msgid "Check if MPTCP between interface and server is working." -msgstr "检查接口和服务器之间的MPTCP是否正常工作." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Congestion Control" -msgstr "阻塞控制" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:97 -msgid "Consecutive segments that should be sent for round robin" -msgstr "连续轮播应发送的连续段" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 -msgid "Current:" -msgstr "实时:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 -msgid "Default is cubic" -msgstr "默认设置 cubic" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Default is fullmesh" -msgstr "默认设置fullmesh" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 -msgid "Download:" -msgstr "下载:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 -msgid "Error" -msgstr "错误" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 -msgid "Established connections" -msgstr "建立的连接" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:91 -msgid "Fill the congestion window on all subflows for round robin" -msgstr "在循环的所有子流上填充拥塞窗口" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:74 -msgid "Fullmesh subflows for each pair of IP addresses" -msgstr "每对IP地址的全网格子流" - -#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 -msgid "Grant UCI access for luci-app-mptcp" -msgstr "授予UCI访问luci-app-mptcp的权限" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 -msgid "" -"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " -"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " -"blocked." -msgstr "如果您在末尾获得“TCPOptionMPTCPCapable [...] Sender 's Key” ,则支持MPTCP" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 -msgid "Inbound:" -msgstr "入站:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 -msgid "Interface" -msgstr "接口" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:104 -msgid "Interfaces Settings" -msgstr "网卡设置" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Loading" -msgstr "载入中" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 -msgid "MB/s" -msgstr "MB/s" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 -msgid "MPTCP" -msgstr "MPTCP" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 -msgid "MPTCP Fullmesh" -msgstr "设置MPTCP全网" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 -msgid "MPTCP Support Check" -msgstr "MPTCP支持检查" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 -msgid "MPTCP monitoring" -msgstr "MPTCP监控" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 -msgid "Mbit/s" -msgstr "Mbit/s" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 -msgid "Multipath Debug" -msgstr "Multipath 调试" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "Multipath TCP" -msgstr "多路径TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:42 -msgid "Multipath TCP SYN retries" -msgstr "多路径 TCP SYN 重试" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 -msgid "Multipath TCP checksum" -msgstr "多路径TCP校验和" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 -msgid "Multipath TCP path-manager" -msgstr "多路径TCP路径管理器" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "Multipath TCP scheduler" -msgstr "多路径TCP调度程序" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 -#, fuzzy -msgid "Multipath TCP version" -msgstr "多路径TCP" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:28 -msgid "Netlink" -msgstr "网络链接" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 -msgid "" -"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" -"ConfigureMPTCP for help." -msgstr "" -"网络MPTCP设置. 访问http://multipath-tcp.org/pmwiki.php/Users/ConfigureMPTCP4 获取更多的支持." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:108 -msgid "One interface must be set as master" -msgstr "必须设置一个网卡为主接口" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 -msgid "Outbound:" -msgstr "出站:" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 -msgid "Peak:" -msgstr "峰值:" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 -msgid "Re-create fullmesh subflows after a timeout" -msgstr "超时后重新创建全网格子流" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 -msgid "Realtime Traffic" -msgstr "实时流量" - -#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 -msgid "Settings" -msgstr "设置" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 -msgid "Test" -msgstr "测试" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 -msgid "" -"The number of MPTCP-level retransmission intervals with no traffic and " -"pending outstanding data on a given subflow required to declare it stale" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:26 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:27 +msgid "(no output)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 -msgid "Upload:" -msgstr "上传:" - -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 -#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 -msgid "Waiting for command to complete..." -msgstr "等待命令完成..." - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:112 -msgid "backup" -msgstr "备份" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "default" -msgstr "默认" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:82 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:93 -msgid "disable" -msgstr "禁用" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:110 -msgid "disabled" -msgstr "禁用" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:81 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:92 -msgid "enable" -msgstr "启用" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:109 -msgid "enabled" -msgstr "启用" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kB/s" -msgstr "kB/秒" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 -msgid "kbit/s" -msgstr "kbit/秒" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:111 -msgid "master" -msgstr "主" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:85 -msgid "ndiffports subflows number" -msgstr "ndiffports子流数" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 -msgid "" -"specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP " -"connection" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:45 +msgid "-- not pinned --" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:133 +msgid "0" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:134 +msgid "1" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 msgid "" -"specifies the maximum number of additional subflows allowed for each MPTCP " -"connection" +"A weight >100 make it more attractive, a weight <100 make it less " +"attractive. Max 256" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:171 +msgid "" +"A weight >100 makes a WAN more attractive, a weight <100 makes it less " +"attractive. Max 256." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:73 +msgid "ADD_ADDR echo failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:71 +msgid "ADD_ADDR echo received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:72 +msgid "ADD_ADDR echo sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:74 +msgid "ADD_ADDR received with a port number" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:70 +msgid "ADD_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:69 +msgid "ADD_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:67 +msgid "ADD_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:68 +msgid "ADD_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:262 +msgid "Accepted ADD_ADDR limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:259 +msgid "Add-addr timeout (s)" msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:326 msgid "All interfaces" msgstr "所有接口" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 -msgid "All interfaces – combined view" -msgstr "所有接口 – 合并视图" - #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:457 msgid "All interfaces overlaid, inbound and outbound separately" msgstr "所有接口叠加显示,入站与出站分开" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:456 +msgid "All interfaces – combined view" +msgstr "所有接口 – 合并视图" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:615 msgid "Average" msgstr "平均" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "BPF schedulers (not available on all platforms):" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:47 +msgid "Bandwidth" +msgstr "带宽" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:61 +msgid "Blackhole detected on the path" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "Blackhole timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:258 +msgid "Blackhole timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:13 +msgid "CS0 (0) - Best effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:14 +msgid "CS1 (8) - Low priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:15 +msgid "CS2 (16) - High priority" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:16 +msgid "CS3 (24) - SIP/signaling" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:17 +msgid "CS4 (32) - Real-time interactive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:18 +msgid "CS5 (40) - Broadcast video" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:19 +msgid "CS6 (48) - Network control" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:20 +msgid "CS7 (56) - Latency sensitive" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:48 +msgid "Check if MPTCP between interface and server is working." +msgstr "检查接口和服务器之间的MPTCP是否正常工作." + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:256 +msgid "Checksum" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:109 +msgid "" +"Choose which WAN carries each DSCP-tagged traffic class -- for the MPTCP " +"bpf_dscp scheduler and for mqvpn -- and review the per-WAN weight used by " +"the *weight schedulers on both. This page only edits the pins/weights; pick " +"the scheduler that actually uses them on the MPTCP and MQVPN pages " +"themselves." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "Close timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:260 +msgid "Close timeout (s)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Congestion Control" +msgstr "阻塞控制" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:277 +msgid "Consecutive segments that should be sent for round robin" +msgstr "连续轮播应发送的连续段" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "Control message timeout" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:23 +msgid "Could not allocate an MPTCP token, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:104 +msgid "Couldn't fall back to TCP (connection state didn't allow it)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Counter" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:611 msgid "Current" msgstr "当前" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:108 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:36 +msgid "DSCP / Weight Routing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:139 +msgid "DSCP class" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:134 +msgid "DSCP class pins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:48 +msgid "DSS corruption detected, fell back to plain TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:49 +msgid "DSS corruption detected, subflow reset" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:53 +msgid "Data checksum errors" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:86 +msgid "Data mapping failures received (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:85 +msgid "Data mapping failures sent (MP_FAIL)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:50 +msgid "Data sequence mapping did not match TCP sequence numbers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:47 +msgid "Data sequence mapping did not match the previous one" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:138 +msgid "Default is cubic" +msgstr "默认设置 cubic" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Default is fullmesh" +msgstr "默认设置fullmesh" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:211 +msgid "Device" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:25 +msgid "Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:244 +msgid "Disabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:151 +msgid "Download interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:55 +msgid "Duplicate data segments discarded" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:34 +msgid "EF (46) - Voice" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:177 +msgid "Enable MPTCPd" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:243 +msgid "Enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:214 +msgid "Endpoint flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:72 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:74 +msgid "Error" +msgstr "错误" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:28 +msgid "Error fetching connections data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:28 +msgid "Error fetching fullmesh data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:29 +msgid "Error fetching monitor data." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:99 +msgid "Established MPTCP connections (current)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:263 +msgid "Established MPTCP connections (right now)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:58 +msgid "Established connections" +msgstr "建立的连接" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:19 +msgid "Fallback to TCP (ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:18 +msgid "Fallback to TCP (SYN/ACK stripped)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:88 +msgid "Fastclose received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:87 +msgid "Fastclose sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:102 +msgid "Fell back to TCP: bad or missing data sequence signal" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:101 +msgid "Fell back to TCP: conflicting TCP MD5SIG option" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:100 +msgid "Fell back to TCP: missing data on first established packet" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:103 +msgid "Fell back to TCP: simultaneous connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:271 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "在循环的所有子流上填充拥塞窗口" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:171 +msgid "Force Multipath configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:254 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "每对IP地址的全网格子流" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:152 +msgid "" +"Gateway (VPS) → router. Only takes effect for MPTCP’s bpf_dscp scheduler " +"(pins the VPS’s own send-side choice via dscp_remote_id) and can be a " +"different WAN than Upload." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:124 +msgid "Gateway sync" +msgstr "" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "授予UCI访问luci-app-mptcp的权限" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:150 +msgid "" +"Helps explain why MPTCP might not be aggregating your WANs correctly: " +"fallback to plain TCP, blackholed/stale subflows, resets, checksum errors, " +"and WANs that never got an MPTCP endpoint registered at all. Refreshes " +"automatically every 15 seconds." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:60 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" +"如果您在末尾获得“TCPOptionMPTCPCapable [...] Sender 's Key” ,则支持MPTCP" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:693 msgid "In" msgstr "入站" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 -msgid "Inbound – all interfaces" -msgstr "入站 – 所有接口" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:248 +msgid "In-kernel" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:151 +msgid "In-kernel path manager" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:634 msgid "Inbound traffic" msgstr "入站流量" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:462 +msgid "Inbound – all interfaces" +msgstr "入站 – 所有接口" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:52 +msgid "Infinite mapping received (peer fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:51 +msgid "Infinite mapping sent (fell back to plain TCP semantics)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:165 +msgid "Initial MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:238 +msgid "" +"Initial time period in second to disable MPTCP on active MPTCP sockets when " +"a MPTCP firewall blackhole issue happens. This time period will grow " +"exponentially when more blackhole issues get detected right after MPTCP is " +"re-enabled and will reset to the initial value when the blackhole issue goes " +"away." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:52 +msgid "Interface" +msgstr "接口" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:284 +msgid "Interfaces Settings" +msgstr "网卡设置" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:36 +msgid "JOIN ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:34 +msgid "JOIN SYN/ACK authentication failures" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:37 +msgid "JOIN attempts with unknown token" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:38 +msgid "JOIN request rejected by the path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:265 +msgid "Kernel MPTCP configuration" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:21 +msgid "LE (1) - Lower effort" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:170 +msgid "Last updated:" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:153 +msgid "" +"Leave empty to just mirror this row’s Upload interface to the gateway " +"instead -- the same \"download always follows upload\" behavior mqvpn " +"already has built in natively." +msgstr "" +"留空则只是把本行的上传接口镜像到网关 -- 与 mqvpn 原生自带的\"下载始终跟随上传" +"\"行为相同。" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:75 +msgid "MB/s" +msgstr "MB/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:14 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:148 +msgid "MPTCP Diagnostics" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:142 +msgid "MPTCP Established connections" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:69 +msgid "MPTCP Fullmesh" +msgstr "设置MPTCP全网" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:141 +msgid "MPTCP Fullmesh (subflow map)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:140 +msgid "MPTCP Settings" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:46 +msgid "MPTCP Support Check" +msgstr "MPTCP支持检查" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:253 +msgid "MPTCP enabled" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:213 +msgid "MPTCP endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:16 +msgid "MPTCP handshake accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:15 +msgid "MPTCP handshake attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:14 +msgid "MPTCP handshake attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:17 +msgid "MPTCP handshake completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:21 +msgid "MPTCP handshake disabled client-side after past issues" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:20 +msgid "MPTCP handshake dropped client-side, fell back to TCP" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:277 +msgid "MPTCP kernel counters (since boot)" +msgstr "" + +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:80 +msgid "MPTCP monitoring" +msgstr "MPTCP监控" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:143 +msgid "MPTCP monitoring (raw kernel counters)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:22 +msgid "MPTCP rejected on a port-only endpoint" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:90 +msgid "MPTCP resets received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:89 +msgid "MPTCP resets sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:46 +msgid "MPTCP-level retransmissions" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:105 +msgid "MPTCP-level zero-window probes" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:205 +msgid "MPTCPd Address annoucement flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:212 +msgid "MPTCPd Address notification flags" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:183 +msgid "MPTCPd path managers" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:194 +msgid "MPTCPd plugins" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "Max add address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "Max subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:77 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:117 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:126 +msgid "Mirror DSCP/weight pins to gateway" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:212 +msgid "Mode" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:60 +msgid "Multipath Debug" +msgstr "Multipath 调试" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:50 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "Multipath TCP" +msgstr "多路径TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:126 +msgid "Multipath TCP SYN retries" +msgstr "多路径 TCP SYN 重试" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:55 +msgid "Multipath TCP checksum" +msgstr "多路径TCP校验和" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:65 +msgid "Multipath TCP path-manager" +msgstr "多路径TCP路径管理器" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:75 +msgid "Multipath TCP scheduler" +msgstr "多路径TCP调度程序" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:132 +#, fuzzy +msgid "Multipath TCP version" +msgstr "多路径TCP" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:72 +msgid "Netlink" +msgstr "网络链接" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:46 +msgid "Networks MPTCP settings." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:279 +msgid "No counters available (nstat/multipath -m returned nothing)." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:26 +msgid "No data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:184 +msgid "No diagnostic data available yet." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:394 msgid "No multipath WAN interface is currently available." msgstr "当前没有可用的多路径 WAN 接口。" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:205 +msgid "No multipath-enabled WAN interfaces found." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:112 +msgid "" +"Nothing to show yet: no DSCP scheduler (bpf_dscp) or weight scheduler " +"(bpf_weight/bpf_weight_rr/bpf_burstweight, or mqvpn’s Weighted RTT/Weighted " +"Round Robin) is currently selected on the MPTCP or MQVPN pages." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:289 +msgid "One interface must be set as master" +msgstr "必须设置一个网卡为主接口" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:165 +msgid "" +"Only WANs with Multipath TCP enabled (the “Multipath TCP” option on the " +"MPTCP page’s Interfaces Settings) are listed below." +msgstr "" +"下面仅列出已启用 Multipath TCP 的 WAN(即 MPTCP 页面“接口设置”中的“Multipath " +"TCP”选项)。" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +msgid "" +"Only used by *weight schedulers/path managers. Ignored if no weight " +"scheduler is selected." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:139 +msgid "OpenMPTCProuter Network overview / Status" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:700 msgid "Out" msgstr "出站" -#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 -msgid "Outbound – all interfaces" -msgstr "出站 – 所有接口" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:58 +msgid "Out-of-order segments merged" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:57 +msgid "Out-of-order segments queued" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:56 +msgid "Out-of-order segments queued at tail" +msgstr "" #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:640 msgid "Outbound traffic" msgstr "出站流量" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:468 +msgid "Outbound – all interfaces" +msgstr "出站 – 所有接口" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:150 +msgid "Path Manager type" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:254 +msgid "Path manager" +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:422 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:619 msgid "Peak" msgstr "峰值" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:203 +msgid "Per-WAN MPTCP endpoint status" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:78 +msgid "RM_ADDR signals dropped" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:77 +msgid "RM_ADDR signals failed to send" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:75 +msgid "RM_ADDR signals received" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:76 +msgid "RM_ADDR signals sent" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:260 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "超时后重新创建全网格子流" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:95 +msgid "Receive window conflict resolved on update" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:94 +msgid "Receive window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:96 +msgid "Receive window update conflicts" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:137 +msgid "Related pages" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "Retranmission intervals" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:144 +msgid "" +"Router → internet. Pins this class to a WAN for MPTCP’s bpf_dscp scheduler " +"(local dscp_iface map) and, for mqvpn, announces the class on this path’s " +"DSCP mask via the control API." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:255 +msgid "Scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:54 +msgid "Segments received outside the MPTCP mapping window" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:93 +msgid "Send window shared across subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:243 +msgid "" +"Set the make-after-break timeout: in absence of any close or shutdown " +"syscall, MPTCP sockets will maintain the status unchanged for such time, " +"after the last subflow removal, before moving to TCP_CLOSE." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:233 +msgid "" +"Set the timeout after which an ADD_ADDR (add address) control message will " +"be resent to an MPTCP peer that has not acknowledged a previous ADD_ADDR " +"message." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:50 +msgid "Settings" +msgstr "设置" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:257 +msgid "Stale loss count threshold" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:63 +msgid "Stale subflows recovered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:41 +msgid "Subflow JOIN ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:43 +msgid "Subflow JOIN ACK with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:39 +msgid "Subflow JOIN SYN received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:42 +msgid "Subflow JOIN SYN with mismatched port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:40 +msgid "Subflow JOIN SYN/ACK received on a different port" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:32 +msgid "Subflow JOIN accepted by peer (SYN/ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:33 +msgid "Subflow JOIN accepted by peer (SYN/ACK, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:30 +msgid "Subflow JOIN attempts received (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:31 +msgid "Subflow JOIN attempts received (SYN, backup)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:26 +msgid "Subflow JOIN attempts sent (SYN)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:35 +msgid "Subflow JOIN completed (ACK)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:28 +msgid "Subflow JOIN failed: could not bind address" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:29 +msgid "Subflow JOIN failed: could not connect" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:27 +msgid "Subflow JOIN failed: could not create socket" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:261 +msgid "Subflow limit" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:82 +msgid "Subflow priority change received (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:81 +msgid "Subflow priority change sent (MP_PRIO)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:62 +msgid "Subflows marked stale (possible blackhole)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:64 +msgid "Subflows removed" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:40 +msgid "Test" +msgstr "测试" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:223 +msgid "" +"The number of MPTCP-level retransmission intervals with no traffic and " +"pending outstanding data on a given subflow required to declare it stale. A " +"low stale_loss_cnt value allows for fast active-backup switch-over, an high " +"value maximize links utilization on edge scenarios e.g. lossy link with high " +"BER or peer pausing the data processing." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:248 +msgid "" +"The number of SYN + MP_CAPABLE retransmissions before falling back to TCP, " +"i.e. dropping the MPTCP options." +msgstr "" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:442 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:570 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:585 @@ -389,6 +935,139 @@ msgstr "总入站" msgid "Total out" msgstr "总出站" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:143 +msgid "Upload interface" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:164 +msgid "" +"Used by the *weight MPTCP schedulers (bpf_weight/bpf_weight_rr) and by " +"mqvpn’s \"Weighted RTT\"/\"Weighted Round Robin\" schedulers -- same value, " +"applies to both upload and download (mirrored to the gateway automatically). " +"Unlike the DSCP pins above, weight is a single value per WAN, not per " +"traffic class." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:249 +msgid "Userspace" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:152 +msgid "Userspace path manager" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:288 +msgid "Value" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:210 +msgid "WAN" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:163 +msgid "WAN weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_check.js:69 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_connections.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_fullmesh.js:15 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_monitor.js:15 +msgid "Waiting for command to complete…" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:304 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:170 +msgid "Weight" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:118 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:127 +msgid "" +"When using a DSCP or weight BPF scheduler, also sync each WAN’s pin to the " +"gateway (VPS) so it also holds for traffic the gateway sends (downloads), " +"not just traffic the router sends (uploads). Disabling this only stops " +"future syncs -- it does not remove pins already pushed to the gateway." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:128 +msgid "" +"While disabled, the DSCP table below only shows Upload -- Download has no " +"effect until this is re-enabled and applied." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:293 +msgid "backup" +msgstr "备份" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:76 +msgid "bpf_burst => same as the default scheduler" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:78 +msgid "bpf_first => always picks the first subflow to send data" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:77 +msgid "bpf_red => sends all packets redundantly on all available subflows" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:79 +msgid "" +"bpf_rr => always picks the next available subflow to send data (round-robin)" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:66 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:82 +msgid "default" +msgstr "默认" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:52 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:57 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:62 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:168 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:174 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:180 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:262 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:273 +msgid "disable" +msgstr "禁用" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:291 +msgid "disabled" +msgstr "禁用" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:51 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:56 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:61 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:167 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:173 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:179 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:261 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:272 +msgid "enable" +msgstr "启用" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:290 +msgid "enabled" +msgstr "启用" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:74 +msgid "kB/s" +msgstr "kB/秒" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:76 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:436 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:446 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:612 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:616 +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:620 +msgid "kbit/s" +msgstr "kbit/秒" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:292 +msgid "master" +msgstr "主" + #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:540 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:541 #: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/multipath.js:673 @@ -396,6 +1075,81 @@ msgstr "总出站" msgid "minutes window, 1 second interval" msgstr "分钟窗口,1 秒间隔" +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "missing" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_dscp_routing.js:154 +msgid "" +"mqvpn has no equivalent: its downlink always mirrors whichever WAN carries " +"the class on upload, so this field has no effect on mqvpn." +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:265 +msgid "ndiffports subflows number" +msgstr "ndiffports子流数" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp_diagnostics.js:225 +msgid "registered" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:228 +msgid "" +"specifies the maximum number of ADD_ADDR (add address) suboptions accepted " +"for each MPTCP connection" +msgstr "" + +#: luci-app-mptcp/htdocs/luci-static/resources/view/mptcp/mptcp.js:218 +msgid "" +"specifies the maximum number of additional subflows allowed for each MPTCP " +"connection" +msgstr "" + +#~ msgid "(%d minute window, %d second interval)" +#~ msgstr "(%d 分钟刷新, %d 秒钟刷新)" + +#~ msgid "(%d minutes window, %d seconds interval)" +#~ msgstr "(%d 分钟间隔, %d 秒钟刷新)" + +#~ msgid "Average:" +#~ msgstr "平均:" + +#~ msgid "Current:" +#~ msgstr "实时:" + +#~ msgid "Download:" +#~ msgstr "下载:" + +#~ msgid "Inbound:" +#~ msgstr "入站:" + +#~ msgid "Loading" +#~ msgstr "载入中" + +#~ msgid "" +#~ "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/" +#~ "Users/ConfigureMPTCP for help." +#~ msgstr "" +#~ "网络MPTCP设置. 访问http://multipath-tcp.org/pmwiki.php/Users/" +#~ "ConfigureMPTCP4 获取更多的支持." + +#~ msgid "Outbound:" +#~ msgstr "出站:" + +#~ msgid "Peak:" +#~ msgstr "峰值:" + +#~ msgid "Realtime Traffic" +#~ msgstr "实时流量" + +#~ msgid "Upload:" +#~ msgstr "上传:" + +#~ msgid "Waiting for command to complete..." +#~ msgstr "等待命令完成..." + #~ msgid "BLEST" #~ msgstr "最好的" diff --git a/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp b/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp index 87bbcb37f..7a42ed07d 100755 --- a/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp +++ b/luci-app-mptcp/root/usr/libexec/rpcd/luci.mptcp @@ -51,6 +51,369 @@ local function bwc_rows(dev) return {} end +local IP_BIN = "/sbin/ip" + +local function trim(s) + return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", "")) +end + +local function read_proc(path) + local f = io.open(path, "r") + if not f then return nil end + local v = f:read("*l") + f:close() + if v == nil then return nil end + return trim(v) +end + +-- First field of /proc/uptime (seconds since boot), used to turn raw +-- cumulative MPTcpExt counters into an "events/hour since boot" rate -- +-- a bare cumulative count (e.g. "7021 resets") doesn't say whether that's +-- alarming or a trickle, since it doesn't say over what timespan. +local function uptime_seconds() + local raw = read_proc("/proc/uptime") + local secs = raw and raw:match("^(%S+)") + return secs and tonumber(secs) or nil +end + +-- ------------------------------------------------------------------------- +-- MPTCP Diagnostics: explain *why* MPTCP might not be aggregating WANs +-- correctly -- kernel-level MPTCP counters (fallback to plain TCP, +-- blackhole/stale-subflow detection, resets, checksum errors, JOIN +-- failures, ...), the live endpoint/limits state, and a per-WAN cross-check +-- of whether each multipath-enabled interface actually has a registered +-- MPTCP endpoint -- turned into a plain-English issue list. +-- +-- All the underlying commands (multipath -k/-m/-c, ip mptcp ...) are +-- read-only/local and near-instant, so none of them are timeout-wrapped. +-- NOTE: never wrap "ip" in "timeout" here -- on this router's busybox +-- userland, "timeout N ip ..." has been seen to silently dispatch +-- busybox's own crippled "ip" applet instead of the real /sbin/ip, which +-- has no "mptcp" subcommand at all. Always call /sbin/ip directly. +-- ------------------------------------------------------------------------- + +-- Kernel MPTCP sysctl snapshot (works across the legacy out-of-tree sysctl +-- layout AND the current in-kernel net.mptcp.* layout -- whichever files +-- actually exist on this kernel). +function kernel_settings() + local settings = {} + settings.enabled = read_proc("/proc/sys/net/mptcp/mptcp_enabled") + or read_proc("/proc/sys/net/mptcp/enabled") + settings.checksum = read_proc("/proc/sys/net/mptcp/mptcp_checksum") + or read_proc("/proc/sys/net/mptcp/checksum_enabled") + settings.path_manager = read_proc("/proc/sys/net/mptcp/mptcp_path_manager") + or read_proc("/proc/sys/net/mptcp/pm_type") + settings.scheduler = read_proc("/proc/sys/net/mptcp/mptcp_scheduler") + or read_proc("/proc/sys/net/mptcp/scheduler") + settings.syn_retries = read_proc("/proc/sys/net/mptcp/mptcp_syn_retries") + settings.stale_loss_cnt = read_proc("/proc/sys/net/mptcp/stale_loss_cnt") + settings.add_addr_timeout = read_proc("/proc/sys/net/mptcp/add_addr_timeout") + settings.close_timeout = read_proc("/proc/sys/net/mptcp/close_timeout") + settings.blackhole_timeout = read_proc("/proc/sys/net/mptcp/blackhole_timeout") + settings.allow_join_initial_addr_port = read_proc("/proc/sys/net/mptcp/allow_join_initial_addr_port") + return settings +end + +-- The kernel's MPTcpExt* MIB counters, either as the "nstat -z" layout +-- (name, value, rate -- one counter per line, what "multipath -m" prints) +-- or the SNMP-style two-line layout (a header line of field names followed +-- by a value line, both prefixed "MPTcpExt:", found in /proc/net/netstat +-- and the legacy /proc/net/mptcp_net/snmp). Parse both. +function parse_counters(raw) + local counters = {} + local header + + for line in (raw or ""):gmatch("[^\n]+") do + -- The nstat-style counter name always continues with a letter right + -- after the "MPTcpExt" prefix (e.g. "MPTcpExtMPCapableSYNTX"); the + -- SNMP-style header/value lines start "MPTcpExt:" instead. Requiring + -- a letter here keeps the two forms from being confused with each + -- other (a bare "MPTcpExt:" line's second "word" can itself be a + -- number, which would otherwise wrongly match as a counter). + local name, value = line:match("^%s*(MPTcpExt%a%w*)%s+(%-?%d+)") + if name and value then + counters[name:gsub("^MPTcpExt", "")] = tonumber(value) + elseif line:match("^MPTcpExt:") then + -- SNMP-style: first "MPTcpExt:" line is field names, the next is values + if not header then + header = {} + for field in line:gmatch("%S+") do header[#header + 1] = field end + else + local i = 0 + for field in line:gmatch("%S+") do + i = i + 1 + local key = header[i] + if key and key ~= "MPTcpExt:" then + counters[key] = tonumber(field) + end + end + end + end + end + return counters +end + +-- Where to read the MPTcpExt* counters from for Diagnostics. Deliberately +-- NOT "multipath -m" here: that wraps "nstat -z", and nstat (without -a) +-- reports the delta since the *previous* nstat invocation by anyone on the +-- box (it keeps a shared per-uid history file) -- confirmed live: two +-- consecutive calls a couple seconds apart came back ~0, while "nstat -a -z" +-- (ignore history) matched /proc/net/netstat exactly. A page that polls +-- every 15s and calls that would show "since last poll" numbers while +-- labelling them "since boot", and would race with anything else on the +-- router that also calls nstat. Reading the kernel's own procfs SNMP-style +-- counters directly sidesteps all of that -- always the true cumulative +-- count, no shared state with other callers. +function mptcp_counters_raw() + local raw = exec_output("cat /proc/net/mptcp_net/snmp 2>/dev/null") + if raw == "" then + raw = exec_output("grep '^MPTcpExt:' /proc/net/netstat 2>/dev/null") + end + return raw +end + +-- "ip mptcp endpoint show": one line per registered endpoint, e.g. +-- 10.0.0.2 id 1 subflow dev eth0 +-- 88.1.2.3 id 2 signal dev wwan0 +-- 10.0.0.5 id 3 subflow backup fullmesh dev eth1 +function parse_endpoints(raw) + local endpoints = {} + for line in (raw or ""):gmatch("[^\n]+") do + local id = line:match("id%s+(%d+)") + local dev = line:match("dev%s+(%S+)") + local addr = line:match("^%s*(%S+)") + if id and addr and addr ~= "id" then + endpoints[#endpoints + 1] = { + id = tonumber(id), + address = addr, + dev = dev or "", + signal = line:match("%f[%a]signal%f[%A]") ~= nil, + subflow = line:match("%f[%a]subflow%f[%A]") ~= nil, + backup = line:match("%f[%a]backup%f[%A]") ~= nil, + fullmesh = line:match("%f[%a]fullmesh%f[%A]") ~= nil, + } + end + end + return endpoints +end + +-- "ip mptcp limits show" -> "add_addr_accepted 8 subflows 8" +function parse_limits(raw) + local limits = {} + for key, value in (raw or ""):gmatch("(%a[%w_]*)%s+(%d+)") do + limits[key] = tonumber(value) + end + return limits +end + +-- Per-WAN endpoint cross-check: for every interface the router considers +-- multipath-enabled, is its device actually registered as an MPTCP +-- endpoint? If not, that WAN can never carry an MPTCP subflow no matter +-- what the schedulers/counters say. +function wan_endpoint_status(endpoints) + local wans = {} + uci:foreach("network", "interface", function(s) + local name = s[".name"] + if name == "loopback" then return end + + local multipath = s["multipath"] + if multipath == nil or multipath == "" then + multipath = uci:get("openmptcprouter", name, "multipath") + end + multipath = multipath or "off" + if multipath == "off" then return end + + local dev = get_device(name) + if dev == "" then dev = s["device"] or s["ifname"] or "" end + + local has_endpoint = false + local endpoint_flags = "" + for _, ep in ipairs(endpoints) do + if dev ~= "" and ep.dev == dev then + has_endpoint = true + local flags = {} + if ep.signal then flags[#flags + 1] = "signal" end + if ep.subflow then flags[#flags + 1] = "subflow" end + if ep.backup then flags[#flags + 1] = "backup" end + if ep.fullmesh then flags[#flags + 1] = "fullmesh" end + endpoint_flags = table.concat(flags, ",") + break + end + end + + wans[#wans + 1] = { + name = name, + device = dev, + multipath = multipath, + has_endpoint = has_endpoint, + endpoint_flags = endpoint_flags, + } + end) + return wans +end + +-- Turn everything above into a plain-English issue list. +local function add_issue(issues, severity, code, message, detail) + issues[#issues + 1] = { + severity = severity, + code = code, + message = message, + detail = detail or "", + } +end + +function build_issues(settings, counters, wans) + local issues = {} + + if settings.enabled == "0" then + add_issue(issues, "error", "mptcp_disabled", + "MPTCP is disabled in the kernel.", + "No connection can use more than one WAN until MPTCP is re-enabled.") + end + + for _, wan in ipairs(wans) do + if wan.device == "" then + add_issue(issues, "warning", "wan_no_device", + string.format("%s: multipath is enabled but the interface has no device yet.", wan.name), + "The interface may still be coming up (no IP/link yet).") + elseif not wan.has_endpoint then + add_issue(issues, "error", "wan_no_endpoint", + string.format("%s (%s): no MPTCP endpoint registered for this WAN.", wan.name, wan.device), + "This WAN will never be used for an MPTCP subflow, regardless of scheduler/weight settings. " .. + "Usually fixed by a hotplug/interface restart (which re-runs 'multipath on|backup'), " .. + "or by checking that the interface actually has a global (non-private-only, non-CGNAT) IP.") + end + end + + local fallback = (counters.MPCapableFallbackSYNACK or 0) + (counters.MPCapableFallbackACK or 0) + if fallback > 0 then + add_issue(issues, "warning", "mptcp_fallback", + string.format("MPTCP fell back to plain TCP %d time(s).", fallback), + "A device on the path (firewall/middlebox/some ISP CGNAT boxes) is stripping the MPTCP TCP option " .. + "from the SYN or SYN/ACK, so the kernel gave up and used regular single-path TCP for those " .. + "connections. Use the MPTCP Support Check page (tracebox) per-WAN to confirm which WAN(s) strip it.") + end + + local stale, recover = counters.SubflowStale or 0, counters.SubflowRecover or 0 + if stale > 0 then + local stuck = stale - recover + if stuck > 0 then + add_issue(issues, "error", "mptcp_blackhole", + string.format("%d subflow(s) currently marked stale (possible blackhole) out of %d total.", stuck, stale), + "A path stopped acknowledging data for one or more subflows; the kernel is avoiding it. " .. + "If this keeps climbing on one specific WAN, that WAN's path is likely being blackholed.") + else + add_issue(issues, "warning", "mptcp_blackhole_recovered", + string.format("%d subflow(s) were marked stale but all recovered.", stale), + "Transient -- a path briefly stopped acking data and the kernel recovered it automatically.") + end + end + + local hmac_fail = (counters.MPJoinSynAckHMacFailure or 0) + (counters.MPJoinAckHMacFailure or 0) + if hmac_fail > 0 then + add_issue(issues, "warning", "mptcp_join_hmac_failure", + string.format("%d MPTCP JOIN handshake authentication failure(s).", hmac_fail), + "A new subflow's JOIN handshake failed HMAC verification -- either packets were altered in " .. + "transit or the two ends disagree on the connection's key/token.") + end + + if (counters.MPJoinNoTokenFound or 0) > 0 then + add_issue(issues, "warning", "mptcp_join_no_token", + string.format("%d subflow JOIN attempt(s) referenced an unknown token.", counters.MPJoinNoTokenFound), + "The peer (usually the VPS) no longer recognizes the MPTCP connection -- often because its proxy " .. + "process restarted and lost state. A new subflow can't attach to a connection the peer forgot.") + end + + if (counters.DataCsumErr or 0) > 0 then + add_issue(issues, "warning", "mptcp_checksum_error", + string.format("%d MPTCP data checksum error(s).", counters.DataCsumErr), + "Check that 'mptcp_checksum' matches on both the router and the VPS -- a mismatch (or a path " .. + "that corrupts data) triggers this.") + end + + -- Split by direction, not just summed: which side is doing the closing + -- matters. Confirmed live on the bench (2026-08-16) -- a steady climb + -- here traced back to OMR's own per-WAN shadowsocks health-check loop + -- (omr-tracker-ss) opening a fresh MPTCP connection through the + -- mptcp-enabled sslocal proxy every ~10s and closing it abortively, NOT + -- to path interference or the VPS dropping the tunnel -- confirmed by + -- MPRstRx staying ~0 while MPRstTx climbed, and by reproducing an + -- MPRstTx increment live by firing that exact health-check request. + local reset_tx = (counters.MPRstTx or 0) + (counters.MPFastcloseTx or 0) + local reset_rx = (counters.MPRstRx or 0) + (counters.MPFastcloseRx or 0) + local resets = reset_tx + reset_rx + if resets > 0 then + local rate_suffix = "" + local uptime = uptime_seconds() + if uptime and uptime >= 60 then + rate_suffix = string.format(" (~%.1f/hour since boot)", resets / (uptime / 3600)) + end + if reset_rx == 0 or reset_tx >= reset_rx * 3 then + -- Tx-heavy: this router is doing almost all the closing and the + -- peer is barely ever resetting back. That's the signature of a + -- local abortive close (e.g. a health-check script tearing down + -- its own short-lived proxied connection), not the peer/path + -- forcing the connection shut. + add_issue(issues, "warning", "mptcp_resets", + string.format("%d MPTCP-level reset/fastclose event(s) sent by this router%s.", reset_tx, rate_suffix), + "Almost all of these were sent by this router, not the peer (received resets are near zero) -- " .. + "that points at something local doing an abortive close of its own MPTCP connections (a common " .. + "cause: a health-check/keepalive script that opens a proxied connection, makes one quick request, " .. + "then closes it hard) rather than active interference on the path or the VPS dropping the tunnel. " .. + "Only worth escalating if it's paired with rising SubflowStale/Blackhole counters above.") + else + add_issue(issues, "warning", "mptcp_resets", + string.format("%d MPTCP-level reset/fastclose event(s)%s.", resets, rate_suffix), + "One side force-closed the whole MPTCP connection (all subflows at once) rather than a single " .. + "subflow -- can indicate active interference or the proxy/VPN tunnel dropping abruptly.") + end + end + + local addr_drop = (counters.AddAddrDrop or 0) + (counters.RmAddrDrop or 0) + if addr_drop > 0 then + -- A handful of drops only matters relative to how much ADD_ADDR/RM_ADDR + -- traffic there's actually been -- against a large total it's usually a + -- one-off from an interface flap or brief restart, already self-healed + -- by the next successful signal, not an ongoing problem. Only surface + -- this as an issue once drops are a meaningful share of that traffic + -- (>1%); with no successful signals at all to compare against, treat + -- it as 100% (nothing has gotten through), which is always worth + -- surfacing. + local addr_total = (counters.AddAddr or 0) + (counters.AddAddrTx or 0) + + (counters.RmAddr or 0) + (counters.RmAddrTx or 0) + local addr_drop_pct = addr_total > 0 and (100 * addr_drop / addr_total) or 100 + if addr_drop_pct > 1 then + local ratio_suffix = "" + if addr_total > 0 then + ratio_suffix = string.format(" (%d of %d ADD_ADDR/RM_ADDR signals, %.3g%%)", + addr_drop, addr_total, addr_drop_pct) + end + add_issue(issues, "warning", "mptcp_addr_signal_dropped", + string.format("%d ADD_ADDR/RM_ADDR signal(s) dropped%s.", addr_drop, ratio_suffix), + "A WAN address announcement (or removal) didn't make it to the peer, so the peer may never " .. + "attempt a subflow toward that WAN. A handful of drops against a much larger signal volume is " .. + "usually a one-off from an interface flap or a brief proxy restart, and self-heals on the next " .. + "successful signal -- only worth chasing further if this keeps climbing.") + end + end + + if (counters.MPFailTx or 0) > 0 or (counters.MPFailRx or 0) > 0 then + add_issue(issues, "warning", "mptcp_mapping_failure", + "MPTCP data mapping failure signalled (MP_FAIL).", + "One side couldn't map received data to the right place in the byte stream on a subflow -- " .. + "that subflow gets torn down and traffic continues on the others, if any remain.") + end + + if #issues == 0 then + add_issue(issues, "ok", "no_issues_detected", + "No MPTCP fallback, blackhole, reset or checksum issues detected right now.", + "This only reflects counters since boot/last reset -- a healthy snapshot doesn't rule out an " .. + "intermittent issue on a specific path; keep this page open while reproducing the problem.") + end + + return issues +end + -- ------------------------------------------------------------------------- -- RPC methods -- ------------------------------------------------------------------------- @@ -354,6 +717,36 @@ local methods = { return { output = exec_output(cmd) } end }, + + -- Diagnostics: kernel MPTCP counters/endpoints/limits + a per-WAN + -- endpoint cross-check, turned into a plain-English issue list. See the + -- helpers above ("MPTCP Diagnostics" section) for the actual logic. + diagnose = { + call = function() + local settings = kernel_settings() + local counters = parse_counters(mptcp_counters_raw()) + local endpoints = parse_endpoints(exec_output(IP_BIN .. " mptcp endpoint show 2>/dev/null")) + local limits = parse_limits(exec_output(IP_BIN .. " mptcp limits show 2>/dev/null")) + local wans = wan_endpoint_status(endpoints) + local issues = build_issues(settings, counters, wans) + + local connections_raw = exec_output("multipath -c 2>/dev/null") + local established_count = 0 + for _ in connections_raw:gmatch("[Ee][Ss][Tt][Aa][Bb]") do + established_count = established_count + 1 + end + + return { + settings = settings, + counters = counters, + endpoints = endpoints, + limits = limits, + wans = wans, + issues = issues, + established_count = established_count, + } + end + }, } -- ------------------------------------------------------------------------- diff --git a/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json b/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json index 3db1c4762..a402c8155 100644 --- a/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json +++ b/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json @@ -21,6 +21,17 @@ "acl": [ "luci-app-mptcp" ] } }, + "admin/network/mptcp/mptcp_diagnostics": { + "title": "Diagnostics", + "order": 12, + "action": { + "type": "view", + "path": "mptcp/mptcp_diagnostics" + }, + "depends": { + "acl": [ "luci-app-mptcp" ] + } + }, "admin/network/mptcp/mptcp_dscp_routing": { "title": "DSCP / Weight Routing", "order": 15, diff --git a/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json b/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json index 12179b086..cdb82bfa8 100644 --- a/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json +++ b/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json @@ -22,7 +22,8 @@ "get_settings", "set_settings", "get_interface_settings", - "set_interface_settings" + "set_interface_settings", + "diagnose" ] } }, diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index 27b248dfc..da9d9036c 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.8.12 -PKG_RELEASE:=226 +PKG_RELEASE:=227 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ @@ -17,6 +17,7 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Geoview \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \ @@ -96,6 +97,12 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria select PACKAGE_hysteria default n +config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy + bool "Include NaiveProxy" + depends on !(arc||armeb||loongarch64||mips||mips64||powerpc||TARGET_gemini) + select PACKAGE_naiveproxy + default n + config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client bool "Include Shadowsocks Rust Client" depends on !i386 diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua new file mode 100644 index 000000000..b00c0c3fc --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/6_naive.lua @@ -0,0 +1,33 @@ +if not api.is_finded("naive") then + return +end + +-- [[ Naive ]] +local m, s1 = ... +local type_name = "Naiveproxy" + +s1.fields["type"]:value(type_name, "NaïveProxy") + +if s1.val["type"] ~= type_name then + return +end + +local s = NamedSection(m, arg[1], "server") +s.type_name = type_name +s.option_prefix = "naive_" + +o = s:option(ListValue, "protocol", translate("Protocol")) +o:value("https", translate("HTTPS")) +o:value("quic", translate("QUIC")) + +o = s:option(Value, "address", translate("Address (Support Domain Name)")) + +o = s:option(Value, "port", translate("Port")) +o.datatype = "port" + +o = s:option(Value, "username", translate("Username")) + +o = s:option(Value, "password", translate("Password")) +o.password = true + +api.luci_types(s1, s) diff --git a/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua b/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua new file mode 100644 index 000000000..a29cfafe6 --- /dev/null +++ b/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua @@ -0,0 +1,42 @@ +module("luci.passwall.util_naiveproxy", package.seeall) +local api = require "luci.passwall.api" +local jsonc = api.jsonc + +function gen_config(var) + local node_id = var["node"] + if not node_id then + print("node 不能为空") + return + end + local node = api.uci_get_c(node_id) + local run_type = var["run_type"] + local local_addr = var["local_addr"] + local local_port = var["local_port"] + local server_host = var["server_host"] or (node.address or ""):lower() + local server_port = var["server_port"] or node.port + + if api.is_ipv6(server_host) then + server_host = api.get_ipv6_full(server_host) + end + local server = server_host .. ":" .. server_port + + local config = { + listen = run_type .. "://" .. local_addr .. ":" .. local_port, + proxy = node.protocol .. "://" .. node.username .. ":" .. node.password .. "@" .. server + } + + return jsonc.stringify(config, 1) +end + +_G.gen_config = gen_config + +if arg[1] then + local func =_G[arg[1]] + if func then + local var = nil + if arg[2] then + var = jsonc.parse(arg[2]) + end + print(func(var)) + end +end diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index 847390709..d0e914264 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -13,6 +13,7 @@ LUA_UTIL_PATH=/usr/lib/lua/luci/passwall UTIL_SINGBOX=$LUA_UTIL_PATH/util_sing-box.lua UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua +UTIL_NAIVE=$LUA_UTIL_PATH/util_naiveproxy.lua UTIL_HYSTERIA2=$LUA_UTIL_PATH/util_hysteria2.lua SINGBOX_BIN=$(first_type $(config_t_get global_app sing_box_file) sing-box) XRAY_BIN=$(first_type $(config_t_get global_app xray_file) xray) @@ -455,6 +456,13 @@ run_socks() { [ -n "$no_run" ] && _args="${_args} no_run=1" run_xray flag=$flag node=$node socks_address=$bind socks_port=$socks_port config_file=$config_file log_file=$log_file ${_args} ;; + naiveproxy) + json_add_string "run_type" "socks" + json_add_string "local_addr" "$bind" + json_add_string "local_port" "$socks_port" + lua $UTIL_NAIVE gen_config "$(json_dump)" > $config_file + [ -n "$no_run" ] || ln_run "$(first_type naive)" naive $log_file "$config_file" + ;; ssr) json_add_string "local_addr" "$bind" json_add_string "local_port" "$socks_port" diff --git a/luci-theme-footstrap/Makefile b/luci-theme-footstrap/Makefile index ce07ba1f0..4eaec10c1 100644 --- a/luci-theme-footstrap/Makefile +++ b/luci-theme-footstrap/Makefile @@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap FOOTSTRAP_VERSION?= ifneq ($(FOOTSTRAP_VERSION),) PKG_VERSION:=$(FOOTSTRAP_VERSION) -PKG_RELEASE:=22 +PKG_RELEASE:=23 endif LUCI_TITLE:=Footstrap Theme diff --git a/luci-theme-footstrap/dev-sync.sh b/luci-theme-footstrap/dev-sync.sh index 46af51b80..392643b7f 100755 --- a/luci-theme-footstrap/dev-sync.sh +++ b/luci-theme-footstrap/dev-sync.sh @@ -132,4 +132,19 @@ rm -f /tmp/luci-indexcache*" scp -q "$D"/root/etc/uci-defaults/30_luci-theme-footstrap "$R":/tmp/30_luci-theme-footstrap ssh "$R" "PKG_UPGRADE=1 sh /tmp/30_luci-theme-footstrap; rm -f /tmp/30_luci-theme-footstrap /tmp/luci-indexcache*" + +# ---- BUST THE BROWSER CACHE, or a dev deploy is invisible to the device you are testing on ---- +# +# head.ut versions every asset with `?v={{ pkgs_update_time }}`, and luci-base derives that from the +# mtime of the PACKAGE DATABASE (runtime.uc: /lib/apk/db/installed, falling back to +# /usr/lib/opkg/status). Installing a package moves it; scp'ing files over an existing install does +# not — so a dev deploy leaves the URL identical while the bytes underneath change, and a browser is +# entitled to keep serving what it already has. On a phone that is not a theory: a whole afternoon of +# "still shakes" reports were taken against a stylesheet several deploys old. +# +# Touching the database file is what an install would have done to it, so the next page carries a new +# `?v=` for every asset and nothing can be stale. Router-only, dev-only: nothing in the package does +# this. +ssh "$R" 'touch /lib/apk/db/installed 2>/dev/null || touch /usr/lib/opkg/status 2>/dev/null || true' + echo "synced to $R (single Footstrap theme registered, active theme unchanged)" diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-chrome.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-chrome.js index 8d08c7952..e53965512 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-chrome.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-chrome.js @@ -210,6 +210,14 @@ function fitShell() { } function fitChrome() { + /* Nothing this function asks can change while the reader scrolls — the bar's width, the menu's + * width, the room beside the brand — and every one of those questions is a layout read landing + * in the middle of a flick. Put off until the scrolling stops; see fs-fit.js. */ + if (fit.scrolling()) { + fit.deferMeasurement(); + return; + } + fitShell(); const bar = document.querySelector('.fs-sidebar'); @@ -463,5 +471,20 @@ return baseclass.extend({ /* registered with fs-fit by the theme's init(): the bar's "does the menu fit beside the brand" * measurement rides the same engine as the data tables' */ fitChrome, + + /* The width a page's content column has, WITHOUT reading layout. The sidebar (or the rail) eats + * a known amount of the window and the shell adds a known padding, and all three are already + * memoised against the density attribute for `fitShell()`. It is exported because a pass that + * must answer mid-scroll — fs-select's, for a table the poll has just brought in — otherwise has + * only `window.innerWidth`, which in the sidebar layout is the wrong number by exactly the + * sidebar: at an 800px window the column is 520px, so the cheap judgement said "plenty of room" + * for a table that then overflowed and was clipped. */ + contentWidth() { + const g = shellGeometry(); + const narrow = document.documentElement.hasAttribute('data-narrow'); + /* in the bar layout the chrome is above the content, not beside it */ + const cut = narrow ? 0 : (prefs.currentRail() ? g.railW : g.sidebarW); + return Math.max(0, window.innerWidth - cut - (g.contentPad * 2)); + }, wireRail }); diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-fit.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-fit.js index ae82bf1dc..2e72e29ac 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-fit.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-fit.js @@ -20,21 +20,184 @@ * ResizeObserver, not onresize: a rail collapse and a layout toggle change the content width * without resizing the window. */ +/* THE STYLESHEET MAY ONLY HIDE WHAT THIS FILE WILL SHOW, AND THE ARM BELONGS TO THE DISARM. + * `theme/30-tables.css` keeps a data table out of the layout until something marks it `.fs-fitted`. + * This attribute is what arms that rule — and it used to be written here, at module eval, while the + * only code that ever writes `.fs-fitted` lives in fs-select.js, which the footer requires + * SEPARATELY (`partials/footer.ut`: one require for menu-footstrap, another for fs-select, with no + * dependency edge between them). A document that loaded this file and not that one — a failed + * fetch, a parse error, a throw in fs-select's own init — armed a rule nobody could clear, and every + * data table on Status/Leases/Processes/Wireless rendered as nothing at all, silently. + * + * So the arming is exported instead, and the module that clears the rule is the one that raises it. + * A document where fs-select never ran carries no attribute and shows every table exactly as it did + * before the rule existed. */ +function armGate() { + if (!fittersEnabled()) return; + try { document.documentElement.dataset.fsFit = '1'; } catch (e) { /* no document, no gate */ } +} + const _fitters = []; let _rafPending = false; let _ro = null, _mo = null, _moFlag = null; -/* Run every fitter NOW, synchronously. A fitter must be idempotent — this fires on every - * relevant mutation. */ -function run() { - for (const fit of _fitters) { +/* ---- A PASS THAT READS LAYOUT MAY NOT RUN WHILE THE READER SCROLLS ---- + * + * Reading layout — `getBoundingClientRect()`, `clientWidth`, `scrollWidth` — forces the engine to + * lay the page out synchronously. Once a second, from a poll tick, in the middle of a flick on a + * phone, that is what iOS holds the main thread back to prevent, and it was the largest part of the + * shaking reported from an iPhone; a stock theme has no JS in that path at all. + * + * The rule is stated by each pass rather than by this file, and that is not an oversight — the + * central version was written, measured and reverted, because moving the decision here also moved + * WHEN the deferred work lands and the device started shaking again. A pass that reads layout asks + * `scrolling()` and calls `deferMeasurement()`; a pass that only writes does neither and runs + * always. The one that must run always is the marking of a freshly polled table: the stylesheet + * keeps an unmarked data table out of the layout, so waiting would leave it invisible for as long + * as the reader keeps scrolling. */ +function runAll(list, what) { + for (const fit of list) { try { fit(); } /* one broken fitter must take neither the others nor the poll's MutationObserver * callback with it — that would silently stop ALL re-fitting */ - catch (e) { console.error('fs-fit: a fitter threw', e); } + catch (e) { console.error('fs-fit: a ' + what + ' threw', e); } } } +/* Everything that may run right now, with the reader kept where they were. + * + * ONE PATH: the mutation observer, the coalesced re-fit and the pass that was put off during a + * scroll all come through here, so the order — reference, work, correction — is stated once. + * `anchorRef()` answers null while the reader scrolls and the correction below does nothing with a + * pass that happens mid-scroll costs neither of the two layout reads. + * + * WHAT MAY RUN MID-SCROLL IS EACH PASS'S OWN ANSWER, not this function's. A pass that only writes — + * marking a freshly polled table, which cannot wait because the stylesheet holds an unmarked table + * out of the layout — runs always; a pass that reads layout asks `scrolling()` first and calls + * `deferMeasurement()`. Deciding it here instead was tried and reverted: it changed WHEN the + * deferred work lands, and the device that had the problem started shaking again. */ +/* DEV SWITCH: `localStorage.fsFit = 'off'` stops every fitter. It exists because the only way to + * tell "the theme's measuring is what shakes this phone" from "something else is" is to turn the + * measuring off ON THAT PHONE, and a laptop cannot answer it. */ +function fittersEnabled() { + try { return localStorage.getItem('fsFit') !== 'off'; } + catch (e) { return true; } +} +function run() { + if (!fittersEnabled()) return; + runAll(_fitters, 'fitter'); +} + +/* ---- IS THE PAGE MOVING RIGHT NOW? — ASKED OF THE POSITION, NEVER OF THE EVENTS ---- + * + * A pass that reads layout must not run while the page moves: on a phone every such read forces a + * synchronous layout in the middle of a flick, which is the work iOS holds the main thread back to + * prevent. So the passes ask this before measuring, and what they skipped is run once the movement + * stops. + * + * THE FIRST VERSION ASKED THE EVENTS — `scroll`, `wheel`, `touchmove`, plus 200 ms of quiet — and it + * was wrong in the one place it mattered. On iOS the momentum keeps carrying the page long after the + * finger has gone, and events do not reliably arrive through it; the timer then declared the reader + * still and dropped the whole deferred pass — every table stripped and measured, the chrome + * re-fitted — into the middle of the glide. That is a stall and a relayout while the page is + * visibly moving, and it is the shaking that came BACK when a refactor made less work happen during + * the scroll and more of it land in that burst. The measurement that named it: the same device + * shook more with strictly less work in the scroll path. + * + * So movement is read from the SCROLL POSITION. A frame in which the offset differs from the last is + * movement, whatever the event stream is doing; the sampler runs only while there is reason to + * think the page moves, and stops itself when the offset has held for SCROLL_IDLE. Momentum, + * rubber-banding and a programmatic `scrollTo` all look the same to it, which is the point. + * + * The offset read is one per frame, and it is the cheapest question there is — no geometry, no + * element, no forced layout beyond what the frame already needs. */ +/* HOW LONG THE PAGE MUST HOLD STILL BEFORE THE PUT-OFF WORK MAY RUN, and the number is the fix for + * the shaking, not a tuning knob. + * + * 200ms was shorter than the pauses a slow reader leaves. Rocking a page gently at the tables — the + * reader's own description of when it happens — the offset stops for a moment between one movement + * and the next, this timer called that a stop, and the whole deferred pass landed in the middle of + * the gesture: every table stripped of its marks, measured, marked again. That is a full relayout + * while the page is visibly moving, and it is what "jerks back and forth" was. + * + * Measured on a stand with the reader's motion imitated (a slow rock, 60 frames, the error between + * what the wheel asked for and what the page did, summed): 137-256px of roughness at 200ms with + * every twentieth frame off by 40px, and 59px — the floor, one pixel of rounding per frame, the same + * as switching the fitters off entirely — at 250ms and above. 400 is that floor with room to spare, + * and still well inside the time a reader takes to look at what they scrolled to. */ +const SCROLL_IDLE = 400; +/* set by a pass that skipped its measurement because the page was moving; consumed by the sampler + * below the moment it stops */ +let _deferred = false; +function deferMeasurement() { _deferred = true; } +let _movingUntil = 0; +let _lastOffset = null; +let _sampling = false; + +/* WHICH ELEMENT SCROLLS, ASKED ONCE PER WIDTH RATHER THAN ONCE PER FRAME. + * + * This function is the one every other pass consults before it dares to measure, and it ran in the + * frame loop below for as long as the page moved — so the `scrollHeight`/`clientHeight` probe it + * used to make WAS a forced synchronous layout, once per frame, in the middle of the flick this file + * exists to keep clear. Worse, a poll tick lands as a microtask that writes classes, so the very + * next frame's probe paid for a layout that had just been dirtied; and `touchstart` starts the + * sampler, so a plain tap on a button bought ~24 of them. + * + * The answer cannot change without the room changing: the two layouts scroll different elements and + * the switch between them is a width change, which `onResize` already watches and stamps. So the + * verdict is cached against that stamp and the offset is then read from the scroller directly — + * `scrollTop` on an element and `scrollY` on the window are both free. */ +let _scroller = null, _scrollerAt = -1; +function scroller() { + if (_scrollerAt === _resizeSeq && (_scroller === null || _scroller.isConnected)) return _scroller; + const sc = document.getElementById('maincontent'); + _scroller = (sc && sc.scrollHeight - sc.clientHeight > 4) ? sc : null; + _scrollerAt = _resizeSeq; + return _scroller; +} +function scrollTop() { + const sc = scroller(); + return sc ? sc.scrollTop : window.scrollY; +} + +function scrolling() { return Date.now() < _movingUntil; } + +function sampleMotion() { + const y = scrollTop(); + if (_lastOffset === null || y !== _lastOffset) { + _lastOffset = y; + _movingUntil = Date.now() + SCROLL_IDLE; + } + if (scrolling()) { requestAnimationFrame(sampleMotion); return; } + _sampling = false; + /* the page has held still for SCROLL_IDLE: whatever was put off may run now */ + if (_deferred) { + _deferred = false; + const ref = anchorRef(); + run(); + scheduleAnchor(ref); + } +} + +function noteMotion() { + _movingUntil = Date.now() + SCROLL_IDLE; + if (_sampling) return; + _sampling = true; + requestAnimationFrame(sampleMotion); +} + +/* `passive: true` and `capture: true`: this must never sit in front of the scroll it is watching, + * and `scroll` does not bubble from an element — it only travels down the capture phase, which is + * how the sidebar layout's inner scroller is seen as well as the document. The events only START + * the sampler; whether the page is still moving is the sampler's answer, not theirs. */ +(function watchMotion() { + const opts = { passive: true, capture: true }; + window.addEventListener('scroll', noteMotion, opts); + window.addEventListener('wheel', noteMotion, opts); + window.addEventListener('touchstart', noteMotion, opts); + window.addEventListener('touchmove', noteMotion, opts); +})(); + /* Next frame, at most once per frame (rule 3). */ function schedule() { if (_rafPending) return; @@ -59,6 +222,9 @@ function schedule() { * * Per element, because the roots are observed separately and a dialog can resize while #view does * not. The first entry for an element always counts as a change, so nothing is lost at start-up. */ +/* bumped whenever an observed root changes WIDTH — the only thing that can change which element + * scrolls, and therefore what `scroller()` above may cache */ +let _resizeSeq = 0; const _lastWidth = new WeakMap(); function onResize(entries) { let widthMoved = false; @@ -71,7 +237,7 @@ function onResize(entries) { widthMoved = true; } } - if (widthMoved) schedule(); + if (widthMoved) { _resizeSeq++; schedule(); } } /* Watch an element's size. A change in WIDTH re-fits everything — the fitters are cheap and few. */ @@ -85,6 +251,111 @@ function watch(el) { _ro.observe(el); } +/* ---- SCROLL ANCHORING, WHERE THE ENGINE HAS NONE ---- + * + * A poll tick changes the height of what is ABOVE the reader: a lease expires, a station joins, a + * section renders one row fewer. An engine with scroll anchoring absorbs that — it moves the scroll + * offset by the same amount, so the page under the reader does not move. WebKit has none, and it is + * every browser on iOS: measured on the reporter's own router, `content +133px, +134px, +123px, + * +108px…` one after another, each next to a `child +1/-1` in a polled section. That is the shaking, + * and it is not the tall-intermediate problem the rest of this file solves — the height change here + * is REAL, and simply nobody compensates for it. + * + * So this compensates for it, and only when nobody else did. A reference is taken from the elements + * that survive a poll — the section frames — choosing the one that crosses the top of the viewport, + * because that is the boundary a reader perceives as "where I am". The fitters run, the reference is + * read again, and the offset is moved by however far it drifted. + * + * WHY THIS IS SAFE ON AN ENGINE THAT DOES ANCHOR, which an earlier attempt got wrong by measuring + * the wrong thing: the correction is computed from the REFERENCE, not from the scroll offset. An + * anchoring engine has already put the reference back where it was by the time this reads it — the + * read forces layout, and the adjustment happens during layout — so the drift is zero and this does + * nothing at all. Measuring the offset instead reads an anchoring adjustment as a fault and corrects + * a correction, which is exactly how a previous version made Chromium worse (16 movements, 1827px). + * + * It never fights the user: a page at the very top has no offset to give back and is left alone, and + * a drift under a pixel is rounding rather than movement. */ +function anchorRef() { + /* NOT WHILE THE READER SCROLLS. Every rect read here is a forced layout, and this runs on every + * content mutation — i.e. once a second, in the middle of a flick, which is the work iOS holds + * the main thread back to avoid. The compensation exists for a page the reader is looking at, + * not for one they are already moving; while they scroll there is nothing to keep still. */ + if (scrolling()) return null; + const frames = document.querySelectorAll('#view .cbi-section, #view > .cbi-section-node, #view > div'); + for (const el of frames) { + const r = el.getBoundingClientRect(); + /* the frame the viewport's top edge cuts through */ + if (r.top <= 0 && r.bottom > 0) return { el, top: r.top }; + } + return null; +} +/* THE CORRECTION IS UNCONDITIONAL, AND IT IS A NO-OP WHERE THE ENGINE DOES THE JOB. + * + * There used to be a watching phase here: the first three mutations were only measured, and a + * reference that had held still meant "this engine anchors, never touch the offset again". It was + * wrong in the way that mattered. WebKit does not anchor, but the drift it leaves is often small — + * a value grew a line, a row appeared — so three quiet samples were easy to come by, the + * compensation switched itself off for the life of the document, and the page walked downwards a + * few pixels at a time, once per poll tick. That is exactly how it was reported: "jerks a little + * downwards, all the time". + * + * Correcting always is safe because the correction is computed from the REFERENCE, not from the + * scroll offset: an engine that anchors has already put the reference back by the time this reads + * it — the read forces layout, and the adjustment happens during layout — so the drift is zero and + * nothing is written. Measuring the OFFSET instead reads an anchoring adjustment as a fault and + * corrects a correction, which is how an earlier version made Chromium worse (10 movements up to + * 1616px against 0 without it); that mistake is not in this shape. + * + * Two guards remain, and both are about not fighting the reader: a page at the very top has no + * offset to give back, and a drift under a pixel is rounding rather than movement. */ +/* ONCE PER FRAME, AFTER EVERYTHING HAS LANDED — not once per mutation batch. + * + * A poll tick does not arrive as one mutation: luci-mod-status fills its sections one after another, + * and each fill wakes this observer. Correcting on each of them measures a page that is still being + * written: the reference is read between two batches, the drift is computed against a layout that + * the next batch immediately invalidates, and the correction is wrong by whatever the rest of the + * tick brought. The next tick corrects the other way. That is a page that jerks while nobody + * touches it, and it is what was reported — with a telling detail: it went away whenever a + * diagnostic probe that forced layout on EVERY frame was loaded, because then every reading this + * code took happened to be against a settled layout. + * + * So the reference is taken at the first mutation of a batch and the correction is applied in a + * requestAnimationFrame — after the batch, after style and layout have settled, once. A newer + * reference is not taken while one is pending: the first one is where the reader actually was. */ +let _anchorPending = null; +let _anchorFrame = 0; +/* DEV SWITCH, for the device that has the problem: `localStorage.fsAnchor = 'off'` stops the theme + * from ever writing the scroll offset, which is the one thing here that can move a page nobody is + * touching. It exists to answer a question a laptop cannot — whether the correction is the cure or + * the disease — and comes out with the answer. */ +function anchorEnabled() { + try { return localStorage.getItem('fsAnchor') !== 'off'; } + catch (e) { return true; } +} +function scheduleAnchor(ref) { + if (!ref || !anchorEnabled()) return; + if (_anchorPending) return; + _anchorPending = ref; + if (_anchorFrame) return; + _anchorFrame = requestAnimationFrame(() => { + _anchorFrame = 0; + const pending = _anchorPending; + _anchorPending = null; + applyAnchor(pending); + }); +} +function applyAnchor(ref) { + if (!ref || !ref.el.isConnected) return; + const sc = document.getElementById('maincontent'); + const inner = sc && sc.scrollHeight - sc.clientHeight > 4; + const at = inner ? sc.scrollTop : window.scrollY; + if (at <= 0) return; + const drift = ref.el.getBoundingClientRect().top - ref.top; + if (Math.abs(drift) < 1) return; + if (inner) sc.scrollTop = at + drift; + else window.scrollTo(0, at + drift); +} + /* Rule 2's mutation side. Deliberately NOT filtered by node type: a filter is a second place to * get wrong (the table fitter's own once said `table.table`, and LuCI renders most of its tables * as DIVs — so the poll never re-measured at all), and run() is a handful of measurements. */ @@ -100,7 +371,12 @@ function watch(el) { * constructor, and luci-base instantiates a class exactly once, at the first require. */ function observeContent() { if (_mo) return; - _mo = new MutationObserver(run); + _mo = new MutationObserver(() => { + /* what the reader is looking at, before the poll's mutation and the fitters move anything */ + const ref = anchorRef(); + run(); + scheduleAnchor(ref); + }); for (const host of [ document.getElementById('view') || document.body, document.getElementById('modal_overlay') ]) { if (!host) continue; _mo.observe(host, { childList: true, subtree: true }); @@ -136,11 +412,21 @@ return baseclass.extend({ fit(); }, + /* Is the reader scrolling, and "I could not measure, wake me when they stop". A pass that has to + * read layout asks the first and calls the second; a pass that only writes does neither. */ + scrolling, + deferMeasurement, + + /* Raise the stylesheet's "an unanswered table takes no room" rule. Called by the module that + * answers — see armGate above; nothing else may call it. */ + armGate, + /* Re-fit on the next frame, coalesced. (There is no exported `run`: everything that changes * the available room — the layout toggle, the rail collapse — schedules. Only the mutation * observer re-fits synchronously, and that is rule 2's whole point.) */ schedule, + /* Coalesce ANY callback into one call per frame (rule 3, for non-fitters): schedule() runs * EVERY fitter, so a caller wanting only its own work batched cannot use it — three had * hand-rolled the identical five lines. NOT for the per-element case: menu-footstrap.js's diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js index 254ee8b55..ae560e17c 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js @@ -32,20 +32,45 @@ * Hooked at module eval — before any view render can set a timer, and LuCI resolves a module's * dependencies BEFORE running the dependent's factory, so this runs no later than it used to when * it sat in menu-footstrap-common.js itself. */ -const _viewIntervals = (window.__fsViewIntervals || (window.__fsViewIntervals = new Set())); +const _viewIntervals = (window.__fsViewIntervals || (window.__fsViewIntervals = new Map())); (function hookIntervals() { if (window.__fsIntervalsHooked) return; window.__fsIntervalsHooked = true; const _si = window.setInterval, _ci = window.clearInterval; - window.setInterval = function () { + window.setInterval = function (fn, ms) { const id = _si.apply(window, arguments); - _viewIntervals.add(id); + /* the arguments are kept, not just the id: a paused timer has to be re-armed with what it + * was armed with, and a `setInterval` id carries none of that back */ + _viewIntervals.set(id, { fn, ms, rest: Array.prototype.slice.call(arguments, 2) }); return id; }; window.clearInterval = function (id) { _viewIntervals.delete(id); return _ci.apply(window, arguments); }; + /* A HIDDEN TAB MUST NOT KEEP CALLING THE ROUTER. `wireVisibility()` below stops LuCI's own poll + * when the tab goes away, which is most of the traffic — but a view is free to run a plain + * `setInterval` of its own (luci-app-podkop's log tailer does), and those kept hammering ubus in + * a background tab for as long as it stayed open. The registry that navigation already uses to + * clear them is enough to pause them too: cleared on hide, re-armed on show with the same + * callback and period, so a view that was polling every 3 s is polling every 3 s again and one + * that was cleared meanwhile stays cleared. */ + let _paused = []; + document.addEventListener('visibilitychange', () => { + if (document.hidden) { + _paused = []; + for (const [ id, spec ] of _viewIntervals) { + _paused.push(spec); + _ci.call(window, id); + _viewIntervals.delete(id); + } + } + else { + const back = _paused; + _paused = []; + for (const spec of back) window.setInterval(spec.fn, spec.ms, ...spec.rest); + } + }); })(); function clearViewIntervals() { /* `L.Poll.timer` is the id of LuCI's OWN 1 s tick, and it is private state — `add`/`remove`/ @@ -84,7 +109,8 @@ function clearViewIntervals() { return; } const keep = running ? L.Poll.timer : null; - _viewIntervals.forEach((id) => { if (id !== keep) window.clearInterval(id); }); + /* Map, not Set: the key is the timer id and the value is what it would take to re-arm it */ + _viewIntervals.forEach((spec, id) => { if (id !== keep) window.clearInterval(id); }); } /* ONE line per document whatever went wrong: this runs on every navigation, and a router that * cannot read L.Poll cannot read it on the next click either — a message per click would bury the diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-select.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-select.js index 967561153..c9d92b891 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-select.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-select.js @@ -3,6 +3,8 @@ 'require ui'; 'require dom'; 'require fs-fit as fit'; +/* for the content column's width without a layout read — see the mid-scroll branch in fitTables */ +'require fs-chrome as chrome'; /* Theme plain LuCI popup cannot be CSS-styled. @@ -503,10 +505,180 @@ function breakWidestColumn(t) { return false; } +/* ---- A TABLE THAT REPLACES A TABLE INHERITS ITS ANSWER ---- + * + * The measurement below has to strip a table's marks first (fs-fit rule 1: a stacked table is a pile + * of flex rows and always "fits"), and that lays the page out with a full-width table for the length + * of the pass — at 390px, several screens taller than the card stack it is about to be. Standing + * still nobody sees it. The poll REPLACES these tables rather than updating them, so every tick used + * to hand the fitter a fresh element with no marks and that intermediate happened again; on a remote + * router at iPhone width it threw the reader 612px out and back, twice per tick. + * + * Compensating for it was tried four ways and each was wrong somewhere; the changelog entry for this + * release records all four, because each looked right. This attacks the cause instead: the + * intermediate exists only because the answer was thrown away with the element, so the answer is + * kept on the SLOT. The slot is the section frame — `slotHome()` below says why it cannot be the + * table's own parent — and inside it a table is named by its id, or by its position among the + * tables of that frame when it has none. + * + * WHEN THE INHERITED ANSWER IS TRUSTED, and it is not "always". The tier depends on how many columns + * share the room and on how wide the room is, so both are remembered with it. Room is `roomFor()`, + * which reads the container rather than the table, so it is unaffected by the marks. The shape is + * the column count, read from the DOM — `shapeOf()` says why rows are deliberately not in it. + * + * A change in either one re-measures. So does the arrival of a table in a slot nobody has measured + * yet, and so does every full pass, which happens whenever the reader is not scrolling — that last + * one is what catches the case a column count cannot see, a value that grew long enough to change + * the tier, within a second of it happening and never during a scroll. + * + * WHAT IT COSTS. A tick on a table whose columns and room did not change writes its class names and + * reads one width, against stripping every mark, forcing a layout, reading `scrollWidth` and + * possibly walking the columns. Mid-scroll it does not even read the width: only tables with no + * answer at all are visited, and each is given one without measuring anything. */ +const _slots = new WeakMap(); + +/* THE SLOT IS THE FRAME, NOT THE PARENT, and the difference is the whole cache. A poll tick hands + * the container a freshly rendered subtree, so the table's immediate parent is usually new as well — + * keyed on that, every lookup missed and every tick measured from scratch, which is exactly the + * behaviour this was written to end (measured: the ±612px kept coming). What survives a tick is the + * frame the theme and luci-mod-status build once, `.cbi-section`; inside it a table is named by its + * id where it has one, and by its position among the tables of that frame where it does not. */ +function slotHome(t) { + return (t.closest && t.closest('.cbi-section, .cbi-section-node, #view')) || t.parentElement; +} + +function slotKey(t, home) { + if (t.id) return '#' + t.id; + const kin = home ? Array.from(home.querySelectorAll('.table')) : []; + const at = kin.indexOf(t); + return at >= 0 ? 'at' + at : 'lone'; +} + +/* WHAT CAN CHANGE THE ANSWER, AND WHAT CANNOT. The tier depends on how many columns have to share + * the room and on how wide the room is — not on how many rows there are. Rows were in this + * signature first and that was the bug behind a whole afternoon: a lease list gains and loses a row + * on almost every poll tick, so the signature changed every tick, the cache never hit, and every + * tick measured from scratch — which is the tall intermediate this exists to avoid. + * + * Read from the tree, never from layout: `children.length` is a DOM question, so asking it cannot + * force the layout the whole design is arranging not to force. */ +function shapeOf(t) { + const head = t.querySelector('.tr.table-titles, .cbi-section-table-titles') || t.firstElementChild; + return String(head ? head.children.length : 0); +} + +function applyDecision(t, d) { + /* the mark that lets the table into the layout at all — see theme/30-tables.css */ + t.classList.add('fs-fitted'); + t.classList.toggle('fs-stacked', !!d.stack); + t.classList.toggle('fs-drop-xs', !!d.drop); + if (d.breakCol !== undefined && d.breakCol !== -1) + markBreakColumn(t, t.querySelectorAll('.tr'), d.breakCol); +} + function fitTables() { - document.querySelectorAll(stackables()).forEach((t) => { + /* MID-SCROLL, ONLY THE TABLES THAT HAVE NO ANSWER YET. A table that already carries its answer + * needs nothing; one that does not is being held out of the layout by the stylesheet and cannot + * wait. Neither branch of this function reads layout while `scrolling()` is true. */ + const sel = fit.scrolling() ? inRoots('.table.fs-dt:not(.fs-fitted)', liveRoots()) : stackables(); + document.querySelectorAll(sel).forEach((t) => { + /* ---- WHILE THE READER SCROLLS, THIS PASS READS NOTHING ---- + * + * Every layout read here — `roomFor()` is one per table — forces the engine to lay the page + * out synchronously, and a poll tick lands once a second, so on a phone that is ten forced + * layouts in the middle of a flick. iOS runs the main thread sparingly during momentum + * scrolling exactly to keep the frame rate; work like this is what it is protecting against, + * and the reporter's word for the result was "shakes". A stock theme has no JS in this path + * at all, which is why the same page under luci-theme-bootstrap scrolls smoothly. + * + * So a pass that happens mid-scroll only WRITES: the answer this slot already has goes on the + * fresh table, and nothing is measured until the scrolling stops. A slot nobody has measured + * yet is judged from the window width instead of the container's — the one number available + * without touching layout, and at phone width it gives the same answer. */ + const home = slotHome(t); + const slots = home ? (_slots.get(home) || new Map()) : null; + const key = slots ? slotKey(t, home) : null; + const known = slots ? slots.get(key) : null; + + /* the answer without a measurement: the slot's, or — for a slot nobody has measured yet — + * the window's width, which is the one number available without touching layout. At the + * width where this matters the cheap judgement and the measured one agree. */ + /* MID-SCROLL THE ANSWER STILL GOES ON, and it must. Letting a freshly polled table wait for + * the scrolling to stop was tried on the device that has the fault: the reader then WATCHES + * the tables fold into cards under their thumb, and that fold is the hardest jerk of all. The + * answer is a write, it forces nothing, and it keeps the fresh table the same shape as the one + * it replaced. */ + if (fit.scrolling()) { + /* the column's width, not the window's: in the sidebar layout they differ by the sidebar, + * and an 800px window whose column is 520px used to clear CRAMPED and leave the table + * unstacked at full width, clipped by `.fs-main { overflow-x: clip }` until the reader + * held still. `chrome.contentWidth()` answers from memoised tokens and attributes — no + * layout is read here either. */ + applyDecision(t, known || { stack: chrome.contentWidth() < CRAMPED, drop: false, breakCol: -1 }); + fit.deferMeasurement(); + return; + } + + /* the column count, read from the tree: no layout is forced by asking */ + const shape = shapeOf(t); + + /* ---- THE ANSWER GOES ON BEFORE ANYTHING IS MEASURED, AND THAT ORDER IS THE FIX ---- + * + * `roomFor()` reads a clientWidth, which forces layout — and a fresh table from a poll tick + * is UNMARKED when it lands, so a pass that measured first laid the page out with a + * full-width table before it had said a word. That is the tall intermediate the engine + * re-anchors on: measured on a remote router at iPhone width, ±612px twice per tick, and it + * survived every attempt to compensate for it because the compensation ran after the layout + * that caused it. + * + * With the slot's answer applied first, the only layout this pass forces is one where the + * table already wears the answer it had a second ago. */ + if (known) applyDecision(t, known); + const was = t.classList.contains('fs-stacked'); - const wasDrop = t.classList.contains('fs-drop-xs'); + /* rounded, because `roomFor()` subtracts parsed padding and answers in fractions: comparing + * those exactly made the cache miss on a width that had not moved at all */ + const room = Math.round(fit.roomFor(t)); + if (!(room > 0)) { + /* Detached, hidden, or a dialog that is closed: keep what it had rather than decide + * against a width it does not have — but LET IT INTO THE LAYOUT anyway. The stylesheet + * keeps an unanswered table out of the flow (theme/30-tables.css), and a table whose + * section is collapsed when it arrives would otherwise stay hidden after the section is + * opened: nothing measures it again, because opening a section changes no width this + * file watches. A table with no room cannot move anything either way, so admitting it + * costs nothing and the next pass with room decides properly. */ + t.classList.add('fs-fitted'); + return; + } + + /* the answer this slot already has, for a table of the same shape in the same room — UNLESS the + * table has since outgrown it. Room and column count are not the whole input: a poll tick can + * put longer values into the same columns, and then a table that fitted a second ago does not. + * Measured on a live router at 900px, where the cache held: status_leases6 stood 1000px wide in + * an 810px column and wifi_assoclist_table 896px, neither carded, both quietly clipped by + * `.fs-main { overflow-x: clip }` — columns cut off with nothing to say so. The extra question + * is one the pass already has the layout for. */ + /* AND THE OTHER DIRECTION, WHICH THAT QUESTION CANNOT ASK. `overflows()` is put to a table + * that is already wearing its remedy, and every remedy makes a table fit by construction: a + * card is a pile of flex rows, `.fs-drop-xs` has hidden the expendable columns, a broken + * column shreds. So the answer is always "it fits", and a remedy applied once could never be + * lifted while the room and the column count held still — a one-way ratchet. The case is + * real: one station with a long hostname makes Associated Stations drop its `hide-xs` + * columns, and those columns stayed hidden after that station left, on a screen with room to + * spare and nothing to say a column existed. + * + * The only honest measurement is of a table with no remedy on it, and taking that on every + * tick would mean stripping the marks on every tick — the strip-measure-restore that lands as + * a visible relayout, which is what the deferral above exists to keep out of a scroll. So the + * re-decision is asked for by the CONTENT instead: a remedied table whose row count has gone + * DOWN has lost something, and losing something is the only way it can stop needing the + * remedy. Rows are counted from the tree, not the layout. A table that keeps its rows keeps + * its answer, which is what makes the poll cheap. */ + const rows = t.querySelectorAll('.tr').length; + const remedied = !!(known && (known.stack || known.drop || known.breakCol !== -1)); + const shrank = remedied && known.rows !== undefined && rows < known.rows; + if (known && known.room === room && known.shape === shape && !shrank && !fit.overflows(t)) + return; /* fs-fit rule 1: a stacked table is a pile of flex rows and always "fits", so reading * it as it stands un-stacks it and the next frame stacks it again — oscillation. Every @@ -515,15 +687,6 @@ function fitTables() { if (t._fsBreakCol !== undefined && t._fsBreakCol !== -1) markBreakColumn(t, t.querySelectorAll('.tr'), -1); - const room = fit.roomFor(t); - if (!(room > 0)) { - /* detached, hidden, or a dialog that is closed: keep what it had rather than decide - * against a width it does not have */ - if (was) t.classList.add('fs-stacked'); - if (wasDrop) t.classList.add('fs-drop-xs'); - return; - } - /* the one judgement a measurement cannot make, and the only number in this file */ let stack = room < CRAMPED; if (!stack && fit.overflows(t)) { @@ -533,6 +696,7 @@ function fitTables() { if (fit.overflows(t) && !breakWidestColumn(t)) stack = true; } + t.classList.add('fs-fitted'); /* write only on a real change: the poll re-renders these tables once a second, and * toggling the class off and on each tick would invalidate style for every row of * Processes/Leases for nothing */ @@ -544,6 +708,20 @@ function fitTables() { markBreakColumn(t, t.querySelectorAll('.tr'), -1); } else if (was) t.classList.remove('fs-stacked'); + + if (slots) { + slots.set(key, { + stack, + drop: t.classList.contains('fs-drop-xs'), + breakCol: (t._fsBreakCol === undefined) ? -1 : t._fsBreakCol, + room, + shape, + /* what the answer was decided over — a drop below this is the one signal that a + * remedy may no longer be needed (see the fast path above) */ + rows, + }); + _slots.set(home, slots); + } }); } @@ -616,6 +794,11 @@ function unreach(t) { } function fitScrollables() { + /* A layout read here lands in the middle of a flick once per poll tick, and that is the work iOS + * holds the main thread back to prevent — the same argument fitTables() makes above, and the + * reason the theme shook on a phone while a stock one did not. Put off until the page is still; + * fs-fit's sampler runs what was deferred the moment the scroll offset stops changing. */ + if (fit.scrolling()) { fit.deferMeasurement(); return; } document.querySelectorAll(scrollables()).forEach((t) => { const was = t.classList.contains('fs-xscroll'); const wasStack = t.classList.contains('fs-rowstack'); @@ -687,6 +870,11 @@ function fitScrollables() { * into — so wiping the pin cannot change the key and set this oscillating. It fires once per CHANGE, * never per tick, so it does not fight upstream for the pin on a polled page. */ function unpinActionColumn() { + /* A layout read here lands in the middle of a flick once per poll tick, and that is the work iOS + * holds the main thread back to prevent — the same argument fitTables() makes above, and the + * reason the theme shook on a phone while a stock one did not. Put off until the page is still; + * fs-fit's sampler runs what was deferred the moment the scroll offset stops changing. */ + if (fit.scrolling()) { fit.deferMeasurement(); return; } for (const t of document.querySelectorAll(inRoots('.table.cbi-section-table', liveRoots()))) { if (!t.querySelector('.cbi-section-actions')) continue; /* ---- and CLAIM upstream's resize hook, because under SPA navigation it is a leak ---- @@ -851,10 +1039,26 @@ return baseclass.extend({ }; scan(); + /* ARM THE STYLESHEET'S GATE FROM HERE, because this is the file that clears it. The rule in + * theme/30-tables.css holds an unanswered data table out of the layout, and `.fs-fitted` — + * the answer — is written nowhere but in this module. Arming it in fs-fit.js meant a document + * that loaded fs-fit and not this file (the footer requires them separately) hid every table + * forever. Raised here, one line before the pass that clears it is registered. */ + fit.armGate(); + /* A table must be TAGGED .fs-dt before it can be fitted, and re-tagged whenever the poll - * brings a fresh one back — so the two travel as one fitter, which fs-fit runs now, on - * every content mutation (synchronously, pre-paint) and on every resize of #view. */ - fit.add(() => { tagDataTables(); fitTables(); fitScrollables(); unpinActionColumn(); resyncValues(); }); + * brings a fresh one back — so tagging leads, and the passes that depend on it follow. + * + * FIVE REGISTRATIONS, NOT ONE CALLBACK. fs-fit catches per registered fitter, so a throw in + * one of these used to take the other four with it — and the first of them walks third-party + * markup, which is the shape most likely to surprise it. Bundled, a single throw in + * `tagDataTables()` left no table tagged, no table answered, and — with the gate above raised + * — a page with no tables on it at all. Registered separately, each pass fails alone. */ + fit.add(tagDataTables); + fit.add(fitTables); + fit.add(fitScrollables); + fit.add(unpinActionColumn); + fit.add(resyncValues); /* one scan per frame, however many mutations arrive (fit.frame — the theme's shared * coalescer) */ diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js index 451a69f9b..342b7354b 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js @@ -838,6 +838,24 @@ function rehostInvasiveSheets() { if (!universe) return; document.querySelectorAll(VIEW_SHEETS).forEach((el) => { if (el.dataset.fsLayered) return; + /* A SHEET WITH NO RULES YET IS NOT AN INNOCENT SHEET. `insertRule()` produces no mutation + * record of any kind, so an app that appends an empty