diff --git a/clashoo/Makefile b/clashoo/Makefile index 8f838e117..83140a310 100644 --- a/clashoo/Makefile +++ b/clashoo/Makefile @@ -6,13 +6,13 @@ PKG_UPSTREAM_TAG:=v$(PKG_UPSTREAM_VERSION) PKG_SHORT_SHA:=3f27ef3 PKG_VERSION:=2026.11.04.$(PKG_UPSTREAM_VERSION) -PKG_RELEASE:=24 +PKG_RELEASE:=25 PKG_SOURCE:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src -PKG_SOURCE_VERSION:=f03c662c952072d2e7bdae30e6ab5a0360606266 +PKG_SOURCE_VERSION:=3b0c0d7f9e5fa5d086fcd45cc211380ad6ccb077 PKG_HASH:=skip PKG_BUILD_VERSION:=$(PKG_UPSTREAM_TAG) diff --git a/dae/Makefile b/dae/Makefile index 59bde7c20..8d62c0f85 100644 --- a/dae/Makefile +++ b/dae/Makefile @@ -5,10 +5,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dae -PKG_VERSION:=2026.10.30 -PKG_RELEASE:=53 +PKG_VERSION:=2026.11.05 +PKG_RELEASE:=54 -PKG_SOURCE:=dae-src-2026.10.30-55c59e68c059.tar.gz +PKG_SOURCE:=dae-src-2026.11.05-7cf97ff42dc6.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/daed/Makefile b/daed/Makefile index 04e221940..ae25fad28 100644 --- a/daed/Makefile +++ b/daed/Makefile @@ -5,10 +5,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=daed -PKG_VERSION:=2026.10.30 -PKG_RELEASE:=65 +PKG_VERSION:=2026.11.05 +PKG_RELEASE:=66 -PKG_SOURCE:=daed-src-2026.10.30-1850c01d032c.tar.gz +PKG_SOURCE:=daed-src-2026.11.05-b1e30bc02200.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/istoreenhance/Makefile b/istoreenhance/Makefile index f573495a0..1d9af408b 100644 --- a/istoreenhance/Makefile +++ b/istoreenhance/Makefile @@ -11,8 +11,8 @@ PKG_ARCH_ISTOREENHANCE:=$(ARCH) PKG_NAME:=istoreenhance # use PKG_SOURCE_DATE instead of PKG_VERSION for compitable -PKG_SOURCE_DATE:=0.8.5 -PKG_RELEASE:=14 +PKG_SOURCE_DATE:=0.8.8 +PKG_RELEASE:=15 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) ARCH_HEXCODE=8664 @@ -88,11 +88,8 @@ define Package/$(PKG_NAME)/install $(INSTALL_BIN) ./files/istoreenhance.init $(1)/etc/init.d/istoreenhance $(INSTALL_BIN) ./files/istoreenhance.uci-default $(1)/etc/uci-defaults/istoreenhance $(INSTALL_DATA) ./files/kspeeder-plugin.json $(1)/usr/share/kspeeder/kspeeder-plugin.json - if [ -d "$(KSPEEDER_WEB_ROOT)" ] && [ -f "$(KSPEEDER_WEB_ROOT)/desktop-entry.js" ]; then \ + if [ -d "$(KSPEEDER_WEB_ROOT)" ] && [ -f "$(KSPEEDER_WEB_ROOT)/index.html" ]; then \ $(CP) $(KSPEEDER_WEB_ROOT)/* $(1)/usr/share/kspeeder/www/; \ - else \ - $(INSTALL_DATA) ./files/www/desktop-entry.js $(1)/usr/share/kspeeder/www/desktop-entry.js; \ - $(INSTALL_DATA) ./files/www/index.html $(1)/usr/share/kspeeder/www/index.html; \ fi $(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kspeeder/www/logo.png ln -sf /usr/share/kspeeder/kspeeder-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/20-kspeeder.json diff --git a/istoreenhance/files/kspeeder-plugin.json b/istoreenhance/files/kspeeder-plugin.json index e61e486b7..bd2fcf73b 100644 --- a/istoreenhance/files/kspeeder-plugin.json +++ b/istoreenhance/files/kspeeder-plugin.json @@ -5,9 +5,23 @@ "icon": "logo.png", "staticRoot": "/usr/share/kspeeder/www", "desktop": { - "mode": "module", - "entry": "desktop-entry.js", - "isolation": "shadow-dom" + "mode": "iframe", + "target": { + "scheme": "http", + "hostMode": "request-host", + "port": { + "default": 5003, + "keys": { + "uci": "istoreenhance.@istoreenhance[0].adminport" + } + }, + "path": "/" + }, + "access": { + "scope": "lan", + "blockedTitle": "请在局域网内打开 KSpeeder", + "blockedMessage": "KSpeeder 运行在设备的独立服务端口,请连接设备所在局域网后再打开。" + } }, "standalone": { "entry": "index.html", @@ -21,6 +35,14 @@ "path": "/" } }, + "config": { + "providerOrder": ["uci"], + "providers": { + "uci": { + "type": "uci" + } + } + }, "backend": { "type": "http", "scheme": "http", diff --git a/istoreenhance/files/www/desktop-entry.js b/istoreenhance/files/www/desktop-entry.js deleted file mode 100644 index 143d60afe..000000000 --- a/istoreenhance/files/www/desktop-entry.js +++ /dev/null @@ -1,260 +0,0 @@ -const stateByElement = new WeakMap(); - -function normalizeBasePath(path) { - const value = typeof path === "string" && path.trim() ? path.trim() : "/apps/kspeeder/"; - return value.endsWith("/") ? value : `${value}/`; -} - -function normalizeAPIBase(context) { - if (context && typeof context.apiBase === "string" && context.apiBase.trim()) { - return context.apiBase.endsWith("/") ? context.apiBase : `${context.apiBase}/`; - } - return `${normalizeBasePath(context && context.basePath)}api/`; -} - -function escapeHTML(value) { - return String(value == null ? "" : value).replace(/[&<>"']/g, (char) => ({ - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - })[char]); -} - -async function fetchJSON(url, options) { - const response = await fetch(url, { - credentials: "same-origin", - headers: { Accept: "application/json" }, - ...options, - }); - const text = await response.text(); - let payload = null; - if (text) { - try { - payload = JSON.parse(text); - } catch (error) { - throw new Error(`API returned non-JSON response (${response.status})`); - } - } - if (!response.ok) { - const message = payload && (payload.message || payload.error || payload.details); - throw new Error(message || `API request failed (${response.status})`); - } - return payload || {}; -} - -function mirrorCounts(overview) { - const mirrorsByProfile = overview && typeof overview.mirrors === "object" ? overview.mirrors : {}; - const result = { online: 0, total: 0, servedSpeed: "", servedDownload: "" }; - Object.values(mirrorsByProfile).forEach((profile) => { - const mirrors = Array.isArray(profile && profile.mirrors) ? profile.mirrors : []; - result.total += mirrors.length; - result.online += mirrors.filter((mirror) => mirror && mirror.status === "online").length; - if (!result.servedSpeed && profile && profile.served_speed) { - result.servedSpeed = profile.served_speed; - } - if (!result.servedDownload && profile && profile.served_download) { - result.servedDownload = profile.served_download; - } - }); - return result; -} - -function profileRows(overview) { - const mirrorsByProfile = overview && typeof overview.mirrors === "object" ? overview.mirrors : {}; - return Object.entries(mirrorsByProfile).map(([profile, status]) => { - const mirrors = Array.isArray(status && status.mirrors) ? status.mirrors : []; - const online = mirrors.filter((mirror) => mirror && mirror.status === "online").length; - const best = mirrors.find((mirror) => mirror && mirror.status === "online") || mirrors[0] || {}; - return ` - - ${escapeHTML(profile)} - ${online}/${mirrors.length} - ${escapeHTML(best.current_speed || best.test_speed || "-")} - ${escapeHTML(best.name || "-")} - ${escapeHTML(best.error_info || "-")} - - `; - }).join(""); -} - -function render(root, model) { - const counts = mirrorCounts(model.overview); - const source = model.overview && model.overview.source ? model.overview.source : "-"; - const error = model.error ? `
${escapeHTML(model.error)}
` : ""; - const refreshing = model.refreshing ? "disabled" : ""; - const rows = profileRows(model.overview); - root.innerHTML = ` - -
-
-
-
-

KSpeeder

-
Docker 镜像下载加速状态
-
-
- - -
-
- ${error} -
-
版本
${escapeHTML(model.summary.version || "-")}
-
可用节点
${counts.online}/${counts.total}
-
当前下发
${escapeHTML(counts.servedSpeed || "-")}
-
累计下发
${escapeHTML(counts.servedDownload || "-")}
-
-
-
镜像节点${escapeHTML(source)}
- ${rows ? ` - - - - - - - - - - - ${rows} -
类型在线速度节点错误
- ` : '
暂无镜像状态,确认 iStoreEnhance 服务已启动并已配置缓存目录。
'} -
-
-
- `; -} - -async function loadModel(state) { - const [summary, overview] = await Promise.all([ - fetchJSON(`${state.apiBase}summary`), - fetchJSON(`${state.apiBase}mirrors/overview`), - ]); - state.model.summary = summary; - state.model.overview = overview; - state.model.error = ""; -} - -async function reload(state) { - try { - await loadModel(state); - } catch (error) { - state.model.error = error instanceof Error ? error.message : "加载失败"; - } finally { - render(state.root, state.model); - } -} - -async function refreshMirrors(state) { - state.model.refreshing = true; - state.model.error = ""; - render(state.root, state.model); - try { - await fetchJSON(`${state.apiBase}mirrors/refresh`, { method: "POST" }); - await loadModel(state); - if (state.hostAdapter && state.hostAdapter.toast) { - state.hostAdapter.toast.success("KSpeeder 测速已刷新"); - } - } catch (error) { - state.model.error = error instanceof Error ? error.message : "刷新测速失败"; - if (state.hostAdapter && state.hostAdapter.toast) { - state.hostAdapter.toast.error(state.model.error); - } - } finally { - state.model.refreshing = false; - render(state.root, state.model); - } -} - -export async function bootstrap() {} - -export async function mount(props) { - const root = props && props.domElement; - if (!root) { - return; - } - const context = props.context || {}; - const state = { - root, - apiBase: normalizeAPIBase(context), - hostAdapter: props.hostAdapter, - model: { - summary: {}, - overview: {}, - error: "", - refreshing: false, - }, - }; - stateByElement.set(root, state); - root.addEventListener("click", handleClick); - render(root, state.model); - await reload(state); -} - -export async function unmount(props) { - const root = props && props.domElement; - if (!root) { - return; - } - root.removeEventListener("click", handleClick); - root.innerHTML = ""; - stateByElement.delete(root); -} - -function handleClick(event) { - const target = event.target && event.target.closest ? event.target.closest("[data-action]") : null; - if (!target) { - return; - } - const root = event.currentTarget; - const state = stateByElement.get(root); - if (!state) { - return; - } - const action = target.getAttribute("data-action"); - if (action === "reload") { - void reload(state); - } else if (action === "refresh-mirrors") { - void refreshMirrors(state); - } -} - -export default { bootstrap, mount, unmount }; diff --git a/istoreenhance/files/www/index.html b/istoreenhance/files/www/index.html deleted file mode 100644 index bae0337c1..000000000 --- a/istoreenhance/files/www/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - KSpeeder - - - -
- - - diff --git a/ks-cli/Makefile b/ks-cli/Makefile index 0edd76959..98eeb886f 100644 --- a/ks-cli/Makefile +++ b/ks-cli/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_ARCH_KS_CLI:=$(ARCH) PKG_NAME:=ks-cli -PKG_VERSION:=0.8.7 -PKG_RELEASE:=4 +PKG_VERSION:=0.8.8 +PKG_RELEASE:=5 PKG_SOURCE:=ks-cli-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/kspeeder/docker_kspeeder/releases/download/v$(PKG_VERSION)/ diff --git a/luci-app-ipsec-server/Makefile b/luci-app-ipsec-server/Makefile index 087812f25..58415dac1 100644 --- a/luci-app-ipsec-server/Makefile +++ b/luci-app-ipsec-server/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-ipsec-server PKG_VERSION:=20260807 -PKG_RELEASE:=3 +PKG_RELEASE:=5 PKG_MAINTAINER:=Lienol diff --git a/luci-app-istoreenhance/Makefile b/luci-app-istoreenhance/Makefile index 929aac162..f50d0755a 100644 --- a/luci-app-istoreenhance/Makefile +++ b/luci-app-istoreenhance/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for KSpeeder LUCI_DEPENDS:=+istoreenhance +luci-lib-linkeaseauth +linkease-app-entry LUCI_PKGARCH:=all -PKG_VERSION:=0.8.5-r1 -PKG_RELEASE:=8 +PKG_VERSION:=0.8.8-r1 +PKG_RELEASE:=9 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-open-box/Makefile b/luci-app-open-box/Makefile index 9ccdc5090..978956cf6 100644 --- a/luci-app-open-box/Makefile +++ b/luci-app-open-box/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-open-box -PKG_VERSION:=0.1.411 -PKG_RELEASE:=66 +PKG_VERSION:=0.1.412 +PKG_RELEASE:=67 PKG_MAINTAINER:=liandu2024 PKG_LICENSE:=GPL-3.0-or-later diff --git a/luci-app-vantage/Makefile b/luci-app-vantage/Makefile index 12ddc2db6..4e3c3adb9 100644 --- a/luci-app-vantage/Makefile +++ b/luci-app-vantage/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-vantage PKG_VERSION:=1.0.15 -PKG_RELEASE:=27 +PKG_RELEASE:=28 PKG_LICENSE:=GPL-3.0-or-later LUCI_TITLE:=Vantage dashboard diff --git a/luci-app-vantage/htdocs/luci-static/resources/vantage/layout.js b/luci-app-vantage/htdocs/luci-static/resources/vantage/layout.js index 074739dae..da9337e61 100644 --- a/luci-app-vantage/htdocs/luci-static/resources/vantage/layout.js +++ b/luci-app-vantage/htdocs/luci-static/resources/vantage/layout.js @@ -106,6 +106,45 @@ return baseclass.extend({ return out; }, + /* the option of a layout in /etc/config/vantage_theme */ + option: function(key) { return 'layout_' + key.replace('-', '_'); }, + + /* a layout as that option's value: 'hero:0:4 chart:0:2:h' */ + encode: function(list) { + return list.map(function(e) { return e.id + ':' + e.c + ':' + e.w + (e.hide ? ':h' : ''); }).join(' '); + }, + + /* the template's data-vt-look-layout, 'wide=hero:0:4 chart:0:2:h;mid=default', + as { wide: [ ... ], mid: null }: null is the default layout. Lists go + through normalize like any stored layout. */ + decode: function(text) { + var out = Object.create(null); + String(text || '').split(';').forEach(function(part) { + var m = /^(wide|mid|narrow)(_wired)?=(.+)$/.exec(part); + if (!m) return; + out[m[1] + (m[2] ? '-wired' : '')] = m[3] === 'default' ? null : m[3].split(' ').map(function(t) { + var f = t.split(':'), e = { id: f[0], c: int(f[1], 0), w: int(f[2], 1) }; + if (f[3] === 'h') e.hide = true; + return e; + }); + }); + return out; + }, + + /* this browser's layouts with the router's (decode): the router's + first for a login that may save there, for any other only where + this browser has none */ + merge: function(mine, saved, first) { + var out = Object.create(null); + Object.keys(mine).forEach(function(k) { out[k] = mine[k]; }); + Object.keys(saved).forEach(function(k) { + if (!first && own(out, k)) return; + if (saved[k]) out[k] = saved[k]; + else delete out[k]; + }); + return out; + }, + /* what is worth storing */ compact: function(list) { return list.map(function(e) { var o = { id: e.id, c: e.c, w: e.w }; if (e.hide) o.hide = true; return o; }); diff --git a/luci-app-vantage/htdocs/luci-static/resources/vantage/series.js b/luci-app-vantage/htdocs/luci-static/resources/vantage/series.js index af8b65c8f..08aa99d15 100644 --- a/luci-app-vantage/htdocs/luci-static/resources/vantage/series.js +++ b/luci-app-vantage/htdocs/luci-static/resources/vantage/series.js @@ -123,6 +123,14 @@ return baseclass.extend({ Linear scales never go below CHART_FLOOR, so an idle link stays a flat line, and round up with niceCeil. */ CHART_STYLES: [ 'overlay', 'log', 'mirror', 'mirror-split', 'lanes' ], + + /* the style in force: the router's first for a login that may save + there, for any other only where this browser has none */ + chartPick: function(saved, mine, first) { + var ok = this.CHART_STYLES; + if (ok.indexOf(saved) >= 0 && (first || ok.indexOf(mine) < 0)) return saved; + return ok.indexOf(mine) >= 0 ? mine : ok[0]; + }, CHART_FLOOR: 1e4, chartGeom: function(style, peakDn, peakUp) { diff --git a/luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js b/luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js index d18f03102..f521c5b3b 100644 --- a/luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js +++ b/luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js @@ -490,8 +490,25 @@ function writeFolds(v) { try { window.localStorage.setItem(FOLD_KEY, JSON.stringify(v)); } catch (e) {} } -/* Tile layouts the viewer arranged, per screen class, in this browser; - vantage.layout validates whatever comes back */ +/* What the Vantage theme's template hands over (data-vt-look-*): under it + the router keeps the layouts and the chart style with the Appearance */ +function lookAttr(name) { + var root = typeof document !== 'undefined' ? document.documentElement : null; + return (root && root.getAttribute ? root.getAttribute(name) : null) || ''; +} + +function lookSaves() { return lookAttr('data-vt-look-save') === 'yes'; } + +/* Done hands the theme what changed; true if it took it (a login that may + save). Without it, or for any other login, it stays in this browser. */ +function offerView(values, done) { + var ev = null; + try { ev = new CustomEvent('vantage:view-save', { detail: { values: values, done: done }, cancelable: true }); } catch (e) { ev = null; } + return !!ev && typeof window.dispatchEvent === 'function' && !window.dispatchEvent(ev); +} + +/* Tile layouts the viewer arranged, per screen class, this browser's copy + of them and the router's; vantage.layout validates whatever comes back */ var LAYOUT_KEY = 'vantage.layout.v1'; function readLayouts() { @@ -500,7 +517,7 @@ function readLayouts() { var out = Object.create(null); if (v && typeof v === 'object' && !Array.isArray(v)) Object.keys(v).forEach(function(k) { if (/^(wide|mid|narrow)(-wired)?$/.test(k) && Array.isArray(v[k])) out[k] = v[k]; }); - return out; + return layout.merge(out, layout.decode(lookAttr('data-vt-look-layout')), lookSaves()); } function writeLayouts(v) { @@ -511,33 +528,42 @@ function writeLayouts(v) { } /* The throughput chart style the viewer picked (series.CHART_STYLES), - in this browser */ + this browser's copy of it and the router's */ var CHART_KEY = 'vantage.chart.v1'; function readChartStyle() { var v = null; try { v = window.localStorage.getItem(CHART_KEY); } catch (e) { v = null; } - return series.CHART_STYLES.indexOf(v) >= 0 ? v : series.CHART_STYLES[0]; + return series.chartPick(lookAttr('data-vt-look-chart'), v, lookSaves()); } function writeChartStyle(v) { try { - if (v === series.CHART_STYLES[0]) window.localStorage.removeItem(CHART_KEY); + /* the default needs no entry, unless the router has another */ + if (v === series.CHART_STYLES[0] && !lookAttr('data-vt-look-chart')) window.localStorage.removeItem(CHART_KEY); else window.localStorage.setItem(CHART_KEY, v); } catch (e) {} } -/* The network path's backdrop the viewer picked (backdrop.STYLES), in - this browser */ +/* The network path's backdrop the viewer picked (backdrop.STYLES). Under + the Vantage theme its Appearance decides (saved for every browser on + the router where the viewer may) and keeps the one in force in + data-vt-backdrop; elsewhere this browser keeps it. */ var BACKDROP_KEY = 'vantage.backdrop.v1'; function readBackdrop() { - var v = null; + var root = typeof document !== 'undefined' ? document.documentElement : null; + var v = root && root.getAttribute ? root.getAttribute('data-vt-backdrop') : null; + if (backdrop.STYLES.indexOf(v) >= 0) return v; try { v = window.localStorage.getItem(BACKDROP_KEY); } catch (e) { v = null; } return backdrop.STYLES.indexOf(v) >= 0 ? v : backdrop.STYLES[0]; } function writeBackdrop(v) { + /* the theme takes it (and cancels the event) */ + var ev = null; + try { ev = new CustomEvent('vantage:backdrop-set', { detail: v, cancelable: true }); } catch (e) { ev = null; } + if (ev && typeof window.dispatchEvent === 'function' && !window.dispatchEvent(ev)) return; try { if (v === backdrop.STYLES[0]) window.localStorage.removeItem(BACKDROP_KEY); else window.localStorage.setItem(BACKDROP_KEY, v); @@ -728,7 +754,7 @@ return view.extend({ this.backdropStyle = readBackdrop(); /* picked under the theme's Appearance (menu-vantage.js), here or in another tab */ - var self = this, follow = function() { self.setBackdrop(readBackdrop()); }; + var self = this, follow = function() { self.showBackdrop(readBackdrop()); }; if (window.addEventListener) { window.addEventListener('vantage:backdrop', follow); window.addEventListener('storage', function(ev) { if (ev.key === BACKDROP_KEY) follow(); }); @@ -1283,6 +1309,7 @@ return view.extend({ }, setEditing: function(on) { + if (!on && this.editing && this.saveView()) return; this.editing = !!on; this.el.root.classList.toggle('vt-editing', this.editing); this.el.layoutBtn.setAttribute('aria-pressed', String(this.editing)); @@ -1291,10 +1318,48 @@ return view.extend({ at once, nothing held from the other mode */ this.held = Object.create(null); this.doLayout(); - if (this.editing) this.el.editDone.focus(); + if (this.editing) { + this.viewStart = this.viewValues(); + this.editNote(lookAttr('data-vt-look-save') === 'relogin' ? _('Log in again to save this for every browser.') : ''); + this.el.editDone.focus(); + } else this.el.layoutBtn.focus(); }, + editNote: function(text) { + this.el.editNote.hidden = !text; + txt(this.el.editNote, text); + }, + + /* the options of /etc/config/vantage_theme this dashboard stands for */ + viewValues: function() { + var self = this, out = { chart: this.chartStyle }; + [ 'wide', 'mid', 'narrow' ].forEach(function(tier) { + [ false, true ].forEach(function(wired) { + var k = layout.key(tier, wired); + out[layout.option(k)] = self.layouts[k] ? layout.encode(self.layouts[k]) : 'default'; + }); + }); + return out; + }, + + /* Done: what changed goes to the theme in one write. True while that + runs: Customize closes when it is saved, and stays open with a note + if it was not, so the pick can be saved again. */ + saveView: function() { + var self = this, now = this.viewValues(), then = this.viewStart || {}, out = {}; + if (this.viewSaving) return true; + Object.keys(now).forEach(function(k) { if (now[k] !== then[k]) out[k] = now[k]; }); + if (!Object.keys(out).length) return false; + this.viewSaving = offerView(out, function(ok) { + self.viewSaving = false; + if (!ok) { self.editNote(_('Could not save this for every browser. Try again.')); return; } + self.viewStart = now; + self.setEditing(false); + }); + return this.viewSaving; + }, + /* the throughput chart style, picked under Customize */ buildChartPick: function() { var self = this, names = { @@ -1322,10 +1387,18 @@ return view.extend({ return E('div', { 'class': 'vt-edit-field' }, [ E('label', { 'for': 'vt-backdrop-style' }, [ _('Network path background') ]), pick ]); }, + /* picked here (Customize): saved, and shown */ setBackdrop: function(v) { if (backdrop.STYLES.indexOf(v) < 0 || v === this.backdropStyle) return; - this.backdropStyle = v; writeBackdrop(v); + this.showBackdrop(v); + }, + + /* picked elsewhere (the theme's Appearance, another tab): shown only, + never saved back */ + showBackdrop: function(v) { + if (backdrop.STYLES.indexOf(v) < 0 || v === this.backdropStyle) return; + this.backdropStyle = v; if (this.backdrop) this.backdrop.style(v); if (this.backdropPick && this.backdropPick.value !== v) this.backdropPick.value = v; }, @@ -1341,10 +1414,11 @@ return view.extend({ buildEditBar: function() { var self = this, el = this.el; el.editHint = E('span', { 'class': 'vt-hint' }); + el.editNote = E('span', { 'class': 'vt-hint', 'role': 'status', 'hidden': 'hidden' }); el.editHidden = E('div', { 'class': 'vt-edit-hidden' }); el.editSay = E('span', { 'class': 'vt-sr', 'role': 'status', 'aria-live': 'polite' }); el.editBar = E('div', { 'class': 'vt-editbar', 'role': 'region', 'aria-label': _('Customize the dashboard'), 'hidden': 'hidden' }, [ - E('div', { 'class': 'vt-editbar-text' }, [ E('strong', {}, [ _('Customize the dashboard') ]), el.editHint ]), + E('div', { 'class': 'vt-editbar-text' }, [ E('strong', {}, [ _('Customize the dashboard') ]), el.editHint, el.editNote ]), el.editHidden, E('div', { 'class': 'vt-edit-picks' }, [ this.buildChartPick(), this.buildBackdropPick() ]), E('div', { 'class': 'vt-editbar-actions' }, [ @@ -1417,9 +1491,10 @@ return view.extend({ var self = this, l = this.lay; if (!l) return; var shown = l.list.filter(function(e) { return !e.hide; }); - txt(this.el.editHint, l.tier === 'wide' ? _('Drag a tile by its handle or use its buttons. Saved in this browser for wide screens.') - : l.tier === 'mid' ? _('Drag a tile by its handle or use its buttons. Saved in this browser for medium screens.') - : _('Drag a tile by its handle or use its buttons. Saved in this browser for narrow screens.')); + var every = lookSaves(); + txt(this.el.editHint, l.tier === 'wide' ? (every ? _('Drag a tile by its handle or use its buttons. Done saves it for wide screens in every browser.') : _('Drag a tile by its handle or use its buttons. Saved in this browser for wide screens.')) + : l.tier === 'mid' ? (every ? _('Drag a tile by its handle or use its buttons. Done saves it for medium screens in every browser.') : _('Drag a tile by its handle or use its buttons. Saved in this browser for medium screens.')) + : every ? _('Drag a tile by its handle or use its buttons. Done saves it for narrow screens in every browser.') : _('Drag a tile by its handle or use its buttons. Saved in this browser for narrow screens.')); this.el.root.classList.toggle('vt-edit-1col', l.cols === 1); shown.forEach(function(e, i) { var o = self.ov[e.id]; diff --git a/luci-app-vantage/po/templates/vantage.pot b/luci-app-vantage/po/templates/vantage.pot index 5e94bf2dc..19861a5b8 100644 --- a/luci-app-vantage/po/templates/vantage.pot +++ b/luci-app-vantage/po/templates/vantage.pot @@ -1,7 +1,7 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3446 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3521 msgid "%d MHz (%d–%d MHz)" msgstr "" @@ -29,19 +29,19 @@ msgid_plural "%d SSIDs · %d idle" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1547 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1622 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2090 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2641 msgid "%d clients" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2978 msgid "%d connected" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2042 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2046 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2902 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2117 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2121 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2977 msgid "%d devices" msgstr "" @@ -67,11 +67,11 @@ msgctxt "vantage" msgid "%d min ago" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2901 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2976 msgid "%d of %d" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1434 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1509 msgid "%d of %d columns" msgstr "" @@ -101,7 +101,7 @@ msgid_plural "%d radios up" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2558 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2633 msgid "%d radios" msgstr "" @@ -125,7 +125,7 @@ msgstr "" msgid "%d weak" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2577 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2652 msgid "%d–%d MHz of the %d–%d MHz band" msgstr "" @@ -143,7 +143,7 @@ msgstr "" msgid "%s (IPv%d)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "%s (new this session)" msgstr "" @@ -154,10 +154,10 @@ msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/fmt.js:166 #: luci-app-vantage/htdocs/luci-static/resources/vantage/wifi.js:103 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2584 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2598 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3000 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2659 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2673 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3075 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 msgid "%s MHz" msgstr "" @@ -176,13 +176,13 @@ msgid "%s at %s; below %s roaming and throughput suffer" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:83 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2334 msgctxt "vantage" msgid "%s available" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2604 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2679 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "%s dBm" msgstr "" @@ -194,13 +194,13 @@ msgstr "" msgid "%s device on a newer radio; uses more airtime per byte" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3473 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3548 msgid "%s error" msgid_plural "%s errors" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3235 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 msgid "%s experience" msgstr "" @@ -216,11 +216,11 @@ msgstr "" msgid "%s has no carrier: cable unplugged or switch port down" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1401 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1475 msgid "%s hidden" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3517 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3592 msgid "%s in · %s out" msgstr "" @@ -236,7 +236,7 @@ msgstr "" msgid "%s is in no zone and accepts every connection" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1394 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1468 msgid "%s is narrower" msgstr "" @@ -244,17 +244,17 @@ msgstr "" msgid "%s is not up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3034 msgid "" "%s is shared by %d devices (a switch or another access point behind it); its " "%s link is not theirs" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2958 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3033 msgid "%s is shared by %d devices behind the switch" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1397 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1471 msgid "%s is wider" msgstr "" @@ -270,23 +270,23 @@ msgstr "" msgid "%s may open the router's admin" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1515 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1590 msgid "%s moved" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1391 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1465 msgid "%s moved down" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1456 msgid "%s moved left" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1385 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1459 msgid "%s moved right" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1388 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1462 msgid "%s moved up" msgstr "" @@ -299,9 +299,9 @@ msgid "%s negotiated only %d Mbit/s; a cable pair or port may be faulty" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:84 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2260 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3543 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2335 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2364 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3618 msgid "%s of %s" msgstr "" @@ -322,21 +322,21 @@ msgstr "" msgid "%s of frames to the device fail; interference likely" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3541 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3616 msgid "%s over %d core" msgid_plural "%s over %d cores" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2353 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2428 msgid "%s radio" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3273 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3348 msgid "%s sent · %s retried · %s failed" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1440 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1515 msgid "%s shown" msgstr "" @@ -352,11 +352,11 @@ msgstr "" msgid "%s used" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2372 msgid "%s used of %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2956 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3031 msgid "%s · %d devices" msgstr "" @@ -364,7 +364,7 @@ msgstr "" msgid "%s · %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3265 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3340 msgid "%s · channel %d · %d MHz" msgstr "" @@ -380,27 +380,27 @@ msgstr "" msgid "%s: no carrier" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "(configured %d dBm, limited by regulatory rules)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2014 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3092 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2089 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3167 msgid "(hidden)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1547 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1622 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2090 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2641 msgid "1 client" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2978 msgid "1 connected" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2046 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2902 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2121 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2977 msgid "1 device" msgstr "" @@ -408,7 +408,7 @@ msgstr "" msgid "1 older device (Wi-Fi 4 or earlier) slows airtime" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2558 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2633 msgid "1 radio" msgstr "" @@ -436,20 +436,20 @@ msgstr "" msgid "60 GHz" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2766 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2841 msgid "Active" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Address type" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3506 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3581 msgid "Addresses" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2606 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2681 msgid "Airtime" msgstr "" @@ -458,8 +458,8 @@ msgctxt "vantage" msgid "Alias" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2757 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2763 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2832 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 msgid "All" msgstr "" @@ -488,7 +488,7 @@ msgstr "" msgid "Busiest radio: %s of Wi-Fi traffic" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2224 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2299 msgid "Busy share of each CPU core" msgstr "" @@ -504,8 +504,8 @@ msgstr[1] "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:71 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:72 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2217 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3541 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2292 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3616 msgctxt "vantage" msgid "CPU" msgstr "" @@ -514,78 +514,78 @@ msgstr "" msgid "Cache (reclaimable)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3382 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3457 msgid "Cancel" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3260 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3335 msgctxt "vantage" msgid "Capabilities" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgid "Carrier" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3446 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3521 msgid "Centre frequency" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2597 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2672 msgid "Ch %d" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1995 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2565 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2070 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2640 msgid "Ch %d · %d MHz" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 msgid "Channel" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1995 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2070 msgid "Channel —" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2630 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2705 msgctxt "vantage" msgid "Clear filter" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2603 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2648 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2649 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2678 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2723 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2724 msgid "Clients" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3453 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3528 msgid "Clients on this radio" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3109 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3184 msgid "Close" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3015 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3090 msgid "Connected" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3060 msgid "Connected after you opened this page" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3266 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3341 msgid "Connected for" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3263 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3294 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3338 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3369 msgid "Connection" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2251 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2326 msgid "Core %d: %s" msgstr "" @@ -593,15 +593,19 @@ msgstr "" msgid "Could not read the firewall configuration" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3365 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3440 msgid "Could not save the name (no permission or the device refused it)." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1356 +msgid "Could not save this for every browser. Try again." +msgstr "" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3589 msgid "Counters since boot" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3451 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3526 msgid "Country" msgstr "" @@ -610,13 +614,13 @@ msgid "" "Custom rule files are configured (%s); rules in them are not listed here." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1536 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1611 msgid "Customize" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1346 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1347 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1535 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1610 msgid "Customize the dashboard" msgstr "" @@ -624,16 +628,16 @@ msgstr "" msgid "DHCP" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3322 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3397 msgid "DHCP hostname" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:42 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3512 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3587 msgid "DNS" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1927 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2002 msgid "DNS %s" msgstr "" @@ -642,55 +646,55 @@ msgstr "" msgid "Dashboard" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2930 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3532 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3005 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3607 msgid "Device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3349 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3424 msgid "Device name" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3378 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3453 msgid "Device type" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2916 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2991 msgid "" "Devices on the Ethernet ports appear here once they send traffic; the bridge " "forgets quiet ones after about five minutes." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1996 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgid "Disabled" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3229 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 msgid "Disconnected %s; shown from the last sample." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1360 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1434 msgctxt "vantage" msgid "Done" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:45 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1996 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgctxt "vantage" msgid "Down" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2330 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2425 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2405 #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2500 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2575 msgid "Download" msgstr "" @@ -698,39 +702,57 @@ msgstr "" msgid "Download (to clients)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3271 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3346 msgctxt "vantage" msgid "Downloaded" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1496 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for medium " +"screens in every browser." +msgstr "" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1497 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for narrow " +"screens in every browser." +msgstr "" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1495 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for wide screens " +"in every browser." +msgstr "" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1496 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for " "medium screens." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1422 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1497 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for " "narrow screens." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1495 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for wide " "screens." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1373 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1447 msgid "Drag to move" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3517 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3592 msgctxt "vantage" msgid "Dropped" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgid "Edit" msgstr "" @@ -738,7 +760,7 @@ msgstr "" msgid "Enhanced Open (OWE)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1599 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1674 msgid "Error" msgstr "" @@ -752,8 +774,8 @@ msgctxt "vantage" msgid "Excellent" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3009 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3084 msgid "Experience" msgstr "" @@ -771,20 +793,20 @@ msgstr "" msgid "Fair signal %s; lower rates at range" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2627 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2828 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2702 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 msgid "Filter by name, address, SSID…" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2828 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 msgid "Filter by name, address, port…" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2628 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2703 msgid "Filter clients" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3535 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3610 msgctxt "vantage" msgid "Firmware" msgstr "" @@ -797,7 +819,7 @@ msgstr "" msgid "Forwarding is accepted by default" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3273 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3348 msgid "Frames to device" msgstr "" @@ -806,15 +828,15 @@ msgctxt "vantage" msgid "Free" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3258 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3333 msgid "From device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2998 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3073 msgid "From device: %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3568 msgid "From network" msgstr "" @@ -824,9 +846,9 @@ msgid "" "files are not shown." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1925 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2950 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3509 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2000 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3025 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3584 msgid "Gateway" msgstr "" @@ -839,7 +861,7 @@ msgstr "" msgid "General Settings" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3334 msgctxt "vantage" msgid "Generation" msgstr "" @@ -849,13 +871,13 @@ msgctxt "vantage" msgid "GiB" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Globally unique" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Globally unique · %s" msgstr "" @@ -873,7 +895,7 @@ msgstr "" msgid "Good signal %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "Grid packets" msgstr "" @@ -889,36 +911,36 @@ msgstr "" msgid "Half duplex" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1045 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1071 msgctxt "vantage" msgid "Health checks" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1437 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3092 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1512 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3167 msgctxt "vantage" msgid "Hidden" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1400 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1474 msgid "Hide %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3278 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3353 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3385 msgid "IP addresses" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3507 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3582 msgid "IPv4" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3508 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3583 msgid "IPv6" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3275 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3307 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3350 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3382 msgid "Identity" msgstr "" @@ -926,7 +948,7 @@ msgstr "" msgid "In no zone: the default policies apply." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3504 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3579 msgid "In the tunnel" msgstr "" @@ -940,21 +962,21 @@ msgctxt "vantage" msgid "Input" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1974 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2049 msgid "Interface" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3501 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3576 msgid "Interface up for" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3292 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3479 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3367 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3554 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3566 msgid "Interfaces" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1925 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2000 msgid "Internet" msgstr "" @@ -980,11 +1002,11 @@ msgid "" "itself." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3536 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3611 msgid "Kernel" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2378 msgid "Kernel %s" msgstr "" @@ -993,58 +1015,58 @@ msgctxt "vantage" msgid "KiB" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2717 msgid "Kind of client" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3267 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3342 msgctxt "vantage" msgid "Last activity" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2839 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2974 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2914 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3049 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3380 msgid "Last heard" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1358 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1432 msgid "Layout reset" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3059 msgid "Left %s" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:174 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2986 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3061 msgctxt "vantage" msgid "Legacy" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2954 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3256 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3497 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3029 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3331 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3572 msgctxt "vantage" msgid "Link" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2997 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3072 msgid "Link rate" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2965 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3002 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3040 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3077 msgid "Live" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3540 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3615 msgid "Load" msgstr "" @@ -1060,23 +1082,27 @@ msgid_plural "Load %s · %d cores" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3542 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3617 msgctxt "vantage" msgid "Load average" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2205 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2280 msgid "Load average over 1, 5 and 15 minutes" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2241 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2316 msgid "Load avg %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3538 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3613 msgid "Local time" msgstr "" +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1323 +msgid "Log in again to save this for every browser." +msgstr "" + #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:164 msgid "Low link rate %s despite good signal; interference or an old device" msgstr "" @@ -1089,8 +1115,8 @@ msgstr "" msgid "MAC" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3276 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3308 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3351 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3383 msgid "MAC address" msgstr "" @@ -1098,11 +1124,11 @@ msgstr "" msgid "MCS %d" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1393 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1467 msgid "Make %s narrower" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1396 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1470 msgid "Make %s wider" msgstr "" @@ -1119,11 +1145,11 @@ msgid "Measuring…" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:83 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2228 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2303 msgid "Memory" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3543 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3618 msgid "Memory in use" msgstr "" @@ -1132,63 +1158,63 @@ msgctxt "vantage" msgid "MiB" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1368 msgid "Mirrored" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1369 msgid "Mirrored, scale per direction" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3445 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3520 msgid "Mode" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3533 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3608 msgid "Model" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1390 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1464 msgid "Move %s down" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1381 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1455 msgid "Move %s left" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1384 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1458 msgid "Move %s right" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1387 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1461 msgid "Move %s up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1373 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1447 msgid "Move %s: drag, or use the arrow keys" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3377 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3452 msgid "Name" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:134 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3417 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3492 msgid "Name contains invisible or control characters" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3279 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3311 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3354 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3386 msgid "Name from" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2935 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3010 msgid "Name from: %s" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:132 #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:137 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3418 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 msgid "Name is longer than %d characters" msgstr "" @@ -1196,27 +1222,27 @@ msgstr "" msgid "Name must be text" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3220 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3289 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3364 msgid "Name this device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2964 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2994 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3264 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3069 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3339 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3379 msgid "Network" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1713 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1714 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1788 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1789 msgid "Network path" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1322 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1387 msgid "Network path background" msgstr "" @@ -1224,13 +1250,13 @@ msgstr "" msgid "Networks: %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2768 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2843 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3060 msgctxt "vantage" msgid "New" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1872 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1947 msgid "No SSIDs" msgstr "" @@ -1238,24 +1264,24 @@ msgstr "" msgid "No clients" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2918 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3458 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2993 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3533 msgid "No clients connected" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3121 msgid "No clients connected." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2909 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 msgid "No clients in this view" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2909 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 msgid "No clients match “%s”" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1926 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2001 msgctxt "vantage" msgid "No default route" msgstr "" @@ -1264,7 +1290,7 @@ msgstr "" msgid "No interface with a route" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3483 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3558 msgid "No interface with a route is up." msgstr "" @@ -1273,7 +1299,7 @@ msgid "No internet-facing zone found" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:47 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgid "No link" msgstr "" @@ -1281,7 +1307,7 @@ msgstr "" msgid "No network interface with a route is up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1853 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1928 msgid "No other interfaces are up" msgstr "" @@ -1291,7 +1317,7 @@ msgid "No problems detected" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:105 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1876 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1951 msgid "No radios reported" msgstr "" @@ -1308,16 +1334,16 @@ msgstr "" msgid "No stations are associated right now" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2990 msgid "No wired devices heard" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3080 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3155 msgctxt "vantage" msgid "No wireless networks configured." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2572 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2647 msgid "No wireless radios are reported by this device." msgstr "" @@ -1332,39 +1358,39 @@ msgstr "" msgid "No zones are configured." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3121 msgid "Nobody is moving data right now." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2605 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2680 msgid "Noise" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3261 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3336 msgid "Noise / SNR" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3449 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3524 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3525 msgid "Noise floor" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:105 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "None" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3416 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 msgid "Not a station MAC address" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3211 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3286 msgid "Not connected" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2966 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3301 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3041 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3376 msgid "Not counted per device on a shared port" msgstr "" @@ -1372,7 +1398,7 @@ msgstr "" msgid "Not in effect" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2278 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2353 msgid "Not reported" msgstr "" @@ -1380,7 +1406,7 @@ msgstr "" msgid "Not reported by the driver" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3325 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3400 msgid "Nothing better known" msgstr "" @@ -1401,7 +1427,7 @@ msgstr "" msgid "Older %s device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2986 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3061 msgid "Older Wi-Fi generation than the radio; uses more airtime" msgstr "" @@ -1409,7 +1435,7 @@ msgstr "" msgid "On this router" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 msgctxt "vantage" msgid "Online" msgstr "" @@ -1426,7 +1452,7 @@ msgctxt "vantage" msgid "Open" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2884 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 msgid "Open details of %s" msgstr "" @@ -1452,11 +1478,11 @@ msgid "" "new rules: what is open is unknown." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1301 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1366 msgid "Overlaid" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1302 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1367 msgid "Overlaid, log scale" msgstr "" @@ -1464,11 +1490,11 @@ msgstr "" msgid "Overview" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3260 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3335 msgid "PMF" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1565 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1640 msgid "Paused while hidden" msgstr "" @@ -1482,7 +1508,7 @@ msgid "" "on to your network: what every router lets in." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3534 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3609 msgctxt "vantage" msgid "Platform" msgstr "" @@ -1492,7 +1518,7 @@ msgctxt "vantage" msgid "Poor" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3370 msgid "Port" msgstr "" @@ -1500,11 +1526,11 @@ msgstr "" msgid "Port %d" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3034 msgid "Port %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2114 msgid "Port total: %s" msgstr "" @@ -1512,11 +1538,11 @@ msgstr "" msgid "Private" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 msgid "Private Wi-Fi address (randomised by the device)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Private address (randomised by the device)" msgstr "" @@ -1524,26 +1550,26 @@ msgstr "" msgid "Private device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3531 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3606 msgid "Processes" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3500 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3575 msgid "Protocol" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2637 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2639 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2712 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2714 msgid "Quick filters" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3265 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3443 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3340 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3518 msgctxt "vantage" msgid "Radio" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2593 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2668 msgid "Radio details" msgstr "" @@ -1555,58 +1581,58 @@ msgstr "" msgid "Radio is enabled but not up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2617 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3437 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2692 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3512 msgid "Radio settings" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2545 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2547 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2620 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2622 msgid "Radios" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1927 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2002 msgid "Reachability not probed" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2951 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3026 msgid "Reached through the uplink port %s, not connected to this device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3566 msgid "Realtime graphs" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3515 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3590 msgctxt "vantage" msgid "Received" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1641 msgctxt "vantage" msgid "Reconnecting…" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2784 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2859 msgid "Remove filter: %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3383 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3458 msgid "Remove name" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3220 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3289 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3364 msgctxt "vantage" msgid "Rename" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1359 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1433 msgid "Reset" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3320 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3395 msgid "Reverse DNS of its address" msgstr "" @@ -1614,7 +1640,7 @@ msgstr "" msgid "Root (overlay)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3511 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3586 msgid "Route metric" msgstr "" @@ -1626,20 +1652,20 @@ msgstr "" msgid "SSH (port 22)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3375 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 msgid "Save" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "Seen since" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3516 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3591 msgctxt "vantage" msgid "Sent" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1370 msgid "Separate lanes" msgstr "" @@ -1647,57 +1673,57 @@ msgstr "" msgid "Settings to check" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 msgid "Shared by %d devices" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2955 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3030 msgid "Shared port" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1514 msgid "Show %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2910 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 msgid "Show all clients" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2214 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 msgid "Show or hide system details" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1714 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1789 msgid "Show or hide the network path" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2548 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2623 msgid "Show or hide the radio details" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2333 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2408 msgid "Show or hide the throughput chart" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgid "Show or hide the wireless networks" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2013 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3089 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2088 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3164 msgid "Show the clients of %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2114 msgid "Show the devices on %s" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:119 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:120 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:128 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2991 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3244 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3066 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3319 msgid "Signal" msgstr "" @@ -1705,7 +1731,7 @@ msgstr "" msgid "Signal not reported" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3499 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3574 msgctxt "vantage" msgid "Speed" msgstr "" @@ -1716,24 +1742,24 @@ msgid_plural "Standard housekeeping: %d rules" msgstr[0] "" msgstr[1] "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "Starfield" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2919 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2994 msgid "Stations appear here as soon as they associate with one of the SSIDs." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgid "Status" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:93 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2231 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2306 msgid "Storage" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3459 msgid "Stored on this device in /etc/config/vantage" msgstr "" @@ -1749,12 +1775,12 @@ msgstr "" msgid "Strong signal, %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2288 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2363 msgctxt "vantage" msgid "Swap" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3299 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3374 msgid "Switch ports" msgstr "" @@ -1766,13 +1792,13 @@ msgstr "" msgid "Switched off" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2213 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2214 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2288 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 msgid "System" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3531 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3606 msgid "System settings" msgstr "" @@ -1785,7 +1811,7 @@ msgid "Telnet (port 23)" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:76 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2245 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2320 msgid "Temperature %s" msgstr "" @@ -1793,11 +1819,11 @@ msgstr "" msgid "Temporary (RAM)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2839 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2914 msgid "The bridge forgets a device after about five minutes without traffic" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2988 msgid "" "The bridges have learned so many addresses that listing them here would " "strain this device." @@ -1810,7 +1836,7 @@ msgid "" "reject in General Settings." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3496 msgid "The device could not write /etc/config/vantage." msgstr "" @@ -1834,7 +1860,7 @@ msgid "" "an uplink in no zone would be open. Set Input to reject in General Settings." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3323 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3398 msgid "The name the device announces (WPS)" msgstr "" @@ -1846,7 +1872,7 @@ msgstr "" msgid "The only measured client" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2950 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3025 msgid "The router this device sends its traffic to" msgstr "" @@ -1862,7 +1888,7 @@ msgstr "" msgid "The uplinks could not be checked" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1942 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2017 msgid "This access point" msgstr "" @@ -1870,11 +1896,11 @@ msgstr "" msgid "This address family is in no zone: the default policies apply." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1942 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2017 msgid "This device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3495 msgid "This device already stores %d names; remove some first." msgstr "" @@ -1882,7 +1908,7 @@ msgstr "" msgid "This device reports no radios" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3480 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3555 msgid "This line is down or has no default route now." msgstr "" @@ -1892,7 +1918,7 @@ msgid "" "the firewall pages." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3428 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 msgid "This radio is not reported any more." msgstr "" @@ -1900,23 +1926,23 @@ msgstr "" msgid "This setup is beyond what this overview checks" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3211 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3286 msgid "This station is not associated right now." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2325 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2327 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3250 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2400 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2402 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3325 msgctxt "vantage" msgid "Throughput" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1375 msgid "Throughput chart" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2318 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2393 msgid "Throughput per link; arrow keys read the values over time" msgstr "" @@ -1925,38 +1951,38 @@ msgctxt "vantage" msgid "TiB" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3257 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3332 msgid "To device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2971 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3006 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3059 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3081 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3134 msgid "To device %s, from device %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2998 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3073 msgid "To device: %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3569 msgid "To network" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2912 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2987 msgid "Too many devices to list" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3023 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3024 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3098 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3099 msgctxt "vantage" msgid "Top talkers" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3270 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3300 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3440 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3345 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3375 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3515 msgid "Traffic" msgstr "" @@ -1972,16 +1998,16 @@ msgid "" "networks. Set Forward to reject in General Settings." msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1938 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2013 msgid "Traffic to the internet goes through %s, a tunnel over this line" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3578 msgid "Tunnel" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2604 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2679 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "Tx power" msgstr "" @@ -1992,16 +2018,16 @@ msgid "" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:272 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3210 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3285 msgctxt "vantage" msgid "Unknown device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3419 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 msgid "Unknown device type" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3428 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 msgid "Unknown radio" msgstr "" @@ -2016,14 +2042,14 @@ msgid "Unnamed rule" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:57 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgctxt "vantage" msgid "Up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2238 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2313 msgid "Up %s" msgstr "" @@ -2032,25 +2058,25 @@ msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:49 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:51 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:57 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2351 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3483 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2426 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3558 msgctxt "vantage" msgid "Uplink" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2351 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2426 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2427 msgid "Uplink %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3476 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3487 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3551 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3562 msgid "Uplink · %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2331 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2427 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2501 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2406 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2502 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2576 msgid "Upload" msgstr "" @@ -2058,21 +2084,21 @@ msgstr "" msgid "Upload (from clients)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3272 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3347 msgctxt "vantage" msgid "Uploaded" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2951 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3026 msgid "Upstream" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3537 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3612 msgid "Uptime" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2952 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3027 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3379 msgid "VLAN %d" msgstr "" @@ -2207,11 +2233,11 @@ msgstr "" msgid "WPS" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3280 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3355 msgid "WPS device name" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1599 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1674 msgid "Warning" msgstr "" @@ -2225,7 +2251,7 @@ msgid "Weak" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:157 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2767 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2842 msgid "Weak signal" msgstr "" @@ -2249,27 +2275,27 @@ msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:106 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:108 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:110 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2821 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2896 msgid "Wi-Fi" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1883 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2821 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1958 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2896 msgid "Wired" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3070 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3145 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgctxt "vantage" msgid "Wireless networks" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3230 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 msgid "Wireless settings" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3319 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3394 msgid "Your name for this device" msgstr "" @@ -2307,15 +2333,15 @@ msgstr "" msgid "any zone (default policy)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2598 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2673 msgid "auto" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "before this page opened" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3372 msgid "behind %s, VLAN %d" msgstr "" @@ -2324,16 +2350,16 @@ msgctxt "vantage" msgid "bit/s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2459 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2534 msgid "collecting · %s of data" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2459 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2534 msgid "collecting · first samples" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:251 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2514 msgid "collecting…" msgstr "" @@ -2345,18 +2371,18 @@ msgstr "" msgid "dBm" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1802 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1940 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1877 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 msgid "default route" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1940 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 msgid "default route via %s" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:385 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2955 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3030 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 msgid "down" msgstr "" @@ -2365,7 +2391,7 @@ msgctxt "vantage" msgid "drop" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3349 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3424 msgctxt "vantage" msgid "e.g. Living room TV" msgstr "" @@ -2404,8 +2430,8 @@ msgid "half duplex" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/fmt.js:62 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1960 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3097 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2035 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3172 msgid "idle" msgstr "" @@ -2447,14 +2473,14 @@ msgctxt "vantage" msgid "kbit/s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2223 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2458 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2298 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2533 msgid "last 5 min" msgstr "" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:175 #: luci-app-vantage/htdocs/luci-static/resources/vantage/wifi.js:104 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3000 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3075 msgid "legacy" msgstr "" @@ -2466,45 +2492,45 @@ msgstr "" msgid "mDNS" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3321 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3396 msgid "mDNS announcement" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3252 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3327 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3378 msgid "measuring" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2434 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2509 msgid "measuring…" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2415 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2490 msgctxt "vantage" msgid "no data" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1933 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2008 msgid "no uplink" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3278 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3353 msgid "not known to this AP" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3385 msgid "not known to this device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3525 msgid "not reported (driver placeholder %s)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3261 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3336 msgid "not reported by the driver" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2455 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2530 msgctxt "vantage" msgid "now" msgstr "" @@ -2513,16 +2539,16 @@ msgstr "" msgid "now %s down, %s up" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3334 msgid "older than the radio (%s)" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2432 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2507 msgctxt "vantage" msgid "peak" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2224 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2299 msgid "per core" msgstr "" @@ -2531,11 +2557,11 @@ msgctxt "vantage" msgid "port forward" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3246 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3321 msgid "range %s … %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3568 msgid "received on %s" msgstr "" @@ -2548,7 +2574,7 @@ msgstr "" msgid "router port %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3569 msgid "sent on %s" msgstr "" @@ -2556,12 +2582,12 @@ msgstr "" msgid "short GI" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2974 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3049 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3380 msgid "static entry" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3298 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3373 msgid "switch port %s" msgstr "" @@ -2573,11 +2599,11 @@ msgstr "" msgid "the covered subnets of zone %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3302 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3377 msgid "the port in total: %s" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3372 msgid "the port: %s" msgstr "" @@ -2593,7 +2619,7 @@ msgstr "" msgid "traffic rule" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1945 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2020 msgid "up %s" msgstr "" @@ -2610,6 +2636,6 @@ msgstr "" msgid "zones %s and %s if they share a device" msgstr "" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2452 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2527 msgid "−%d min" msgstr "" diff --git a/luci-app-vantage/po/zh_Hans/vantage.po b/luci-app-vantage/po/zh_Hans/vantage.po index 8b04f71ba..c30694957 100644 --- a/luci-app-vantage/po/zh_Hans/vantage.po +++ b/luci-app-vantage/po/zh_Hans/vantage.po @@ -12,7 +12,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3446 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3521 msgid "%d MHz (%d–%d MHz)" msgstr "%d MHz(%d–%d MHz)" @@ -36,19 +36,19 @@ msgid "%d SSID · %d idle" msgid_plural "%d SSIDs · %d idle" msgstr[0] "%d 个 SSID · %d 个空闲" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1547 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1622 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2090 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2641 msgid "%d clients" msgstr "%d 个客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2978 msgid "%d connected" msgstr "已连接 %d 个" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2042 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2046 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2902 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2117 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2121 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2977 msgid "%d devices" msgstr "%d 台设备" @@ -73,11 +73,11 @@ msgctxt "vantage" msgid "%d min ago" msgstr "%d 分钟前" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2901 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2976 msgid "%d of %d" msgstr "%d/%d" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1434 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1509 msgid "%d of %d columns" msgstr "%d/%d 列" @@ -104,7 +104,7 @@ msgid "%d radio up" msgid_plural "%d radios up" msgstr[0] "%d 个射频已上线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2558 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2633 msgid "%d radios" msgstr "%d 个射频" @@ -128,7 +128,7 @@ msgstr "%d 项需要关注" msgid "%d weak" msgstr "%d 个信号弱" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2577 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2652 msgid "%d–%d MHz of the %d–%d MHz band" msgstr "%d–%d MHz 属于 %d–%d MHz 频段" @@ -146,7 +146,7 @@ msgstr "%s(%s)已启用但未上线" msgid "%s (IPv%d)" msgstr "%s(IPv%d)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "%s (new this session)" msgstr "%s(本次新增)" @@ -157,10 +157,10 @@ msgstr "%s Gbit/s" #: luci-app-vantage/htdocs/luci-static/resources/vantage/fmt.js:166 #: luci-app-vantage/htdocs/luci-static/resources/vantage/wifi.js:103 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2584 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2598 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3000 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2659 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2673 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3075 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 msgid "%s MHz" msgstr "%s MHz" @@ -179,13 +179,13 @@ msgid "%s at %s; below %s roaming and throughput suffer" msgstr "%s(%s);低于 %s 时漫游和吞吐量会受影响" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:83 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2334 msgctxt "vantage" msgid "%s available" msgstr "可用 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2604 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2679 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "%s dBm" msgstr "%s dBm" @@ -197,12 +197,12 @@ msgstr "%s 设备" msgid "%s device on a newer radio; uses more airtime per byte" msgstr "%s 设备连接在较新的射频上,每字节占用更多空口时间" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3473 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3548 msgid "%s error" msgid_plural "%s errors" msgstr[0] "%s 个错误" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3235 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 msgid "%s experience" msgstr "%s 体验" @@ -218,11 +218,11 @@ msgstr "overlay 空闲 %s(已用 %s)" msgid "%s has no carrier: cable unplugged or switch port down" msgstr "%s 无载波:网线未插或交换机端口关闭" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1401 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1475 msgid "%s hidden" msgstr "%s 已隐藏" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3517 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3592 msgid "%s in · %s out" msgstr "%s 入 · %s 出" @@ -238,7 +238,7 @@ msgstr "%s 被转发到 %s" msgid "%s is in no zone and accepts every connection" msgstr "%s 不属于任何区域,接受所有连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1394 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1468 msgid "%s is narrower" msgstr "%s 已变窄" @@ -246,18 +246,18 @@ msgstr "%s 已变窄" msgid "%s is not up" msgstr "%s 未上线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3034 msgid "" "%s is shared by %d devices (a switch or another access point behind it); its " "%s link is not theirs" msgstr "" "%s 由 %d 台设备共用(其后接有交换机或另一个接入点);%s 的链路不属于这些设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2958 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3033 msgid "%s is shared by %d devices behind the switch" msgstr "%s 由交换机后的 %d 台设备共用" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1397 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1471 msgid "%s is wider" msgstr "%s 已加宽" @@ -273,23 +273,23 @@ msgstr "%s 链路" msgid "%s may open the router's admin" msgstr "%s 可能暴露了路由器管理界面" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1515 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1590 msgid "%s moved" msgstr "%s 已移动" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1391 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1465 msgid "%s moved down" msgstr "%s 已下移" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1456 msgid "%s moved left" msgstr "%s 已左移" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1385 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1459 msgid "%s moved right" msgstr "%s 已右移" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1388 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1462 msgid "%s moved up" msgstr "%s 已上移" @@ -302,9 +302,9 @@ msgid "%s negotiated only %d Mbit/s; a cable pair or port may be faulty" msgstr "%s 仅协商到 %d Mbit/s;网线线对或端口可能有故障" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:84 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2260 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3543 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2335 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2364 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3618 msgid "%s of %s" msgstr "%s / %s" @@ -325,20 +325,20 @@ msgstr "发往设备的帧失败率:%s" msgid "%s of frames to the device fail; interference likely" msgstr "发往设备的帧失败率:%s,可能存在干扰" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3541 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3616 msgid "%s over %d core" msgid_plural "%s over %d cores" msgstr[0] "%s / %d 核" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2353 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2428 msgid "%s radio" msgstr "%s 射频" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3273 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3348 msgid "%s sent · %s retried · %s failed" msgstr "发送 %s · 重传 %s · 失败 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1440 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1515 msgid "%s shown" msgstr "%s 已显示" @@ -354,11 +354,11 @@ msgstr "%s 已连接,速率 %s" msgid "%s used" msgstr "已用 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2372 msgid "%s used of %s" msgstr "已用 %s / 共 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2956 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3031 msgid "%s · %d devices" msgstr "%s · %d 台设备" @@ -366,7 +366,7 @@ msgstr "%s · %d 台设备" msgid "%s · %s" msgstr "%s · %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3265 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3340 msgid "%s · channel %d · %d MHz" msgstr "%s · 信道 %d · %d MHz" @@ -382,27 +382,27 @@ msgstr "%s · 链路较慢" msgid "%s: no carrier" msgstr "%s:无载波" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "(configured %d dBm, limited by regulatory rules)" msgstr "(配置 %d dBm,受管制规则限制)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2014 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3092 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2089 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3167 msgid "(hidden)" msgstr "(隐藏)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1547 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1622 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2090 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2641 msgid "1 client" msgstr "1 个客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2978 msgid "1 connected" msgstr "已连接 1 个" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2046 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2902 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2121 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2977 msgid "1 device" msgstr "1 台设备" @@ -410,7 +410,7 @@ msgstr "1 台设备" msgid "1 older device (Wi-Fi 4 or earlier) slows airtime" msgstr "1 台旧设备(Wi-Fi 4 或更早)占用更多空口时间" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2558 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2633 msgid "1 radio" msgstr "1 个射频" @@ -438,20 +438,20 @@ msgstr "6 GHz" msgid "60 GHz" msgstr "60 GHz" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2766 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2841 msgid "Active" msgstr "活跃" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Address type" msgstr "地址类型" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3506 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3581 msgid "Addresses" msgstr "地址" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2606 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2681 msgid "Airtime" msgstr "空口时间" @@ -460,8 +460,8 @@ msgctxt "vantage" msgid "Alias" msgstr "别名" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2757 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2763 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2832 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 msgid "All" msgstr "全部" @@ -490,7 +490,7 @@ msgstr "B" msgid "Busiest radio: %s of Wi-Fi traffic" msgstr "最繁忙射频:占 Wi-Fi 流量的 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2224 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2299 msgid "Busy share of each CPU core" msgstr "每个 CPU 核心的繁忙占比" @@ -505,8 +505,8 @@ msgstr[0] "繁忙;负载 %s(%d 核);查看最繁忙进程" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:71 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:72 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2217 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3541 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2292 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3616 msgctxt "vantage" msgid "CPU" msgstr "CPU" @@ -515,78 +515,78 @@ msgstr "CPU" msgid "Cache (reclaimable)" msgstr "缓存(可回收)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3382 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3457 msgid "Cancel" msgstr "取消" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3260 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3335 msgctxt "vantage" msgid "Capabilities" msgstr "能力" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgid "Carrier" msgstr "链路状态" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3446 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3521 msgid "Centre frequency" msgstr "中心频率" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2597 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2672 msgid "Ch %d" msgstr "信道 %d" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1995 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2565 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2070 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2640 msgid "Ch %d · %d MHz" msgstr "信道 %d · %d MHz" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 msgid "Channel" msgstr "信道" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1995 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2070 msgid "Channel —" msgstr "信道 —" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2630 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2705 msgctxt "vantage" msgid "Clear filter" msgstr "清除筛选" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2603 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2648 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2649 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2678 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2723 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2724 msgid "Clients" msgstr "客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3453 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3528 msgid "Clients on this radio" msgstr "此射频上的客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3109 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3184 msgid "Close" msgstr "关闭" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3015 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3090 msgid "Connected" msgstr "已连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3060 msgid "Connected after you opened this page" msgstr "打开本页面后连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3266 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3341 msgid "Connected for" msgstr "已连接时长" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3263 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3294 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3338 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3369 msgid "Connection" msgstr "连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2251 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2326 msgid "Core %d: %s" msgstr "核心 %d:%s" @@ -594,15 +594,19 @@ msgstr "核心 %d:%s" msgid "Could not read the firewall configuration" msgstr "无法读取防火墙配置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3365 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3440 msgid "Could not save the name (no permission or the device refused it)." msgstr "无法保存名称(无权限或设备拒绝)。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3514 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1356 +msgid "Could not save this for every browser. Try again." +msgstr "无法为所有浏览器保存此设置,请重试。" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3589 msgid "Counters since boot" msgstr "自启动以来的计数器" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3451 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3526 msgid "Country" msgstr "国家" @@ -611,13 +615,13 @@ msgid "" "Custom rule files are configured (%s); rules in them are not listed here." msgstr "已配置自定义规则文件(%s);其中的规则不会在此列出。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1536 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1611 msgid "Customize" msgstr "自定义" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1346 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1347 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1535 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1610 msgid "Customize the dashboard" msgstr "自定义仪表盘" @@ -625,16 +629,16 @@ msgstr "自定义仪表盘" msgid "DHCP" msgstr "DHCP" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3322 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3397 msgid "DHCP hostname" msgstr "DHCP 主机名" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:42 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3512 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3587 msgid "DNS" msgstr "DNS" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1927 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2002 msgid "DNS %s" msgstr "DNS %s" @@ -643,56 +647,56 @@ msgstr "DNS %s" msgid "Dashboard" msgstr "仪表盘" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2930 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3532 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3005 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3607 msgid "Device" msgstr "设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3349 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3424 msgid "Device name" msgstr "设备名" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3378 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3453 msgid "Device type" msgstr "设备类型" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2916 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2991 msgid "" "Devices on the Ethernet ports appear here once they send traffic; the bridge " "forgets quiet ones after about five minutes." msgstr "" "以太网端口上的设备发送流量后会显示在这里;网桥会在约五分钟无流量后忘记它们。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1996 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgid "Disabled" msgstr "已禁用" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3229 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 msgid "Disconnected %s; shown from the last sample." msgstr "断开于 %s;显示最后一次采样的数据。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1360 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1434 msgctxt "vantage" msgid "Done" msgstr "完成" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:45 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1996 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgctxt "vantage" msgid "Down" msgstr "已下线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2330 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2425 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2405 #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2500 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2575 msgid "Download" msgstr "下载" @@ -700,39 +704,60 @@ msgstr "下载" msgid "Download (to clients)" msgstr "下载(到客户端)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3271 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3346 msgctxt "vantage" msgid "Downloaded" msgstr "已下载" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1496 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for medium " +"screens in every browser." +msgstr "" +"拖动卡片手柄或使用其按钮移动。点击“完成”后,中屏布局将保存到所有浏览器。" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1497 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for narrow " +"screens in every browser." +msgstr "" +"拖动卡片手柄或使用其按钮移动。点击“完成”后,窄屏布局将保存到所有浏览器。" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1495 +msgid "" +"Drag a tile by its handle or use its buttons. Done saves it for wide screens " +"in every browser." +msgstr "" +"拖动卡片手柄或使用其按钮移动。点击“完成”后,宽屏布局将保存到所有浏览器。" + +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1496 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for " "medium screens." msgstr "拖动卡片手柄或使用其按钮移动。中屏布局保存在此浏览器中。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1422 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1497 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for " "narrow screens." msgstr "拖动卡片手柄或使用其按钮移动。窄屏布局保存在此浏览器中。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1495 msgid "" "Drag a tile by its handle or use its buttons. Saved in this browser for wide " "screens." msgstr "拖动卡片手柄或使用其按钮移动。宽屏布局保存在此浏览器中。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1373 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1447 msgid "Drag to move" msgstr "拖动以移动" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3517 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3592 msgctxt "vantage" msgid "Dropped" msgstr "已丢弃" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgid "Edit" msgstr "编辑" @@ -740,7 +765,7 @@ msgstr "编辑" msgid "Enhanced Open (OWE)" msgstr "增强开放 (OWE)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1599 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1674 msgid "Error" msgstr "错误" @@ -754,8 +779,8 @@ msgctxt "vantage" msgid "Excellent" msgstr "极好" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3009 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3084 msgid "Experience" msgstr "体验" @@ -773,20 +798,20 @@ msgstr "信号一般" msgid "Fair signal %s; lower rates at range" msgstr "信号一般 %s;远距离速率较低" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2627 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2828 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2702 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 msgid "Filter by name, address, SSID…" msgstr "按名称、地址、SSID…筛选" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2828 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2903 msgid "Filter by name, address, port…" msgstr "按名称、地址、端口…筛选" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2628 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2703 msgid "Filter clients" msgstr "筛选客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3535 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3610 msgctxt "vantage" msgid "Firmware" msgstr "固件" @@ -799,7 +824,7 @@ msgstr "从 %s 转发到 %s" msgid "Forwarding is accepted by default" msgstr "默认接受转发" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3273 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3348 msgid "Frames to device" msgstr "发往设备的帧" @@ -808,15 +833,15 @@ msgctxt "vantage" msgid "Free" msgstr "空闲" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3258 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3333 msgid "From device" msgstr "来自设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2998 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3073 msgid "From device: %s" msgstr "来自设备:%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3568 msgid "From network" msgstr "来自网络" @@ -826,9 +851,9 @@ msgid "" "files are not shown." msgstr "内容来自防火墙配置。由 UPnP 或自定义规则文件开放的端口不会显示。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1925 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2950 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3509 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2000 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3025 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3584 msgid "Gateway" msgstr "网关" @@ -841,7 +866,7 @@ msgstr "Gbit/s" msgid "General Settings" msgstr "基本设置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3334 msgctxt "vantage" msgid "Generation" msgstr "代际" @@ -851,13 +876,13 @@ msgctxt "vantage" msgid "GiB" msgstr "GiB" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Globally unique" msgstr "全局唯一" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Globally unique · %s" msgstr "全局唯一 · %s" @@ -875,7 +900,7 @@ msgstr "信号良好" msgid "Good signal %s" msgstr "信号良好 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "Grid packets" msgstr "网格数据包" @@ -891,36 +916,36 @@ msgstr "HTTPS(端口 443)" msgid "Half duplex" msgstr "半双工" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1045 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1071 msgctxt "vantage" msgid "Health checks" msgstr "健康检查" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1437 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3092 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1512 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3167 msgctxt "vantage" msgid "Hidden" msgstr "隐藏" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1400 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1474 msgid "Hide %s" msgstr "隐藏 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3278 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3353 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3385 msgid "IP addresses" msgstr "IP 地址" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3507 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3582 msgid "IPv4" msgstr "IPv4" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3508 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3583 msgid "IPv6" msgstr "IPv6" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3275 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3307 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3350 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3382 msgid "Identity" msgstr "身份" @@ -928,7 +953,7 @@ msgstr "身份" msgid "In no zone: the default policies apply." msgstr "不属于任何区域:适用默认策略。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3504 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3579 msgid "In the tunnel" msgstr "隧道内" @@ -942,21 +967,21 @@ msgctxt "vantage" msgid "Input" msgstr "入站数据" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1974 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2049 msgid "Interface" msgstr "接口" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3501 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3576 msgid "Interface up for" msgstr "接口已启用时长" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3292 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3479 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3367 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3554 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3566 msgid "Interfaces" msgstr "接口" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1925 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2000 msgid "Internet" msgstr "互联网" @@ -986,11 +1011,11 @@ msgstr "" "它将来自互联网上任何地址的 %s 转发到 %s。无法读取接口列表,因此本页无法判断该" "地址是否为路由器本身。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3536 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3611 msgid "Kernel" msgstr "内核" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2378 msgid "Kernel %s" msgstr "内核 %s" @@ -999,58 +1024,58 @@ msgctxt "vantage" msgid "KiB" msgstr "KiB" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2717 msgid "Kind of client" msgstr "客户端类型" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3267 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3342 msgctxt "vantage" msgid "Last activity" msgstr "最后活动" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2839 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2974 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2914 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3049 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3380 msgid "Last heard" msgstr "最后活动" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1358 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1432 msgid "Layout reset" msgstr "布局已重置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3059 msgid "Left %s" msgstr "离开于 %s" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:174 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2986 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3061 msgctxt "vantage" msgid "Legacy" msgstr "旧版" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2954 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3256 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3497 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3029 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3331 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3572 msgctxt "vantage" msgid "Link" msgstr "链路" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2997 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3072 msgid "Link rate" msgstr "链路速率" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1567 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2965 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3002 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1642 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3040 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3077 msgid "Live" msgstr "实时" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3540 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3615 msgid "Load" msgstr "负载" @@ -1064,23 +1089,27 @@ msgid "Load %s · %d core" msgid_plural "Load %s · %d cores" msgstr[0] "负载 %s · %d 核" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3542 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3617 msgctxt "vantage" msgid "Load average" msgstr "平均负载" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2205 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2280 msgid "Load average over 1, 5 and 15 minutes" msgstr "1、5、15 分钟平均负载" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2241 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2316 msgid "Load avg %s" msgstr "平均负载 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3538 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3613 msgid "Local time" msgstr "本地时间" +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1323 +msgid "Log in again to save this for every browser." +msgstr "重新登录后即可为所有浏览器保存此设置。" + #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:164 msgid "Low link rate %s despite good signal; interference or an old device" msgstr "信号良好但链路速率仅 %s;可能存在干扰或设备较旧" @@ -1093,8 +1122,8 @@ msgstr "链路速率低于信号预期" msgid "MAC" msgstr "MAC" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3276 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3308 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3351 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3383 msgid "MAC address" msgstr "MAC 地址" @@ -1102,11 +1131,11 @@ msgstr "MAC 地址" msgid "MCS %d" msgstr "MCS %d" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1393 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1467 msgid "Make %s narrower" msgstr "使 %s 变窄" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1396 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1470 msgid "Make %s wider" msgstr "使 %s 加宽" @@ -1123,11 +1152,11 @@ msgid "Measuring…" msgstr "测量中…" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:83 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2228 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2303 msgid "Memory" msgstr "内存" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3543 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3618 msgid "Memory in use" msgstr "已用内存" @@ -1136,63 +1165,63 @@ msgctxt "vantage" msgid "MiB" msgstr "MiB" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1368 msgid "Mirrored" msgstr "镜像" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1369 msgid "Mirrored, scale per direction" msgstr "镜像,每个方向单独刻度" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3445 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3520 msgid "Mode" msgstr "模式" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3533 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3608 msgid "Model" msgstr "型号" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1390 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1464 msgid "Move %s down" msgstr "下移 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1381 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1455 msgid "Move %s left" msgstr "左移 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1384 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1458 msgid "Move %s right" msgstr "右移 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1387 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1461 msgid "Move %s up" msgstr "上移 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1373 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1447 msgid "Move %s: drag, or use the arrow keys" msgstr "移动 %s:拖动或使用方向键" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3377 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3452 msgid "Name" msgstr "名称" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:134 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3417 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3492 msgid "Name contains invisible or control characters" msgstr "名称包含不可见或控制字符" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3279 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3311 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3354 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3386 msgid "Name from" msgstr "名称来源" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2935 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3010 msgid "Name from: %s" msgstr "名称来源:%s" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:132 #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:137 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3418 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 msgid "Name is longer than %d characters" msgstr "名称超过 %d 个字符" @@ -1200,27 +1229,27 @@ msgstr "名称超过 %d 个字符" msgid "Name must be text" msgstr "名称必须是文本" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3220 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3289 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3364 msgid "Name this device" msgstr "命名此设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2838 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2964 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2994 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3264 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3069 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3339 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3379 msgid "Network" msgstr "网络" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1713 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1714 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1788 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1789 msgid "Network path" msgstr "网络路径" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1322 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1387 msgid "Network path background" msgstr "网络路径背景" @@ -1228,13 +1257,13 @@ msgstr "网络路径背景" msgid "Networks: %s" msgstr "网络:%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2768 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2843 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3060 msgctxt "vantage" msgid "New" msgstr "新增" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1872 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1947 msgid "No SSIDs" msgstr "无 SSID" @@ -1242,24 +1271,24 @@ msgstr "无 SSID" msgid "No clients" msgstr "无客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2918 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3458 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2993 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3533 msgid "No clients connected" msgstr "无客户端连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3121 msgid "No clients connected." msgstr "没有客户端连接。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2909 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 msgid "No clients in this view" msgstr "此视图中没有客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2909 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2984 msgid "No clients match “%s”" msgstr "没有匹配“%s”的客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1926 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2001 msgctxt "vantage" msgid "No default route" msgstr "无默认路由" @@ -1268,7 +1297,7 @@ msgstr "无默认路由" msgid "No interface with a route" msgstr "没有带路由的接口" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3483 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3558 msgid "No interface with a route is up." msgstr "没有带路由的接口处于启用状态。" @@ -1277,7 +1306,7 @@ msgid "No internet-facing zone found" msgstr "未找到面向互联网的区域" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:47 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgid "No link" msgstr "无链路" @@ -1285,7 +1314,7 @@ msgstr "无链路" msgid "No network interface with a route is up" msgstr "没有带路由的网络接口处于启用状态" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1853 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1928 msgid "No other interfaces are up" msgstr "没有其他接口处于启用状态" @@ -1295,7 +1324,7 @@ msgid "No problems detected" msgstr "未检测到问题" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:105 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1876 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1951 msgid "No radios reported" msgstr "未报告射频" @@ -1312,16 +1341,16 @@ msgstr "无信号" msgid "No stations are associated right now" msgstr "当前没有站点关联" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2990 msgid "No wired devices heard" msgstr "未发现有线设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3080 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3155 msgctxt "vantage" msgid "No wireless networks configured." msgstr "未配置无线网络。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2572 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2647 msgid "No wireless radios are reported by this device." msgstr "此设备未报告任何无线射频。" @@ -1338,39 +1367,39 @@ msgstr "" msgid "No zones are configured." msgstr "尚未配置区域。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3121 msgid "Nobody is moving data right now." msgstr "当前没有设备在传输数据。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2605 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2680 msgid "Noise" msgstr "噪声" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3261 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3336 msgid "Noise / SNR" msgstr "噪声 / 信噪比" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3449 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3524 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3525 msgid "Noise floor" msgstr "底噪" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:105 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "None" msgstr "无" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3416 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 msgid "Not a station MAC address" msgstr "不是站点 MAC 地址" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3211 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3286 msgid "Not connected" msgstr "未连接" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2966 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3301 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3041 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3376 msgid "Not counted per device on a shared port" msgstr "共用端口不按设备统计" @@ -1378,7 +1407,7 @@ msgstr "共用端口不按设备统计" msgid "Not in effect" msgstr "未生效" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2278 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2353 msgid "Not reported" msgstr "未报告" @@ -1386,7 +1415,7 @@ msgstr "未报告" msgid "Not reported by the driver" msgstr "驱动未报告" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3325 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3400 msgid "Nothing better known" msgstr "无更多信息" @@ -1407,7 +1436,7 @@ msgstr "OWE" msgid "Older %s device" msgstr "较旧的 %s 设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2986 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3061 msgid "Older Wi-Fi generation than the radio; uses more airtime" msgstr "比射频支持的 Wi-Fi 代际更旧;占用更多空口时间" @@ -1415,7 +1444,7 @@ msgstr "比射频支持的 Wi-Fi 代际更旧;占用更多空口时间" msgid "On this router" msgstr "在此路由器上" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 msgctxt "vantage" msgid "Online" msgstr "在线" @@ -1431,7 +1460,7 @@ msgctxt "vantage" msgid "Open" msgstr "开放" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2884 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 msgid "Open details of %s" msgstr "打开 %s 的详情" @@ -1459,11 +1488,11 @@ msgstr "" "基本设置中的选项 %s 的值被 firewall4 拒绝,因此不会加载新规则:无法确定开放了" "哪些内容。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1301 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1366 msgid "Overlaid" msgstr "叠加" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1302 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1367 msgid "Overlaid, log scale" msgstr "叠加,对数刻度" @@ -1471,11 +1500,11 @@ msgstr "叠加,对数刻度" msgid "Overview" msgstr "概览" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3260 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3335 msgid "PMF" msgstr "PMF" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1565 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1640 msgid "Paused while hidden" msgstr "页面隐藏时暂停" @@ -1491,7 +1520,7 @@ msgstr "" "Ping 和其他控制消息、组播、DHCP 续租以及转发到你网络的 IPsec:每台路由器都会" "放行的流量。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3534 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3609 msgctxt "vantage" msgid "Platform" msgstr "平台" @@ -1501,7 +1530,7 @@ msgctxt "vantage" msgid "Poor" msgstr "较差" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3370 msgid "Port" msgstr "端口" @@ -1509,11 +1538,11 @@ msgstr "端口" msgid "Port %d" msgstr "端口 %d" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2959 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3034 msgid "Port %s" msgstr "端口 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2114 msgid "Port total: %s" msgstr "端口合计:%s" @@ -1521,11 +1550,11 @@ msgstr "端口合计:%s" msgid "Private" msgstr "私有" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3277 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3352 msgid "Private Wi-Fi address (randomised by the device)" msgstr "私有 Wi-Fi 地址(设备随机化)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3309 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 msgid "Private address (randomised by the device)" msgstr "私有地址(设备随机化)" @@ -1533,26 +1562,26 @@ msgstr "私有地址(设备随机化)" msgid "Private device" msgstr "私有设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3531 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3606 msgid "Processes" msgstr "进程" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3500 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3575 msgid "Protocol" msgstr "协议" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2637 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2639 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2712 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2714 msgid "Quick filters" msgstr "快速筛选" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3265 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3443 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3340 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3518 msgctxt "vantage" msgid "Radio" msgstr "射频" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2593 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2668 msgid "Radio details" msgstr "射频详情" @@ -1564,58 +1593,58 @@ msgstr "射频已禁用" msgid "Radio is enabled but not up" msgstr "射频已启用但未上线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2617 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3437 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2692 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3512 msgid "Radio settings" msgstr "射频设置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2545 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2547 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2620 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2622 msgid "Radios" msgstr "射频" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1927 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2002 msgid "Reachability not probed" msgstr "未探测可达性" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2951 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3026 msgid "Reached through the uplink port %s, not connected to this device" msgstr "经由上行端口 %s 到达,并未连接到本设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3491 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3566 msgid "Realtime graphs" msgstr "实时图表" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3515 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3590 msgctxt "vantage" msgid "Received" msgstr "已接收" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1566 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1641 msgctxt "vantage" msgid "Reconnecting…" msgstr "重新连接中…" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2784 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2859 msgid "Remove filter: %s" msgstr "移除筛选:%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3383 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3458 msgid "Remove name" msgstr "移除名称" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3220 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3289 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3295 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3364 msgctxt "vantage" msgid "Rename" msgstr "重命名" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1359 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1433 msgid "Reset" msgstr "重置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3320 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3395 msgid "Reverse DNS of its address" msgstr "其地址的反向 DNS" @@ -1623,7 +1652,7 @@ msgstr "其地址的反向 DNS" msgid "Root (overlay)" msgstr "Root(overlay)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3511 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3586 msgid "Route metric" msgstr "路由跃点数" @@ -1635,20 +1664,20 @@ msgstr "路由器管理界面已开放:%s" msgid "SSH (port 22)" msgstr "SSH(端口 22)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3375 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 msgid "Save" msgstr "保存" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "Seen since" msgstr "首次出现" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3516 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3591 msgctxt "vantage" msgid "Sent" msgstr "已发送" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1370 msgid "Separate lanes" msgstr "分开显示" @@ -1656,57 +1685,57 @@ msgstr "分开显示" msgid "Settings to check" msgstr "待检查的设置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 msgid "Shared by %d devices" msgstr "%d 台设备共用" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2955 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3030 msgid "Shared port" msgstr "共用端口" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1514 msgid "Show %s" msgstr "显示 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2910 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2985 msgid "Show all clients" msgstr "显示全部客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2214 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 msgid "Show or hide system details" msgstr "显示/隐藏系统详情" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1714 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1789 msgid "Show or hide the network path" msgstr "显示/隐藏网络路径" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2548 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2623 msgid "Show or hide the radio details" msgstr "显示/隐藏射频详情" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2333 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2408 msgid "Show or hide the throughput chart" msgstr "显示/隐藏吞吐量图表" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgid "Show or hide the wireless networks" msgstr "显示/隐藏无线网络" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2013 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3089 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2088 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3164 msgid "Show the clients of %s" msgstr "显示 %s 的客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2039 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2114 msgid "Show the devices on %s" msgstr "显示 %s 上的设备" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:119 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:120 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:128 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2840 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2991 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3244 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2915 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3066 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3319 msgid "Signal" msgstr "信号强度" @@ -1714,7 +1743,7 @@ msgstr "信号强度" msgid "Signal not reported" msgstr "未报告信号" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3499 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3574 msgctxt "vantage" msgid "Speed" msgstr "速率" @@ -1724,24 +1753,24 @@ msgid "Standard housekeeping: %d rule" msgid_plural "Standard housekeeping: %d rules" msgstr[0] "标准常规规则:%d 条" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1317 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1382 msgid "Starfield" msgstr "星空" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2919 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2994 msgid "Stations appear here as soon as they associate with one of the SSIDs." msgstr "站点一旦关联到任一 SSID 便会显示在这里。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 msgid "Status" msgstr "状态" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:93 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2231 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2306 msgid "Storage" msgstr "存储" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3384 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3459 msgid "Stored on this device in /etc/config/vantage" msgstr "保存在本设备 /etc/config/vantage 中" @@ -1757,12 +1786,12 @@ msgstr "信号强 %s,链路 %s" msgid "Strong signal, %s" msgstr "信号强,%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2288 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2363 msgctxt "vantage" msgid "Swap" msgstr "交换分区" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3299 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3374 msgid "Switch ports" msgstr "交换机端口" @@ -1774,13 +1803,13 @@ msgstr "VLAN %d(%s)的交换机端口:%s" msgid "Switched off" msgstr "已关闭" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2213 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2214 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2288 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2289 msgid "System" msgstr "系统" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3531 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3606 msgid "System settings" msgstr "系统设置" @@ -1793,7 +1822,7 @@ msgid "Telnet (port 23)" msgstr "Telnet(端口 23)" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:76 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2245 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2320 msgid "Temperature %s" msgstr "温度 %s" @@ -1801,11 +1830,11 @@ msgstr "温度 %s" msgid "Temporary (RAM)" msgstr "临时(RAM)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2839 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2914 msgid "The bridge forgets a device after about five minutes without traffic" msgstr "设备约五分钟无流量后,网桥会将其遗忘" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2913 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2988 msgid "" "The bridges have learned so many addresses that listing them here would " "strain this device." @@ -1820,7 +1849,7 @@ msgstr "" "该处适用默认入站数据策略且为接受,因此互联网上的任何主机都能访问路由器本身。" "请将其加入 wan 区域,或在基本设置中将入站数据设为拒绝。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3421 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3496 msgid "The device could not write /etc/config/vantage." msgstr "设备无法写入 /etc/config/vantage。" @@ -1846,7 +1875,7 @@ msgstr "" "无法读取接口列表,且默认入站数据策略为接受:不属于任何区域的上行接口将会开" "放。请在基本设置中将入站数据设为拒绝。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3323 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3398 msgid "The name the device announces (WPS)" msgstr "设备广播的名称(WPS)" @@ -1858,7 +1887,7 @@ msgstr "唯一已测客户端高于 %s" msgid "The only measured client" msgstr "唯一已测客户端" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2950 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3025 msgid "The router this device sends its traffic to" msgstr "此设备发送流量所经的路由器" @@ -1874,7 +1903,7 @@ msgstr "保存的名称包含无效的配置节 ID" msgid "The uplinks could not be checked" msgstr "无法检查上行接口" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1942 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2017 msgid "This access point" msgstr "此接入点" @@ -1882,11 +1911,11 @@ msgstr "此接入点" msgid "This address family is in no zone: the default policies apply." msgstr "此地址族不属于任何区域:适用默认策略。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1942 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2017 msgid "This device" msgstr "此设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3420 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3495 msgid "This device already stores %d names; remove some first." msgstr "此设备已存储 %d 个名称;请先移除部分。" @@ -1894,7 +1923,7 @@ msgstr "此设备已存储 %d 个名称;请先移除部分。" msgid "This device reports no radios" msgstr "此设备未报告任何射频" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3480 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3555 msgid "This line is down or has no default route now." msgstr "此线路已断开,或当前没有默认路由。" @@ -1904,7 +1933,7 @@ msgid "" "the firewall pages." msgstr "本页无法判断开放了哪些内容。请重新加载;如果仍无效,请检查防火墙页面。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3428 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 msgid "This radio is not reported any more." msgstr "驱动不再报告此射频。" @@ -1912,23 +1941,23 @@ msgstr "驱动不再报告此射频。" msgid "This setup is beyond what this overview checks" msgstr "此配置超出本概览的检查范围" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3211 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3286 msgid "This station is not associated right now." msgstr "此站点当前未关联。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1149 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2325 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2327 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3250 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1175 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2400 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2402 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3325 msgctxt "vantage" msgid "Throughput" msgstr "吞吐量" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1375 msgid "Throughput chart" msgstr "吞吐量图表" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2318 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2393 msgid "Throughput per link; arrow keys read the values over time" msgstr "每条链路的吞吐量;方向键可查看历史值" @@ -1937,38 +1966,38 @@ msgctxt "vantage" msgid "TiB" msgstr "TiB" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3257 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3332 msgid "To device" msgstr "到设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2971 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3006 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3059 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3046 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3081 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3134 msgid "To device %s, from device %s" msgstr "到设备 %s,来自设备 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2998 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3073 msgid "To device: %s" msgstr "到设备:%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3569 msgid "To network" msgstr "发往网络" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2912 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2987 msgid "Too many devices to list" msgstr "设备过多,无法列出" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3023 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3024 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3098 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3099 msgctxt "vantage" msgid "Top talkers" msgstr "流量大户" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3270 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3300 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3440 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3345 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3375 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3515 msgid "Traffic" msgstr "流量" @@ -1986,16 +2015,16 @@ msgstr "" "未被任何转发覆盖的互联网流量仍会到达你的其他网络。请在基本设置中将转发设为拒" "绝。" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1938 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2013 msgid "Traffic to the internet goes through %s, a tunnel over this line" msgstr "去往互联网的流量经过 %s,一条在此线路上运行的隧道" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3578 msgid "Tunnel" msgstr "隧道" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2604 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3447 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2679 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3522 msgid "Tx power" msgstr "发射功率" @@ -2007,16 +2036,16 @@ msgstr "" "已安装 UPnP:它运行时,你网络中的设备可以自行开放端口,这些端口不会在此列出。" #: luci-app-vantage/htdocs/luci-static/resources/vantage/names.js:272 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3210 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3285 msgctxt "vantage" msgid "Unknown device" msgstr "未知设备" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3419 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 msgid "Unknown device type" msgstr "未知设备类型" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3428 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3503 msgid "Unknown radio" msgstr "未知射频" @@ -2031,14 +2060,14 @@ msgid "Unnamed rule" msgstr "未命名的规则" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:57 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2592 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3444 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3498 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2667 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3519 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3573 msgctxt "vantage" msgid "Up" msgstr "已上线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2238 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2313 msgid "Up %s" msgstr "已运行 %s" @@ -2047,25 +2076,25 @@ msgstr "已运行 %s" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:49 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:51 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:57 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2351 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3483 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2426 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3558 msgctxt "vantage" msgid "Uplink" msgstr "上行链路" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2351 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2352 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2426 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2427 msgid "Uplink %s" msgstr "上行链路 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3476 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3487 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3551 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3562 msgid "Uplink · %s" msgstr "上行链路 · %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2331 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2427 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2501 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2406 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2502 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2576 msgid "Upload" msgstr "上传" @@ -2073,21 +2102,21 @@ msgstr "上传" msgid "Upload (from clients)" msgstr "上传(来自客户端)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3272 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3347 msgctxt "vantage" msgid "Uploaded" msgstr "已上传" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2951 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3026 msgid "Upstream" msgstr "上游" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3537 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3612 msgid "Uptime" msgstr "运行时间" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2952 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3304 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3027 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3379 msgid "VLAN %d" msgstr "VLAN %d" @@ -2232,11 +2261,11 @@ msgstr "WPA3 个人版" msgid "WPS" msgstr "WPS" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3280 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3355 msgid "WPS device name" msgstr "WPS 设备名称" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1599 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1674 msgid "Warning" msgstr "警告" @@ -2250,7 +2279,7 @@ msgid "Weak" msgstr "弱" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:157 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2767 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2842 msgid "Weak signal" msgstr "信号弱" @@ -2273,27 +2302,27 @@ msgstr "开放内容取决于 firewall4 如何处理 %s,本页无法跟踪。 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:106 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:108 #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:110 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2821 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2896 msgid "Wi-Fi" msgstr "Wi-Fi" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1883 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2821 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1958 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2896 msgid "Wired" msgstr "有线" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1150 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3070 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3071 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1176 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3145 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3146 msgctxt "vantage" msgid "Wireless networks" msgstr "无线网络" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3230 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 msgid "Wireless settings" msgstr "无线设置" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3319 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3394 msgid "Your name for this device" msgstr "你为此设备设置的名称" @@ -2331,15 +2360,15 @@ msgstr "任意区域" msgid "any zone (default policy)" msgstr "任意区域(默认策略)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2598 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2673 msgid "auto" msgstr "自动" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3268 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3343 msgid "before this page opened" msgstr "打开本页之前" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3372 msgid "behind %s, VLAN %d" msgstr "位于 %s 之后,VLAN %d" @@ -2348,16 +2377,16 @@ msgctxt "vantage" msgid "bit/s" msgstr "bit/s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2459 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2534 msgid "collecting · %s of data" msgstr "采集中 · 已采集 %s 数据" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2459 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2534 msgid "collecting · first samples" msgstr "采集中 · 首个样本" #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:251 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2439 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2514 msgid "collecting…" msgstr "采集中…" @@ -2369,18 +2398,18 @@ msgstr "自定义规则文件" msgid "dBm" msgstr "dBm" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1802 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1940 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1877 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 msgid "default route" msgstr "默认路由" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1940 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2015 msgid "default route via %s" msgstr "默认路由经由 %s" #: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:385 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2955 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3296 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3030 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3371 msgid "down" msgstr "已断开" @@ -2389,7 +2418,7 @@ msgctxt "vantage" msgid "drop" msgstr "丢弃" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3349 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3424 msgctxt "vantage" msgid "e.g. Living room TV" msgstr "例如:客厅电视" @@ -2428,8 +2457,8 @@ msgid "half duplex" msgstr "半双工" #: luci-app-vantage/htdocs/luci-static/resources/vantage/fmt.js:62 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1960 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3097 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2035 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3172 msgid "idle" msgstr "空闲" @@ -2471,14 +2500,14 @@ msgctxt "vantage" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2223 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2458 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2298 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2533 msgid "last 5 min" msgstr "最近 5 分钟" #: luci-app-vantage/htdocs/luci-static/resources/vantage/insight.js:175 #: luci-app-vantage/htdocs/luci-static/resources/vantage/wifi.js:104 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3000 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3075 msgid "legacy" msgstr "旧版" @@ -2490,45 +2519,45 @@ msgstr "已连接" msgid "mDNS" msgstr "mDNS" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3321 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3396 msgid "mDNS announcement" msgstr "mDNS 广播" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3252 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3303 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3327 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3378 msgid "measuring" msgstr "测量中" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2434 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2509 msgid "measuring…" msgstr "测量中…" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2415 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2490 msgctxt "vantage" msgid "no data" msgstr "无数据" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1933 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2008 msgid "no uplink" msgstr "无上行链路" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3278 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3353 msgid "not known to this AP" msgstr "此 AP 未识别" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3310 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3385 msgid "not known to this device" msgstr "此设备未识别" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3450 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3525 msgid "not reported (driver placeholder %s)" msgstr "未报告(驱动占位值 %s)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3261 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3336 msgid "not reported by the driver" msgstr "驱动未报告" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2455 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2530 msgctxt "vantage" msgid "now" msgstr "现在" @@ -2537,16 +2566,16 @@ msgstr "现在" msgid "now %s down, %s up" msgstr "当前下行 %s,上行 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3259 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3334 msgid "older than the radio (%s)" msgstr "比射频支持的标准更旧(%s)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2432 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2507 msgctxt "vantage" msgid "peak" msgstr "峰值" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2224 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2299 msgid "per core" msgstr "每核" @@ -2555,11 +2584,11 @@ msgctxt "vantage" msgid "port forward" msgstr "端口转发" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3246 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3321 msgid "range %s … %s" msgstr "范围 %s … %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3493 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3568 msgid "received on %s" msgstr "在 %s 上接收" @@ -2572,7 +2601,7 @@ msgstr "拒绝" msgid "router port %s" msgstr "路由器端口 %s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3494 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3569 msgid "sent on %s" msgstr "在 %s 上发送" @@ -2580,12 +2609,12 @@ msgstr "在 %s 上发送" msgid "short GI" msgstr "短 GI" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2974 -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3305 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3049 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3380 msgid "static entry" msgstr "静态条目" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3298 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3373 msgid "switch port %s" msgstr "交换机端口 %s" @@ -2597,11 +2626,11 @@ msgstr "已关闭" msgid "the covered subnets of zone %s" msgstr "区域 %s 覆盖的子网" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3302 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3377 msgid "the port in total: %s" msgstr "该端口合计:%s" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3297 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:3372 msgid "the port: %s" msgstr "端口:%s" @@ -2617,7 +2646,7 @@ msgstr "此路由器" msgid "traffic rule" msgstr "通信规则" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:1945 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2020 msgid "up %s" msgstr "已运行 %s" @@ -2634,7 +2663,7 @@ msgstr "区域转发" msgid "zones %s and %s if they share a device" msgstr "区域 %s 和 %s(若两者共用设备)" -#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2452 +#: luci-app-vantage/htdocs/luci-static/resources/view/vantage/overview.js:2527 msgid "−%d min" msgstr "−%d 分钟" diff --git a/luci-theme-argon/Makefile b/luci-theme-argon/Makefile index a66e3e271..839441c1e 100644 --- a/luci-theme-argon/Makefile +++ b/luci-theme-argon/Makefile @@ -8,11 +8,12 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Argon Theme # Older SDKs require the coreutils parent menu to enable coreutils-timeout. -LUCI_DEPENDS:=+luci-base +USE_APK:wget-any +!USE_APK:wget +jsonfilter +ucode-mod-math +flock +coreutils +coreutils-timeout +# Virtual wget providers include wget-nossl, but every wallpaper API uses HTTPS. +LUCI_DEPENDS:=+luci-base +wget-ssl +ca-bundle +jsonfilter +ucode-mod-math +flock +coreutils +coreutils-timeout # Keep existing translation package names and the argon-config message domain. LUCI_BASENAME:=argon-config -PKG_VERSION:=3.1.2 -PKG_RELEASE:=41 +PKG_VERSION:=3.1.3 +PKG_RELEASE:=42 PKG_LICENSE:=Apache-2.0 MIT # LuCI derives translations independently of the theme version. Keep release @@ -36,6 +37,20 @@ define Package/luci-theme-argon/conffiles /etc/config/argon endef +# Some firmware builds bundle translations into the theme instead of separate +# language packages. Preserve them even when an older updater installs us alone. +define Package/luci-theme-argon/preinst +#!/bin/sh +root="$${IPKG_INSTROOT}" +for catalog in "$$root"/usr/lib/lua/luci/i18n/argon-config.*.lmo "$$root"/usr/lib/lua/luci/i18n/argon.*.lmo; do + [ -f "$$catalog" ] && [ ! -L "$$catalog" ] || continue + umask 077 + mkdir -p "$$root/etc/argon-config-migration/i18n" || exit 1 + cp -p "$$catalog" "$$root/etc/argon-config-migration/i18n/$${catalog##*/}" || exit 1 +done +exit 0 +endef + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-argon/README.md b/luci-theme-argon/README.md index b3ef06f03..18ebefa15 100644 --- a/luci-theme-argon/README.md +++ b/luci-theme-argon/README.md @@ -41,7 +41,7 @@ It also supports automatic and manual switching between light and dark modes. - **Layout fixes.** Improve dashboard actions, overview layouts, dynamic lists and custom IP/MAC inputs across narrow screens, light/dark modes and RTL layouts. - **Compatibility improvements.** Improve compatibility with stable OpenWrt firmware. -Users on v3.0.0 or earlier must install v3.1.2 manually once to get online updates. Users on v3.1.0 or later can upgrade through Theme updates. See the [release notes](RELEASE.md). +Users on v3.0.0 or earlier must install v3.1.3 manually once to get online updates. Users on v3.1.0 or later can upgrade through Theme updates. See the [release notes](RELEASE.md). ## 3.0 highlights @@ -99,7 +99,9 @@ Local image and video backgrounds are supported, along with Bing, Unsplash and W Under **Theme updates**, check the latest stable release, read its release notes and download the package matching your firmware's package manager. -When a newer version is available, choose **Update now** and confirm to install the theme using the firmware’s native APK or OPKG package manager, preserving your Argon configuration. The page shows download, verification and installation status plus installation logs, and resumes monitoring after a page refresh. Reload the page after installation. Automatic installation requires a matching release package and SHA256 digest and does not perform downgrades. It updates the main theme package; separate translation packages remain managed by the system package manager. +When a newer version is available, choose **Update now** and confirm to install the theme using the firmware’s native APK or OPKG package manager, preserving your Argon configuration. The page shows download, verification and installation status plus installation logs, and resumes monitoring after a page refresh. Reload the page after installation. The updater downloads and verifies the theme and matching packages for your existing Argon translations before installing them. It also installs the configured LuCI language when that translation is available. Automatic installation requires matching release packages and SHA256 digests and does not downgrade the theme. If verified metadata is missing for an existing translation, update the theme and language packages manually from the same release. + +Translations bundled into a firmware's theme package, such as KWRT's Chinese catalog, are preserved during the first upgrade to official packages, including upgrades started by an older updater. A separately installed language package can then take ownership of the catalog. When building firmware, stop including the old standalone `luci-app-argon-config` plugin alongside the theme: its files conflict with the integrated settings. See [Build with OpenWrt](docs/DEVELOPMENT.md#build-with-openwrt) for existing build scripts. diff --git a/luci-theme-argon/README_ZH.md b/luci-theme-argon/README_ZH.md index f184402fe..ed72b18aa 100644 --- a/luci-theme-argon/README_ZH.md +++ b/luci-theme-argon/README_ZH.md @@ -41,7 +41,7 @@ Argon 是**一款干净整洁的 OpenWrt LuCI 主题**, - **布局修复**:优化 Dashboard 操作区、概览布局、动态列表和自定义 IP/MAC 输入框,兼顾窄屏、亮暗色和 RTL 布局。 - **兼容性改进**:改善稳定版 OpenWrt 固件上的兼容性。 -v3.0.0 及更早版本用户需先手动安装一次 v3.1.2,之后即可使用在线更新。v3.1.0 及以上用户可直接通过主题更新升级。详见[更新日志](RELEASE_ZH.md)。 +v3.0.0 及更早版本用户需先手动安装一次 v3.1.3,之后即可使用在线更新。v3.1.0 及以上用户可直接通过主题更新升级。详见[更新日志](RELEASE_ZH.md)。 ## 3.0 主要特性 @@ -99,7 +99,9 @@ apk add --allow-untrusted ./luci-theme-argon-*.apk 在**主题更新**中手动检查最新稳定版、查看更新日志,并下载与固件包管理器匹配的安装包。 -检测到更高版本后,可点击**立即更新**并确认,通过固件自带的 APK 或 OPKG 安装主题,保留当前 Argon 配置。页面显示下载、校验、安装状态及安装日志,刷新页面后可继续查看进度;安装完成后重新加载页面。自动安装要求正式发布提供对应安装包及 SHA256 校验值,不执行降级。此功能更新主题主包,独立语言包仍由系统包管理器管理。 +检测到更高版本后,可点击**立即更新**并确认,通过固件自带的 APK 或 OPKG 安装主题,保留当前 Argon 配置。页面显示下载、校验、安装状态及安装日志,刷新页面后可继续查看进度;安装完成后重新加载页面。更新器会先下载并校验主题与现有 Argon 翻译对应的语言包,再执行安装;如果发布中提供了 LuCI 当前配置语言的翻译,也会一并安装。自动安装要求对应安装包及 SHA256 校验值,不降级主题。现有翻译缺少可校验的语言包信息时,请从同一次发布中手动安装主题和语言包。 + +从 KWRT 等将中文翻译内嵌在主题主包的固件升级时,首次安装官方主题会保留原有翻译,使用旧版更新器发起升级也适用。之后安装独立语言包即可完成翻译文件的归属交接。 自行编译固件时,不要再同时引入旧版独立 `luci-app-argon-config` 插件;它会与主题内置文件冲突。已有自动编译脚本的调整方式见[源码构建说明](docs/DEVELOPMENT_ZH.md#源码构建)。 diff --git a/luci-theme-argon/RELEASE.md b/luci-theme-argon/RELEASE.md index 7e8be352c..fcd081f1f 100644 --- a/luci-theme-argon/RELEASE.md +++ b/luci-theme-argon/RELEASE.md @@ -1,5 +1,11 @@ # Update log for master branch +## v3.1.3 [ 2026.11.06 ] + +- Preserve bundled Argon translations during upgrades and synchronize language packages in subsequent online updates (#737). +- Fix online wallpapers failing on firmware that selects a downloader without HTTPS support (#738). +- Keep bridge VLAN dropdown labels readable instead of wrapping one character per line (#738). + ## v3.1.2 [ 2026.11.02 ] - Fix port card wrapping and alignment, including ImmortalWrt. diff --git a/luci-theme-argon/RELEASE_ZH.md b/luci-theme-argon/RELEASE_ZH.md index 8372c414b..9220c76ce 100644 --- a/luci-theme-argon/RELEASE_ZH.md +++ b/luci-theme-argon/RELEASE_ZH.md @@ -1,5 +1,11 @@ # Master 分支的更新日志 +## v3.1.3 [ 2026.11.06 ] + +- 修复部分固件升级后 Argon 翻译丢失,保留已有翻译,并在后续在线升级时同步语言包(#737)。 +- 修复部分固件因下载器缺少 HTTPS 支持而无法获取在线壁纸的问题(#738)。 +- 修复网桥 VLAN 下拉菜单文字逐字竖排的问题(#738)。 + ## v3.1.2 [ 2026.11.02 ] - 修复端口卡片换行和高度不一致,兼容 ImmortalWrt。 diff --git a/luci-theme-argon/docs/DEVELOPMENT.md b/luci-theme-argon/docs/DEVELOPMENT.md index 72f837aa2..29c6daec2 100644 --- a/luci-theme-argon/docs/DEVELOPMENT.md +++ b/luci-theme-argon/docs/DEVELOPMENT.md @@ -93,7 +93,7 @@ Use monochrome SVGs with a `viewBox` and transparent background. CSS masks suppl ## Static update feed deployment -The router reads a static `/updates/stable.json` manifest without calling the GitHub API. After publication, CI uses its own `GITHUB_TOKEN` to retrieve the official release, verifies the theme package SHA256 digests and sizes, and generates one artifact. GitHub Pages publishes that artifact directly; Cloudflare Pages deploys the same files from a dedicated `updates` Git branch. Packages continue to download from the pinned GitHub Release, and translation packages remain separate. +The router reads a static `/updates/stable.json` manifest without calling the GitHub API. After publication, CI uses its own `GITHUB_TOKEN` to retrieve the official release, verifies theme and translation package SHA256 digests and sizes, and generates one artifact. GitHub Pages publishes that artifact directly; Cloudflare Pages deploys the same files from a dedicated `updates` Git branch. Packages continue to download from the pinned GitHub Release. The installer includes matching packages for existing Argon translations and the configured LuCI language when available. Initial maintainer setup: @@ -119,6 +119,8 @@ Run **Publish update feeds** again to republish GitHub Pages. Identical artifact The manifest contains `schema`, `repository`, `tag`, `published_at`, `notes`, and the `apk`/`ipk` filenames with `_sha256`/`_size` fields. Metadata comes from the published package bytes rather than master's Makefile. Both formats must be complete and match the tag. Malformed feeds trigger fallback and never overwrite the previous successful cache. Checks are manual, with a five-minute success cache, a one-minute failure cooldown and a lock that coalesces concurrent requests. +Schema 1 also supports an optional `translations` object keyed by language package suffix, such as `zh-cn`. Each entry has the same six package fields for both formats. Names must match the theme's release, each translation is limited to 1 MiB, and at most 32 languages are accepted. Existing translations without verified metadata disable automatic installation. All required packages are downloaded and verified before the package manager runs; storage checks use their combined size, and completion requires the expected installed versions. The theme's pre-install hook and UCI initialization preserve bundled catalogs across a first upgrade made by an older updater, without replacing catalogs already supplied by independent language packages. + Source builds default to an empty CF primary. Configure one before packaging: ```sh diff --git a/luci-theme-argon/docs/DEVELOPMENT_ZH.md b/luci-theme-argon/docs/DEVELOPMENT_ZH.md index 7a0b28130..ec402ae76 100644 --- a/luci-theme-argon/docs/DEVELOPMENT_ZH.md +++ b/luci-theme-argon/docs/DEVELOPMENT_ZH.md @@ -93,7 +93,7 @@ lessc less/cascade.less htdocs/luci-static/argon/css/cascade.css ## 静态更新源部署 -更新检查读取 `/updates/stable.json` 静态清单。路由器不调用 GitHub API;发布工作流使用自身的 `GITHUB_TOKEN` 读取正式 Release,核验主题包的 SHA256/大小后生成一份产物。GitHub Pages 直接发布该产物,Cloudflare Pages 从专用 `updates` 分支部署同一份文件。安装包继续从固定的 GitHub Release 版本下载,独立语言包仍单独安装。 +更新检查读取 `/updates/stable.json` 静态清单。路由器不调用 GitHub API;发布工作流使用自身的 `GITHUB_TOKEN` 读取正式 Release,核验主题和语言包的 SHA256/大小后生成一份产物。GitHub Pages 直接发布该产物,Cloudflare Pages 从专用 `updates` 分支部署同一份文件。安装包继续从固定的 GitHub Release 版本下载;安装器会包含现有 Argon 翻译及可用的 LuCI 当前配置语言对应的包。 首次启用需要仓库维护者完成以下配置: @@ -119,6 +119,8 @@ lessc less/cascade.less htdocs/luci-static/argon/css/cascade.css 清单字段包括 `schema`、`repository`、`tag`、`published_at`、`notes`,以及 `apk`/`ipk` 文件名和对应的 `_sha256`/`_size`。由最终发布包计算元数据,不从 master 的 Makefile 推断最新版。两种格式均须完整且属于同一版本;客户端拒绝损坏清单,并保留上一次成功记录。请求只在手动检查时发起,成功缓存五分钟,双源均失败后冷却一分钟。 +Schema 1 还支持可选的 `translations` 对象,以 `zh-cn` 等语言包后缀为键,每项包含双格式对应的六个包字段。文件名须与主题发行版本匹配,单个语言包不超过 1 MiB,最多接受 32 种语言。现有翻译缺少可校验信息时不开放自动安装。所有所需包先完成下载和校验,再调用包管理器;空间检查按总大小计算,安装完成后核对各包版本。主题的 preinst 与 UCI 初始化会保留旧更新器首次升级时的内嵌翻译,并保留独立语言包已提供的文件。 + 源码构建默认不包含 CF 地址。需要自行指定时,在打包前执行: ```sh diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css index 3dda33796..02e9baa1b 100644 --- a/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css +++ b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css @@ -3788,7 +3788,7 @@ body:not(.Interfaces) .cbi-rowstyle-2:first-child { background: transparent; color: inherit; white-space: normal; - overflow-wrap: anywhere; + overflow-wrap: break-word; cursor: pointer; } .cbi-dropdown[open] > ul.dropdown > li > label { diff --git a/luci-theme-argon/less/components/dropdowns.less b/luci-theme-argon/less/components/dropdowns.less index 1d6b1f4d6..43e1b0636 100644 --- a/luci-theme-argon/less/components/dropdowns.less +++ b/luci-theme-argon/less/components/dropdowns.less @@ -99,7 +99,9 @@ background: transparent; color: inherit; white-space: normal; - overflow-wrap: anywhere; + // Let full words contribute to the menu's intrinsic width. `anywhere` + // shrinks compact controls' expanded labels down to a single character. + overflow-wrap: break-word; cursor: pointer; > label { diff --git a/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon b/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon index 0ac96bbac..5550c5faf 100644 --- a/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon +++ b/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon @@ -1,5 +1,22 @@ #!/bin/sh +# OPKG/APK may remove catalogs owned by the previous theme. Keep existing +# translations until a separate language package takes ownership of them. +i18n_backup=/etc/argon-config-migration/i18n +if [ -d "$i18n_backup" ]; then + mkdir -p /usr/lib/lua/luci/i18n || exit 1 + for catalog in "$i18n_backup"/argon-config.*.lmo "$i18n_backup"/argon.*.lmo; do + [ -f "$catalog" ] && [ ! -L "$catalog" ] || continue + target="/usr/lib/lua/luci/i18n/${catalog##*/}" + if [ ! -e "$target" ] && [ ! -L "$target" ]; then + cp -p "$catalog" "$target" || exit 1 + fi + rm -f "$catalog" + done + rmdir "$i18n_backup" 2>/dev/null || true + rmdir /etc/argon-config-migration 2>/dev/null || true +fi + # The empty legacy package saves its conffile before releasing file ownership. if [ -f /etc/argon-config-migration/argon ]; then cp -p /etc/argon-config-migration/argon /etc/config/argon || exit 1 diff --git a/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_update b/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_update index fb6f61070..c3718dec7 100755 --- a/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_update +++ b/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_update @@ -6,6 +6,10 @@ readonly state_dir='/var/run/argon-update' readonly cache_file='/var/run/argon-update/release.json' readonly sources_file='/usr/share/argon/update-sources.json' readonly repository='jerrykuku/luci-theme-argon' +readonly i18n_dir='/usr/lib/lua/luci/i18n' + +wget_bin=/usr/libexec/wget-ssl +[ -x "$wget_bin" ] || wget_bin="$(command -v uclient-fetch || command -v wget)" opkg_query() ( # OPKG locks its database even for status and comparison commands. Keep our @@ -66,7 +70,45 @@ load_sources() { fi } -normalize_manifest() { +valid_language() { + printf '%s\n' "$1" | grep -Eq '^[a-z]{2,3}(-[a-z0-9]{2,8})?$' +} + +valid_translation_asset() { + [ "$1" = "$4" ] && printf '%s\n' "$2" | grep -Eq '^[a-f0-9]{64}$' && + printf '%s\n' "$3" | grep -Eq '^[1-9][0-9]{0,6}$' && [ "$3" -le 1048576 ] +} + +translation_languages() ( + json_get_type kind translations + [ -n "$kind" ] || exit 0 + [ "$kind" = object ] && json_select translations || exit 1 + json_get_keys language_keys + count=0 + for language_key in $language_keys; do + # jshn's reader converts hyphens to underscores. Recover the package + # suffix, then require filenames that exactly match that language. + language="$(printf '%s' "$language_key" | tr '_' '-')" + count=$((count + 1)) + [ "$count" -le 32 ] && valid_language "$language" || exit 1 + json_get_type kind "$language_key" + [ "$kind" = object ] && json_select "$language_key" || exit 1 + for kind in ipk apk; do + json_get_var file "$kind" + json_get_var checksum "${kind}_sha256" + json_get_var bytes "${kind}_size" + case "$kind" in + ipk) expected="luci-i18n-argon-config-${language}_v${ipk#luci-theme-argon_}" ;; + apk) expected="luci-i18n-argon-config-${language}-${apk#luci-theme-argon-}" ;; + esac + valid_translation_asset "$file" "$checksum" "$bytes" "$expected" || exit 1 + done + json_select .. + printf '%s\n' "$language" + done +) + +read_manifest_fields() { json_load_file "$1" || return 1 json_get_var schema schema json_get_var manifest_repository repository @@ -82,6 +124,17 @@ normalize_manifest() { done printf '%s\n' "$published_at" | grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$' || return 1 [ "${#notes}" -le 131072 ] || return 1 + languages="$(translation_languages)" || return 1 +} + +normalize_manifest() { + local manifest_namespace language field + json_set_namespace manifest_input manifest_namespace + if ! read_manifest_fields "$1"; then + json_set_namespace "$manifest_namespace" + return 1 + fi + json_set_namespace "$manifest_namespace" # Copy only the contract fields, not remote status, URLs or local timestamps. json_init json_add_int schema 1 @@ -95,6 +148,29 @@ normalize_manifest() { json_add_string apk_sha256 "$apk_sha256" json_add_int ipk_size "$ipk_size" json_add_int apk_size "$apk_size" + if [ -n "$languages" ]; then + json_add_object translations + for language in $languages; do + json_set_namespace manifest_input + json_select translations + json_select "$language" + for field in ipk apk ipk_sha256 apk_sha256 ipk_size apk_size; do + json_get_var "translation_$field" "$field" + done + json_select .. + json_select .. + json_set_namespace "$manifest_namespace" + json_add_object "$language" + json_add_string ipk "$translation_ipk" + json_add_string apk "$translation_apk" + json_add_string ipk_sha256 "$translation_ipk_sha256" + json_add_string apk_sha256 "$translation_apk_sha256" + json_add_int ipk_size "$translation_ipk_size" + json_add_int apk_size "$translation_apk_size" + json_close_object + done + json_close_object + fi json_add_int checked_at "$(date +%s)" } @@ -131,7 +207,7 @@ check_updates() { for source_url in "$primary_url" "$fallback_url"; do [ -n "$source_url" ] || continue # The two attempts together stay below rpcd's request timeout. - if (ulimit -f 2048; timeout -k 1 5 wget -T 4 -q -U 'luci-theme-argon' \ + if (ulimit -f 2048; timeout -k 1 5 "$wget_bin" -T 4 -q -U 'luci-theme-argon' \ -O "$work/manifest.json" "$source_url") 2>/dev/null && [ "$(wc -c < "$work/manifest.json")" -le 1048576 ] && normalize_manifest "$work/manifest.json"; then json_dump > "$work/cache.json" @@ -172,6 +248,79 @@ select_package() { [ "$size" -gt 0 ] && [ "$size" -le 8388608 ] } +installed_translations() { + { + for catalog in "$i18n_dir"/argon-config.*.lmo "$i18n_dir"/argon.*.lmo; do + [ -f "$catalog" ] && [ ! -L "$catalog" ] || continue + language="${catalog##*/}" + language="${language#*.}" + printf '%s\n' "${language%.lmo}" + done + case "$package_manager" in + apk) apk list --installed 'luci-i18n-argon-config-*' 2>/dev/null | + sed -n 's/^luci-i18n-argon-config-\([a-z][a-z0-9-]*\)-[0-9].*/\1/p' ;; + opkg) opkg_query list-installed 'luci-i18n-argon-config-*' 2>/dev/null | + awk '$1 ~ /^luci-i18n-argon-config-/ { sub(/^luci-i18n-argon-config-/, "", $1); print $1 }' ;; + esac + } | sort -u | while IFS= read -r language; do + valid_language "$language" && printf '%s\n' "$language" + done +} + +# Emit a private, validated download plan. Never install the theme first and +# discover afterwards that the language package is missing or corrupt. +package_plan() ( + printf '%s %s %s\n' "$package" "$digest" "$size" + wanted="$(installed_translations)" + configured="$(uci -q get luci.main.lang 2>/dev/null | tr 'A-Z_' 'a-z-')" + case "$configured" in zh-cn|zh-hans) configured=zh-cn ;; zh-tw|zh-hant) configured=zh-tw ;; nb-no) configured=no ;; esac + if ! json_select translations; then + [ -z "$wanted" ] + exit $? + fi + if valid_language "$configured"; then + json_get_type kind "$configured" + [ "$kind" != object ] || wanted="$(printf '%s\n%s\n' "$wanted" "$configured" | sort -u)" + fi + for language in $wanted; do + json_select "$language" || exit 1 + json_get_var file "$format" + json_get_var checksum "${format}_sha256" + json_get_var bytes "${format}_size" + case "$format" in + ipk) expected="luci-i18n-argon-config-${language}_v${target_version}_all.ipk" ;; + apk) expected="luci-i18n-argon-config-${language}-${target_version}.apk" ;; + esac + valid_translation_asset "$file" "$checksum" "$bytes" "$expected" || exit 1 + printf '%s %s %s\n' "$file" "$checksum" "$bytes" + json_select .. + done +) + +verify_translation_versions() { + local file checksum bytes name expected actual + while read -r file checksum bytes; do + case "$file" in luci-i18n-argon-config-*) ;; *) continue ;; esac + case "$package_manager" in + apk) + name="${file%-${target_version}.apk}" + expected="$target_version" + actual="$(apk list --installed "$name" 2>/dev/null | awk -v prefix="$name-" ' + index($1, prefix) == 1 { print substr($1, length(prefix) + 1); exit }')" ;; + opkg) + name="${file%_v${target_version}_all.ipk}" + expected="v$target_version" + actual="$(opkg_query status "$name" 2>/dev/null | awk ' + /^Version: / { version=$2 } + /^Status: .* installed$/ { installed=1 } + END { if (installed) print version }')" ;; + esac + [ "$actual" = "$expected" ] || return 1 + done </dev/null 2>&1 && command -v sha256sum >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1; then + select_package && is_upgrade && package_plan >/dev/null && command -v flock >/dev/null 2>&1 && command -v sha256sum >/dev/null 2>&1 && command -v timeout >/dev/null 2>&1; then can_upgrade=1 fi json_add_int result "$1" @@ -268,6 +417,7 @@ write_status() { } run_upgrade() { + local plan file checksum bytes total_size # Run a private copy, since installing the theme replaces this RPC script. work="${0%/*}" case "$work" in "$state_dir"/job.??????) ;; *) return 1 ;; esac @@ -277,27 +427,39 @@ run_upgrade() { json_load_file "$work/release.json" && select_package || { write_status failed metadata; return; } installed_version is_upgrade || { write_status failed version; return; } + plan="$(package_plan)" || { write_status failed metadata; return; } + total_size="$(printf '%s\n' "$plan" | awk '{ size += $3 } END { print size }')" # Leave room for download metadata and unpacking. The package manager also # performs its own dependency and storage checks; never force those checks. tmp_free="$(df -Pk "$state_dir" | awk 'END { print $4 }')" root_path=/ [ ! -d /overlay ] || root_path=/overlay root_free="$(df -Pk "$root_path" | awk 'END { print $4 }')" - if [ "${tmp_free:-0}" -lt "$((size / 1024 + 2048))" ] || - [ "${root_free:-0}" -lt "$((size * 3 / 1024 + 1024))" ]; then + if [ "${tmp_free:-0}" -lt "$((total_size / 1024 + 2048))" ] || + [ "${root_free:-0}" -lt "$((total_size * 3 / 1024 + 1024))" ]; then write_status failed space return fi write_status downloading - url="https://github.com/jerrykuku/luci-theme-argon/releases/download/$tag/$package" - (ulimit -f 16384; timeout -k 2 90 wget -T 20 -q -U 'luci-theme-argon' \ - -O "$work/$package" "$url") 2>/dev/null || { write_status failed network; return; } + set -- + while read -r file checksum bytes; do + url="https://github.com/jerrykuku/luci-theme-argon/releases/download/$tag/$file" + (ulimit -f 16384; timeout -k 2 90 "$wget_bin" -T 20 -q -U 'luci-theme-argon' \ + -O "$work/$file" "$url") 2>/dev/null || { write_status failed network; return; } + set -- "$@" "$work/$file" + done < "$work/exit" ) 2>&1 | tail -c 8192 > "$state_dir/log" @@ -315,7 +477,7 @@ run_upgrade() { return fi installed_version - if [ "$current_version" != "$target_version" ]; then + if [ "$current_version" != "$target_version" ] || ! verify_translation_versions "$plan"; then write_status failed install return fi @@ -331,6 +493,7 @@ start_upgrade() { read_cache && [ "$now" -ge "$checked_at" ] && [ "$((now - checked_at))" -lt 300 ] && select_package && [ "$tag" = "$requested_tag" ] && [ "$package" = "$requested_package" ] || { fail 3; return; } is_upgrade || { fail 5; return; } + package_plan >/dev/null || { fail 3; return; } prepare_state || { fail 1; return; } exec 9>"$state_dir/lock" flock -n 9 || { fail 4; return; } diff --git a/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_wallpaper b/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_wallpaper index 2decfaea2..232418e2b 100755 --- a/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_wallpaper +++ b/luci-theme-argon/root/usr/libexec/rpcd/luci.argon_wallpaper @@ -4,8 +4,7 @@ . /lib/functions.sh . /usr/share/libubox/jshn.sh -# the script will be excuted when `argon.@global[0].bing_background == '1'` -# defaults to 'bing' to be compatible with old config +# Default to Bing for the legacy bing_background configuration. WEB_PIC_SRC="$(uci -q get argon.@global[0].online_wallpaper || echo 'bing')" # API_KEY is used by Unsplash and Wallhaven when configured. @@ -16,10 +15,23 @@ EXACT_RESO="$(uci -q get argon.@global[0].use_exact_resolution || echo '1')" CACHE="/var/run/argon_${WEB_PIC_SRC}.url" WRLOCK="/var/lock/argon_${WEB_PIC_SRC}.lock" +# Older releases give wget-ssl and wget-nossl the same alternative priority. +# Use the TLS binary directly even when /usr/bin/wget still selects wget-nossl. +WGET=/usr/libexec/wget-ssl +if [ ! -x "$WGET" ]; then + # Keep source-only deployments compatible with the firmware's downloader. + WGET="$(command -v uclient-fetch || command -v wget)" +fi + +fetch_url() { + # GNU wget may retry beyond -T. Bound the whole request below rpcd's timeout. + timeout -k 1 6 "$WGET" -T 5 -qO- "$1" +} + fetch_pic_url() { case "$WEB_PIC_SRC" in bing) - local picpath="$(wget -T3 -qO- \ + local picpath="$(fetch_url \ "https://www.bing.com/HPImageArchive.aspx?format=js&n=1" | jsonfilter -qe '@.images[0].url' | sed 's/1920x1080/UHD/g')" @@ -27,20 +39,20 @@ fetch_pic_url() { ;; unsplash) if [ -n "$API_KEY" ]; then - wget -T3 -qO- "https://api.unsplash.com/photos/random?client_id=${API_KEY}" | + fetch_url "https://api.unsplash.com/photos/random?client_id=${API_KEY}" | jsonfilter -qe '@["urls"]["regular"]' fi ;; unsplash_*) local collection_id="${WEB_PIC_SRC#unsplash_}" if [ -n "$API_KEY" ]; then - wget -T3 -qO- \ + fetch_url \ "https://api.unsplash.com/photos/random?client_id=${API_KEY}&collections=${collection_id}" | jsonfilter -qe '@["urls"]["regular"]' fi ;; wallhaven) - wget -T3 -qO- \ + fetch_url \ "https://wallhaven.cc/api/v1/search?resolutions=1920x1080&sorting=random" | jsonfilter -qe "@.data[0].path" ;; @@ -49,7 +61,7 @@ fetch_pic_url() { local use_reso="resolutions" [ "$EXACT_RESO" -eq "1" ] || use_reso="atleast" [ -z "$API_KEY" ] || API_KEY="apikey=$API_KEY&" - wget -T3 -qO- \ + fetch_url \ "https://wallhaven.cc/api/v1/search?${API_KEY}q=id%3A${tag_id}&${use_reso}=1920x1080&sorting=random" | jsonfilter -qe '@.data[0].path' ;; @@ -58,9 +70,9 @@ fetch_pic_url() { try_update() { local lock="$WRLOCK" - exec 200>"$lock" + exec 9>"$lock" - if flock -n 200 >"/dev/null" 2>&1; then + if flock -n 9 >"/dev/null" 2>&1; then local picurl="$(fetch_pic_url)" if [ -n "$picurl" ]; then @@ -70,7 +82,7 @@ try_update() { # if not, browser only displays a blank image # NOTE: only happens to Wallhaven.cc source images case "$WEB_PIC_SRC" in - wallhaven*) wget -T3 -qO- "${picurl}" > /dev/null ;; + wallhaven*) fetch_url "${picurl}" > /dev/null ;; esac echo "$picurl" | tee "$CACHE" @@ -79,7 +91,7 @@ try_update() { # and let the login page select a local background instead. : > "$CACHE" fi - flock -u 200 >"/dev/null" 2>&1 + flock -u 9 >"/dev/null" 2>&1 elif [ -s "$CACHE" ]; then cat "$CACHE" fi diff --git a/luci-theme-argon/tests/test_config_migration.py b/luci-theme-argon/tests/test_config_migration.py index da32f28e9..bff6b6e2d 100644 --- a/luci-theme-argon/tests/test_config_migration.py +++ b/luci-theme-argon/tests/test_config_migration.py @@ -51,7 +51,8 @@ if op != 'get': p.write_text(json.dumps(state)) PKG_UPGRADE='1', PATH=str(binary) + os.pathsep + os.environ['PATH']) script = (ROOT / 'root/etc/uci-defaults/30_luci-theme-argon').read_text() self.script = self.root / 'initialize' - self.script.write_text(script.replace('/etc/', str(self.root / 'etc') + '/')) + self.script.write_text(script.replace('/etc/', str(self.root / 'etc') + '/') + .replace('/usr/lib/lua/luci/i18n', str(self.root / 'i18n'))) def initialize(self, state=None): if state is not None: @@ -128,6 +129,40 @@ if op != 'get': p.write_text(json.dumps(state)) check=True, capture_output=True) self.assertFalse((self.root / 'etc/argon-config-migration').exists()) + def theme_preinst(self): + recipe = (ROOT / 'Makefile').read_text() + source = re.search(r'define Package/luci-theme-argon/preinst\n(.*?)\nendef', recipe, re.S).group(1) + script = self.root / 'theme-preinst' + script.write_text(source.replace('$$', '$')) + subprocess.run(['sh', str(script)], env=dict(self.env, IPKG_INSTROOT=str(self.root)), + check=True, capture_output=True) + + def test_bundled_translations_survive_an_older_theme_only_updater(self): + original = self.root / 'usr/lib/lua/luci/i18n/argon-config.zh-cn.lmo' + original.parent.mkdir(parents=True) + original.write_bytes(b'previous Chinese catalog') + self.theme_preinst() + # The previous package removes its formerly owned catalog on upgrade. + original.unlink() + self.initialize() + restored = self.root / 'i18n/argon-config.zh-cn.lmo' + self.assertEqual(restored.read_bytes(), b'previous Chinese catalog') + self.assertFalse((self.root / 'etc/argon-config-migration').exists()) + self.initialize() + self.assertEqual(restored.read_bytes(), b'previous Chinese catalog') + + def test_language_package_catalog_is_not_replaced_by_the_migration_backup(self): + original = self.root / 'usr/lib/lua/luci/i18n/argon-config.de.lmo' + original.parent.mkdir(parents=True) + original.write_bytes(b'old German catalog') + self.theme_preinst() + target = self.root / 'i18n/argon-config.de.lmo' + target.parent.mkdir() + target.write_bytes(b'new official language package') + self.initialize() + self.assertEqual(target.read_bytes(), b'new official language package') + self.assertFalse((self.root / 'etc/argon-config-migration').exists()) + if __name__ == '__main__': unittest.main() diff --git a/luci-theme-argon/tests/test_update_rpc.py b/luci-theme-argon/tests/test_update_rpc.py index ab885f5f8..2d1dd156c 100644 --- a/luci-theme-argon/tests/test_update_rpc.py +++ b/luci-theme-argon/tests/test_update_rpc.py @@ -25,9 +25,31 @@ class UpdateRpcTests(unittest.TestCase): fakebin.mkdir() scripts = { 'apk': '''case "$1" in -list) test -n "$APK_VERSION" || exit 1; v=$APK_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'luci-theme-argon-%s noarch [installed]\\n' "$v" ;; +list) + case "$3" in + luci-i18n-argon-config-*) + if [ -f "$LANG_INSTALLED" ]; then + while read -r name version; do + [ "$3" = 'luci-i18n-argon-config-*' ] || [ "$3" = "$name" ] || continue + printf '%s-%s noarch [installed]\\n' "$name" "$version" + done < "$LANG_INSTALLED" + fi + exit 0 ;; + esac + test -n "$APK_VERSION" || exit 1; v=$APK_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'luci-theme-argon-%s noarch [installed]\\n' "$v" ;; version) test "$COMPARE_FAIL" != 1 || exit 1; [ "$3" = "$4" ] && printf '=\\n' || { [ "$3" = 3.0.0-r20261015 ] && printf '>\\n' || printf '<\\n'; } ;; -add) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-r2' > "$INSTALLED"; echo 'Theme installed' ;; +add) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-r2' > "$INSTALLED" + for file in "$@"; do + case "$file" in */luci-i18n-argon-config-*.apk) + name=${file##*/}; name=${name%-3.0.0-r2.apk} + if [ -f "$LANG_INSTALLED" ]; then + awk -v name="$name" '$1 != name' "$LANG_INSTALLED" > "$LANG_INSTALLED.tmp" + mv "$LANG_INSTALLED.tmp" "$LANG_INSTALLED" + fi + test "$WRONG_LANGUAGE_VERSION" = 1 || printf '%s 3.0.0-r2\\n' "$name" >> "$LANG_INSTALLED" ;; + esac + done + echo 'Theme installed' ;; esac ''', 'opkg': '''if [ "$OPKG_QUERY_GUARD" = 1 ]; then @@ -36,9 +58,23 @@ esac sleep .05 fi case "$1" in -status) v=$OPKG_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'Package: luci-theme-argon\\nVersion: %s\\nStatus: install ok installed\\n' "$v" ;; +list-installed) [ ! -f "$LANG_INSTALLED" ] || awk '{ print $1 " - " $2 }' "$LANG_INSTALLED" ;; +status) + case "$2" in luci-i18n-argon-config-*) + v=$(awk -v name="$2" '$1 == name { v=$2 } END { print v }' "$LANG_INSTALLED" 2>/dev/null) + test -n "$v" || exit 0 + printf 'Package: %s\\nVersion: %s\\nStatus: install ok installed\\n' "$2" "$v"; exit 0 ;; + esac + v=$OPKG_VERSION; [ ! -f "$INSTALLED" ] || v=$(cat "$INSTALLED"); test -n "$v" || exit 1; printf 'Package: luci-theme-argon\\nVersion: %s\\nStatus: install ok installed\\n' "$v" ;; compare-versions) [ "$3" = "<<" ] && [ "$COMPARE_FAIL" != 1 ] && [ "$2" != "$4" ] && [ "$2" != 3.0.0-20261015 ] ;; -install) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-2' > "$INSTALLED"; echo 'Theme installed' ;; +install) printf '%s\\n' "$@" >> "$MUTATIONS"; test "$INSTALL_FAIL" != 1 || { echo 'database locked'; exit 1; }; test "$WRONG_VERSION" = 1 || printf '3.0.0-2' > "$INSTALLED" + for file in "$@"; do + case "$file" in */luci-i18n-argon-config-*.ipk) + name=${file##*/}; name=${name%_v3.0.0-2_all.ipk} + test "$WRONG_LANGUAGE_VERSION" = 1 || printf '%s v3.0.0-2\\n' "$name" >> "$LANG_INSTALLED" ;; + esac + done + echo 'Theme installed' ;; esac ''', 'df': 'printf "Filesystem 1024-blocks Used Available Capacity Mounted on\\nroot 100000 1000 %s 1%% /\\n" "${FREE_KB:-99000}"\n', @@ -56,30 +92,45 @@ case "$destination" in *primary.argon.test*) test "$PRIMARY_FAIL" != 1 || exit 8; cp "${PRIMARY_PAYLOAD:-$PAYLOAD}" "$destination" ;; *) cp "$PAYLOAD" "$destination" ;; esac ;; -*) sleep "${DOWNLOAD_DELAY:-0}"; test "$DOWNLOAD_FAIL" != 1 || exit 8; cp "$PACKAGE_DATA" "$destination" ;; +*) sleep "${DOWNLOAD_DELAY:-0}"; test "$DOWNLOAD_FAIL" != 1 || exit 8 + case "$url" in + *luci-i18n-argon-config-*) test "$LANG_DOWNLOAD_FAIL" != 1 || exit 8; cp "$LANG_DATA" "$destination" ;; + *) cp "$PACKAGE_DATA" "$destination" ;; + esac ;; esac -''' +''', + 'uci': 'test -z "$LUCI_LANGUAGE" || printf "%s\\n" "$LUCI_LANGUAGE"\n' } for name, content in scripts.items(): path = fakebin / name path.write_text('#!/bin/sh\n' + content) path.chmod(0o755) helper = self.directory / 'json_fixture.py' - helper.write_text('''import json,sys + helper.write_text('''import json,re,sys root=json.load(sys.stdin); path=json.loads(sys.argv[1]); op=sys.argv[2]; args=sys.argv[3:] obj=root for key in path: obj=obj[int(key)] if isinstance(obj,list) else obj[key] +def alias(key): return re.sub(r'[^a-zA-Z0-9_]', '_', str(key)) +def resolve(key): + if key in obj: return key + return next((name for name in reversed(list(obj)) if alias(name)==key), key) if op=='select': if args[0]=='..': path=path[:-1] else: - child=obj[int(args[0])] if isinstance(obj,list) else obj[args[0]] + key=args[0] if isinstance(obj,list) else resolve(args[0]) + child=obj[int(key)] if isinstance(obj,list) else obj[key] if not isinstance(child,(dict,list)): raise ValueError('not a container') - path.append(args[0]) + path.append(key) print(json.dumps(path)) -elif op=='keys': print(' '.join(map(str,range(len(obj)) if isinstance(obj,list) else obj.keys()))) +elif op=='keys': print(' '.join(map(alias,range(len(obj)) if isinstance(obj,list) else obj.keys()))) elif op=='get': - value=obj.get(args[0],'') + value=obj.get(resolve(args[0]),'') print(int(value) if isinstance(value,bool) else '' if value is None else value) +elif op=='type': + value=obj.get(resolve(args[0])) + print('object' if isinstance(value,dict) else 'array' if isinstance(value,list) else + 'boolean' if isinstance(value,bool) else 'int' if isinstance(value,int) else + 'string' if isinstance(value,str) else '') elif op=='add': obj[args[1]]=int(args[2]) if args[0]=='int' else bool(int(args[2])) if args[0]=='boolean' else {} if args[0]=='object' else args[2] print(json.dumps(root)) @@ -92,6 +143,7 @@ json_load() {{ FIXTURE_JSON=$1; FIXTURE_PATH='[]'; fixture_json validate >/dev/n json_load_file() {{ json_load "$(cat "$1")"; }} json_init() {{ FIXTURE_JSON='{{}}'; FIXTURE_PATH='[]'; }} json_get_var() {{ fixture_value=$(fixture_json get "$2"); export "$1=$fixture_value"; }} +json_get_type() {{ fixture_value=$(fixture_json type "$2"); export "$1=$fixture_value"; }} json_get_keys() {{ fixture_value=$(fixture_json keys); export "$1=$fixture_value"; }} json_select() {{ fixture_value=$(fixture_json select "$1" 2>/dev/null) || return 1; FIXTURE_PATH=$fixture_value; }} json_add_string() {{ FIXTURE_JSON=$(fixture_json add string "$1" "$2"); }} @@ -100,8 +152,14 @@ json_add_boolean() {{ FIXTURE_JSON=$(fixture_json add boolean "$1" "$2"); }} json_add_object() {{ FIXTURE_JSON=$(fixture_json add object "$1" ''); json_select "$1"; }} json_close_object() {{ json_select ..; }} json_set_namespace() {{ - if [ "$1" = upgrade_status ]; then FIXTURE_SAVED_JSON=$FIXTURE_JSON; FIXTURE_SAVED_PATH=$FIXTURE_PATH; export "$2=base"; - else FIXTURE_JSON=$FIXTURE_SAVED_JSON; FIXTURE_PATH=$FIXTURE_SAVED_PATH; fi + [ "$#" -lt 2 ] || export "$2=${{FIXTURE_NAMESPACE:-base}}" + printf '%s' "$FIXTURE_JSON" > '{self.directory}/namespace-'"${{FIXTURE_NAMESPACE:-base}}"'.json' + printf '%s' "$FIXTURE_PATH" > '{self.directory}/namespace-'"${{FIXTURE_NAMESPACE:-base}}"'.path' + FIXTURE_NAMESPACE=${{1:-base}} + if [ -f '{self.directory}/namespace-'"$FIXTURE_NAMESPACE"'.json' ]; then + FIXTURE_JSON=$(cat '{self.directory}/namespace-'"$FIXTURE_NAMESPACE"'.json') + FIXTURE_PATH=$(cat '{self.directory}/namespace-'"$FIXTURE_NAMESPACE"'.path') + else json_init; fi }} json_dump() {{ printf '%s\\n' "$FIXTURE_JSON"; }} @@ -109,16 +167,22 @@ json_dump() {{ printf '%s\\n' "$FIXTURE_JSON"; }} self.script = self.directory / 'rpc.sh' sources = self.directory / 'sources.json' sources.write_text(json.dumps({'primary': PRIMARY, 'fallback': FALLBACK})) + self.catalogs = self.directory / 'catalogs' + self.catalogs.mkdir() self.script.write_text((ROOT / 'root/usr/libexec/rpcd/luci.argon_update').read_text() .replace('/usr/share/libubox/jshn.sh', str(shim)) .replace('/usr/share/argon/update-sources.json', str(sources)) .replace('/var/run/argon-update/release.json', str(self.cache)) - .replace('/var/run/argon-update', str(self.directory / 'state'))) + .replace('/var/run/argon-update', str(self.directory / 'state')) + .replace('/usr/lib/lua/luci/i18n', str(self.catalogs)) + .replace('wget_bin=/usr/libexec/wget-ssl', 'wget_bin=' + str(fakebin / 'wget'))) self.env = dict(os.environ, PATH=str(fakebin) + os.pathsep + os.environ['PATH'], APK_VERSION='3.0.0-r1', OPKG_VERSION='', PAYLOAD=str(self.payload), REQUESTS=str(self.requests), FETCH_FAIL='0', INSTALLED=str(self.directory / 'installed'), - MUTATIONS=str(self.directory / 'mutations'), PACKAGE_DATA=str(self.directory / 'package')) + MUTATIONS=str(self.directory / 'mutations'), PACKAGE_DATA=str(self.directory / 'package'), + LANG_DATA=str(self.directory / 'language'), LANG_INSTALLED=str(self.directory / 'languages-installed')) (self.directory / 'package').write_bytes(b'argon-package') + (self.directory / 'language').write_bytes(b'argon-language') self.release = {'schema': 1, 'repository': 'jerrykuku/luci-theme-argon', 'tag': 'v3.0.0', 'published_at': '2026-10-16T01:00:00Z', 'notes': '## 更新\n- 修复布局。', 'ipk': 'luci-theme-argon_3.0.0-2_all.ipk', 'apk': 'luci-theme-argon-3.0.0-r2.apk', @@ -297,6 +361,92 @@ json_dump() {{ printf '%s\\n' "$FIXTURE_JSON"; }} time.sleep(.05) self.fail('worker did not finish') + def add_languages(self, *languages): + digest = hashlib.sha256((self.directory / 'language').read_bytes()).hexdigest() + self.release['translations'] = {language: { + 'apk': f'luci-i18n-argon-config-{language}-3.0.0-r2.apk', + 'ipk': f'luci-i18n-argon-config-{language}_v3.0.0-2_all.ipk', + 'apk_sha256': digest, 'ipk_sha256': digest, + 'apk_size': 14, 'ipk_size': 14, + } for language in languages} + self.payload.write_text(json.dumps(self.release)) + + def test_bundled_chinese_is_installed_with_the_theme_for_both_managers(self): + self.add_languages('zh-cn', 'de') + (self.catalogs / 'argon-config.zh-cn.lmo').write_bytes(b'bundled Chinese') + for manager in ['apk', 'opkg']: + with self.subTest(manager=manager): + for file in ['installed', 'languages-installed', 'mutations', 'requests']: + (self.directory / file).unlink(missing_ok=True) + self.env.update(APK_VERSION='3.0.0-r1' if manager == 'apk' else '', + OPKG_VERSION='3.0.0-1' if manager == 'opkg' else '') + self.assertTrue(self.call('check')['can_upgrade']) + self.assertEqual(self.start()['result'], 0) + done = self.finished() + self.assertEqual(done['upgrade']['phase'], 'complete', done) + command = (self.directory / 'mutations').read_text() + self.assertIn('luci-i18n-argon-config-zh-cn', command) + self.assertNotIn('luci-i18n-argon-config-de', command) + self.assertLess(command.index('luci-theme-argon'), command.index('luci-i18n-argon-config-zh-cn')) + self.assertNotIn('force-', command) + + def test_missing_verified_language_metadata_blocks_theme_only_installation(self): + (self.catalogs / 'argon-config.zh-cn.lmo').write_bytes(b'bundled Chinese') + self.assertFalse(self.call('check')['can_upgrade']) + self.assertEqual(self.start()['result'], 3) + self.assertFalse((self.directory / 'mutations').exists()) + + def test_configured_locale_is_added_when_available_and_missing_catalog_packages_are_repaired(self): + self.add_languages('zh-cn', 'de') + self.env['LUCI_LANGUAGE'] = 'zh_Hans' + (self.directory / 'languages-installed').write_text('luci-i18n-argon-config-de 3.0.0-r1\n') + self.assertTrue(self.call('check')['can_upgrade']) + self.assertEqual(self.start()['result'], 0) + self.assertEqual(self.finished()['upgrade']['phase'], 'complete') + command = (self.directory / 'mutations').read_text() + for language in ['zh-cn', 'de']: + self.assertIn('luci-i18n-argon-config-' + language, command) + + def test_language_download_or_checksum_failure_never_mutates_the_theme(self): + self.add_languages('zh-cn') + (self.catalogs / 'argon-config.zh-cn.lmo').touch() + self.call('check') + for failure in ['network', 'checksum']: + with self.subTest(failure=failure): + self.env['LANG_DOWNLOAD_FAIL'] = '1' if failure == 'network' else '0' + if failure == 'checksum': + (self.directory / 'language').write_bytes(b'corrupt') + self.assertEqual(self.start()['result'], 0) + done = self.finished() + self.assertEqual(done['upgrade']['phase'], 'failed') + self.assertEqual(done['upgrade']['error'], failure, done) + self.assertFalse((self.directory / 'mutations').exists()) + + def test_language_version_is_verified_before_reporting_complete(self): + self.add_languages('zh-cn') + (self.catalogs / 'argon-config.zh-cn.lmo').touch() + self.env['WRONG_LANGUAGE_VERSION'] = '1' + self.call('check') + self.assertEqual(self.start()['result'], 0) + self.assertEqual(self.finished()['upgrade']['error'], 'install') + + def test_translation_metadata_is_validated_and_only_contract_fields_are_cached(self): + self.add_languages('zh-cn') + original = self.release['translations']['zh-cn'].copy() + for bad in [[], {'../zh-cn': original}, {'zh-cn': dict(original, apk_size=0)}, + {'zh-cn': dict(original, ipk_sha256='bad')}, + {'zh-cn': dict(original, apk='luci-i18n-argon-config-zh-cn-4.0.0-r1.apk')}]: + with self.subTest(metadata=bad): + (self.directory / 'state/retry_at').unlink(missing_ok=True) + self.payload.write_text(json.dumps(dict(self.release, translations=bad))) + self.assertNotEqual(self.call('check')['result'], 0) + self.assertFalse(self.cache.exists()) + (self.directory / 'state/retry_at').unlink(missing_ok=True) + self.payload.write_text(json.dumps(dict(self.release, translations={'zh-cn': dict(original, url='https://untrusted.invalid/')}))) + result = self.call('check') + self.assertEqual(result['translations']['zh-cn'], original) + self.assertNotIn('untrusted.invalid', self.requests.read_text()) + def test_background_install_for_both_managers_and_status_survives_reloads(self): for manager in ['apk', 'opkg']: with self.subTest(manager=manager): diff --git a/luci-theme-argon/tests/test_update_site.py b/luci-theme-argon/tests/test_update_site.py index 37b033946..b2cd7cc4c 100644 --- a/luci-theme-argon/tests/test_update_site.py +++ b/luci-theme-argon/tests/test_update_site.py @@ -43,6 +43,45 @@ class UpdateSiteTests(unittest.TestCase): def generate(self, release=None): return SITE.generate(release or self.release, self.packages, 'jerrykuku/luci-theme-argon', self.output) + def add_language(self, language='zh-cn'): + metadata = SITE.resolve(self.release['tag_name']) + names = [f'luci-i18n-argon-config-{language}_{metadata["ipk_i18n_version"]}_all.ipk', + f'luci-i18n-argon-config-{language}-{metadata["apk_i18n_version"]}.apk'] + for name in names: + data = ('translation bytes for ' + name).encode() + (self.packages / name).write_bytes(data) + self.release['assets'].append({'name': name, 'size': len(data), + 'digest': 'sha256:' + hashlib.sha256(data).hexdigest()}) + return names + + def test_language_packages_are_versioned_and_verified_in_both_formats(self): + names = self.add_language() + self.add_language('de') + manifest = self.generate() + self.assertEqual(set(manifest['translations']), {'zh-cn', 'de'}) + for kind, name in zip(['ipk', 'apk'], names): + entry = manifest['translations']['zh-cn'] + self.assertEqual(entry[kind], name) + self.assertEqual(entry[kind + '_sha256'], hashlib.sha256((self.packages / name).read_bytes()).hexdigest()) + self.assertEqual(entry[kind + '_size'], (self.packages / name).stat().st_size) + + def test_missing_corrupt_or_wrong_version_language_packages_block_publication(self): + for problem in ['missing-format', 'corrupt', 'wrong-version', 'duplicate']: + with self.subTest(problem=problem): + self.release = self.release_for('v3.1.0') + names = self.add_language() + if problem == 'missing-format': + self.release['assets'].pop() + elif problem == 'corrupt': + (self.packages / names[0]).write_bytes(b'corrupt translation') + elif problem == 'wrong-version': + self.release['assets'][-1]['name'] = names[1].replace('3.1.0', '3.0.0') + else: + self.release['assets'].append(self.release['assets'][-1]) + with self.assertRaises(ValueError): + self.generate() + self.assertFalse(self.output.exists()) + def test_manifest_contains_exact_revision_names_digests_sizes_and_notes(self): for tag in ['v3.0.0', 'v3.1.0']: release = self.release_for(tag) diff --git a/luci-theme-argon/tests/theme-behavior.test.js b/luci-theme-argon/tests/theme-behavior.test.js index 41ca2508b..fb1471a7f 100644 --- a/luci-theme-argon/tests/theme-behavior.test.js +++ b/luci-theme-argon/tests/theme-behavior.test.js @@ -294,8 +294,11 @@ jsonfilter() { return 1; } try { const script = path.join(dir, 'wallpaper.sh'); const cache = path.join(dir, 'wallpaper.url'); + const downloader = path.join(dir, 'wget'); + writeFileSync(downloader, '#!/bin/sh\nexit 1\n', { mode: 0o755 }); writeFileSync(cache, 'https://example.com/old.jpg\n'); writeFileSync(script, source.replace(imports, stub) + .replace('WGET=/usr/libexec/wget-ssl', `WGET="${downloader}"`) .replace('CACHE="/var/run/argon_${WEB_PIC_SRC}.url"', 'CACHE="$TEST_CACHE"') .replace('WRLOCK="/var/lock/argon_${WEB_PIC_SRC}.lock"', 'WRLOCK="$TEST_LOCK"')); for (const wallpaper of ['unsplash', 'unsplash_123']) { @@ -306,7 +309,7 @@ jsonfilter() { return 1; } assert.deepEqual(JSON.parse(output), { url: '' }); } rmSync(cache); - const failedFetch = execFileSync('bash', [script, 'call', 'get_url'], { + const failedFetch = execFileSync('sh', [script, 'call', 'get_url'], { input: '{}\n', encoding: 'utf8', env: { ...process.env, TEST_WALLPAPER: 'unsplash', TEST_KEY: 'test-key', TEST_CACHE: cache, TEST_LOCK: path.join(dir, 'lock') } }); diff --git a/luci-theme-argon/tests/wallpaper-rpc.test.js b/luci-theme-argon/tests/wallpaper-rpc.test.js new file mode 100644 index 000000000..8965ad5cb --- /dev/null +++ b/luci-theme-argon/tests/wallpaper-rpc.test.js @@ -0,0 +1,113 @@ +'use strict'; + +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); +const { execFileSync } = require('node:child_process'); +const test = require('node:test'); + +function fixture(t, budget = '6') { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'argon-wallpaper-')); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + const bin = path.join(dir, 'bin'); + fs.mkdirSync(bin); + const cache = path.join(dir, 'wallpaper.url'); + const requests = path.join(dir, 'requests'); + const ssl = path.join(bin, 'wget-ssl'); + const downloader = `#!/bin/sh +printf '%s\\n' "$0 $*" >> "$REQUESTS" +[ "$FETCH_MODE" != failure ] || exit 1 +[ "$FETCH_MODE" != hang ] || sleep 20 +printf '%s' "$FETCH_PAYLOAD" +`; + for (const name of ['wget-ssl', 'uclient-fetch']) + fs.writeFileSync(path.join(bin, name), downloader, { mode: 0o755 }); + fs.writeFileSync(path.join(bin, 'wget'), '#!/bin/sh\necho "HTTPS support not compiled in" >&2\nexit 1\n', { mode: 0o755 }); + fs.writeFileSync(path.join(bin, 'jsonfilter'), `#!/usr/bin/env python3 +import json,re,sys +try: + value=json.load(sys.stdin) + for key in re.findall(r'[a-zA-Z_]+|[0-9]+',sys.argv[-1]): + value=value[int(key)] if isinstance(value,list) else value[key] + print(value) +except (ValueError,KeyError,IndexError,TypeError): + sys.exit(1) +`, { mode: 0o755 }); + const stub = ` +uci() { + case "$*" in + *online_wallpaper) printf '%s\\n' "$WALLPAPER_SOURCE" ;; + *use_api_key) printf '%s\\n' fixture-key ;; + *use_exact_resolution) printf '1\\n' ;; + esac +} +json_init() { json_url=''; } +json_add_string() { json_url="$2"; } +json_dump() { printf '{"url":"%s"}\\n' "$json_url"; } +json_cleanup() { :; } +`; + const script = path.join(dir, 'rpc.sh'); + const source = fs.readFileSync(path.join(__dirname, '../root/usr/libexec/rpcd/luci.argon_wallpaper'), 'utf8') + .replace('. /lib/functions.sh\n. /usr/share/libubox/jshn.sh', stub) + .replace('CACHE="/var/run/argon_${WEB_PIC_SRC}.url"', `CACHE="${cache}"`) + .replace('WRLOCK="/var/lock/argon_${WEB_PIC_SRC}.lock"', `WRLOCK="${dir}/lock"`) + .replace('WGET=/usr/libexec/wget-ssl', `WGET="${ssl}"`) + .replace('timeout -k 1 6', `timeout -k 1 ${budget}`); + fs.writeFileSync(script, source); + return { + cache, ssl, + requests: () => fs.existsSync(requests) ? fs.readFileSync(requests, 'utf8').trim().split('\n') : [], + call(source = 'bing', body = { images: [{ url: '/th?id=Fixture_1920x1080.jpg' }] }, mode = '') { + return JSON.parse(execFileSync('sh', ['-c', 'ulimit -n 64; exec sh "$@"', 'sh', script, 'call', 'get_url'], { + input: '{}\n', encoding: 'utf8', timeout: 3000, + env: { ...process.env, PATH: bin + path.delimiter + process.env.PATH, + REQUESTS: requests, WALLPAPER_SOURCE: source, FETCH_PAYLOAD: JSON.stringify(body), FETCH_MODE: mode } + })); + } + }; +} + +test('cold wallpaper requests use TLS despite a non-SSL wget, then reuse the cache', t => { + for (const [source, body, expected] of [ + ['bing', { images: [{ url: '/th?id=Fixture_1920x1080.jpg' }] }, 'https://www.bing.com/th?id=Fixture_UHD.jpg'], + ['unsplash', { urls: { regular: 'https://images.unsplash.com/fixture.jpg' } }, 'https://images.unsplash.com/fixture.jpg'], + ['wallhaven', { data: [{ path: 'https://w.wallhaven.cc/full/fixture.jpg' }] }, 'https://w.wallhaven.cc/full/fixture.jpg'] + ]) { + const f = fixture(t); + assert.deepEqual(f.call(source, body), { url: expected }); + assert.equal(fs.readFileSync(f.cache, 'utf8'), expected + '\n'); + const first = f.requests(); + assert.ok(first.length > 0 && first.every(line => line.startsWith(f.ssl + ' '))); + assert.deepEqual(f.call(source, body, 'failure'), { url: expected }); + assert.deepEqual(f.requests(), first); + } +}); + +test('source deployments use uclient-fetch when the standalone TLS binary is absent', t => { + const f = fixture(t); + fs.unlinkSync(f.ssl); + assert.equal(f.call().url, 'https://www.bing.com/th?id=Fixture_UHD.jpg'); + assert.ok(f.requests().every(line => line.includes('/uclient-fetch '))); +}); + +test('failed wallpaper fetches return a local fallback and retry after the cooldown', t => { + const f = fixture(t); + assert.deepEqual(f.call('bing', {}, 'failure'), { url: '' }); + assert.equal(fs.readFileSync(f.cache, 'utf8'), ''); + assert.equal(f.requests().length, 1); + assert.deepEqual(f.call(), { url: '' }); + assert.equal(f.requests().length, 1); + const expired = new Date(Date.now() - 122000); + fs.utimesSync(f.cache, expired, expired); + assert.equal(f.call().url, 'https://www.bing.com/th?id=Fixture_UHD.jpg'); + assert.equal(f.requests().length, 2); +}); + +test('a stalled downloader cannot hold the login wallpaper RPC indefinitely', t => { + const f = fixture(t, '0.2'); + const start = Date.now(); + assert.deepEqual(f.call('bing', {}, 'hang'), { url: '' }); + assert.ok(Date.now() - start < 2000); + assert.equal(fs.readFileSync(f.cache, 'utf8'), ''); +}); diff --git a/luci-theme-vantage/Makefile b/luci-theme-vantage/Makefile index cfe690611..586153063 100644 --- a/luci-theme-vantage/Makefile +++ b/luci-theme-vantage/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-theme-vantage PKG_VERSION:=1.0.15 -PKG_RELEASE:=33 +PKG_RELEASE:=34 PKG_LICENSE:=GPL-3.0-or-later LUCI_TITLE:=Vantage theme @@ -34,6 +34,11 @@ LUCI_MINIFY_CSS:=0 LUCI_BASENAME:=vantage-theme PKG_PO_VERSION:=$(PKG_VERSION)-r$(PKG_RELEASE) +# Appearance for every browser (Appearance under the colour-theme button) +define Package/luci-theme-vantage/conffiles +/etc/config/vantage_theme +endef + define Package/luci-theme-vantage/postrm #!/bin/sh # opkg (24.10) also runs the old package's postrm on an upgrade, as diff --git a/luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js b/luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js index d32576cab..18673690d 100644 --- a/luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js +++ b/luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js @@ -30,6 +30,35 @@ const LOGIN_KEY = 'vantage.login'; /* read by the login page's login.js */ picked here when the dashboard is installed; the dashboard listens for BACKDROP_EVENT */ const BACKDROP_KEY = 'vantage.backdrop.v1'; const BACKDROP_EVENT = 'vantage:backdrop'; +/* Appearance for every browser: saved on the router, in + /etc/config/vantage_theme (section appearance), by whoever may (rpcd + group luci-theme-vantage); header.ut and sysauth.ut hand its values over + as data-vt-look-, and data-vt-look-save says whether this login + may save: 'yes', 'relogin' (it would at a new login: one from before + the group existed) or 'no'. A pick made without that right stays in + this browser (the own key) and wins here, but not for a login that may + save (those keys are dropped then); this browser's last pick (the old + key, also what the dashboard reads under another theme) counts until + the router has one. */ +const LOOK = { + theme: { own: 'vantage.theme.own', before: THEME_KEY, ok: [ 'auto', 'light', 'dark' ] }, + login: { own: 'vantage.login.own', before: LOGIN_KEY, ok: [ 'grid', 'stars', 'none' ] }, + backdrop: { own: 'vantage.backdrop.own', before: BACKDROP_KEY, ok: [ 'grid', 'stars', 'none' ] } +}; +const LOOK_SYNC = 'vantage.look'; /* another tab saved one: { name, value } */ +const LOOK_SET_EVENT = 'vantage:backdrop-set'; /* the dashboard's own picker hands its pick over */ +/* The dashboard's Customize saves its chart style and layouts with the + Appearance, in one write when it is done: { values, done(ok) }. The + template reads them back with these same rules. */ +const VIEW_SAVE_EVENT = 'vantage:view-save'; +const VIEW_CHARTS = [ 'overlay', 'log', 'mirror', 'mirror-split', 'lanes' ]; +const VIEW_LAYOUT = /^(default|[a-z]{1,8}:[0-3]:[1-4](:h)?( [a-z]{1,8}:[0-3]:[1-4](:h)?){0,7})$/; +const callLookSet = rpc.declare({ object: 'uci', method: 'set', params: [ 'config', 'section', 'values' ], reject: true }); +const callLookCommit = rpc.declare({ object: 'uci', method: 'commit', params: [ 'config' ], reject: true }); +/* While an apply awaits its rollback, rpcd refuses commit and revert alike, but not set: a pick set + then could not be taken back, and would go out unseen with the next Save & Apply. So a save starts + with this revert, which has nothing to undo and is refused in just that case. */ +const callLookRevert = rpc.declare({ object: 'uci', method: 'revert', params: [ 'config' ], reject: true }); /* 24px stroke icons, drawn for this theme: constant [tag, attributes] lists, built with createElementNS (no markup parsing, no user data) */ @@ -124,6 +153,30 @@ function svg(name, size) { } function storageGet(k) { try { return localStorage.getItem(k); } catch (e) { return null; } } + +/* the value in force, from [ pending, own, router, before ]: the first + the theme knows, else the first choice (the default); the templates' + inline scripts and login.js do the same without the pending one */ +function lookValue(ok, list) { + for (const v of list) if (ok.indexOf(v) >= 0) return v; + return ok[0]; +} +function lookWrite(values) { + return callLookRevert('vantage_theme') + .then(() => callLookSet('vantage_theme', 'appearance', values)) + .then(() => callLookCommit('vantage_theme').catch(e => callLookRevert('vantage_theme').then(() => { throw e; }, () => { throw e; }))); +} +function viewValue(name, value) { + if (name === 'chart') return VIEW_CHARTS.indexOf(value) >= 0; + return /^layout_(wide|mid|narrow)(_wired)?$/.test(name) && typeof value === 'string' && VIEW_LAYOUT.test(value); +} + +/* the router's value of one, as the templates set it (literal names) */ +function setLookAttr(root, name, value) { + if (name === 'theme') root.setAttribute('data-vt-look-theme', value); + else if (name === 'login') root.setAttribute('data-vt-look-login', value); + else if (name === 'backdrop') root.setAttribute('data-vt-look-backdrop', value); +} function storageSet(k, v) { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, v); } catch (e) {} } function isTyping(el) { @@ -775,7 +828,7 @@ return baseclass.extend({ /* Appearance opened before the menu came in lacks the network path's group (hasDashboard): add it now */ if (this.appear && this.hasDashboard() && !this.appear.querySelector('input[name="vt-backdrop"]')) { - this.appear.appendChild(this.backdropGroup()); + this.appear.insertBefore(this.backdropGroup(), this.appearNote); this.syncAppearance(); } this.dp = (L.env.dispatchpath || []).slice(); @@ -1423,14 +1476,56 @@ return baseclass.extend({ /* -------------------------------------------------------- theme */ + /* may this login save Appearance for every browser (header.ut): yes, relogin or no */ + lookState() { + const v = this.root.getAttribute('data-vt-look-save'); + return v === 'yes' || v === 'relogin' ? v : 'no'; + }, + + /* one Appearance setting (LOOK), the value in force */ + lookPref(name) { + const k = LOOK[name], mine = this.lookState() === 'yes' ? null : storageGet(k.own); + return lookValue(k.ok, [ (this.lookPending || {})[name], mine, this.root.getAttribute('data-vt-look-' + name), storageGet(k.before) ]); + }, + + /* Save one for every browser where this login may, else for this + browser. Saves queue in order and only the latest pick of each is + written; `apply` shows it at once and again when done. A save that + fails leaves the pick shown on this page, with a note. */ + setLook(name, value, apply) { + const k = LOOK[name]; + const pending = this.lookPending || (this.lookPending = {}); + if (k.ok.indexOf(value) < 0 || pending[name] === value) return; + if (this.lookState() !== 'yes') { + storageSet(k.own, value); + storageSet(k.before, value); + apply(); + return; + } + const seqs = this.lookSeqs || (this.lookSeqs = {}), seq = seqs[name] = (seqs[name] || 0) + 1; + pending[name] = value; + this.lookFailed = false; + apply(); + const latest = () => seqs[name] === seq; + this.lookChain = (this.lookChain || Promise.resolve()).then(() => { + if (!latest()) return; + return lookWrite({ [name]: value }) + .then(() => { + /* the router's value first, so other tabs never see a gap */ + setLookAttr(this.root, name, value); + storageSet(LOOK_SYNC, JSON.stringify({ name: name, value: value, at: Date.now() })); + storageSet(k.before, value); + if (latest()) delete pending[name]; + }, () => { if (latest()) this.lookFailed = true; }); + }).then(apply); + }, + themePref() { - const p = storageGet(THEME_KEY); - return (p === 'light' || p === 'dark') ? p : 'auto'; + return this.lookPref('theme'); }, setTheme(pref) { - storageSet(THEME_KEY, pref === 'auto' ? null : pref); - this.applyTheme(); + this.setLook('theme', pref, () => this.applyTheme()); }, applyTheme() { @@ -1450,8 +1545,7 @@ return baseclass.extend({ /* the login page's backdrop (login.js): grid packets unless set */ loginPref() { - const p = storageGet(LOGIN_KEY); - return (p === 'stars' || p === 'none') ? p : 'grid'; + return this.lookPref('login'); }, loginNames() { @@ -1459,8 +1553,7 @@ return baseclass.extend({ }, setLoginPref(pref) { - storageSet(LOGIN_KEY, pref === 'grid' ? null : pref); - this.syncAppearance(); + this.setLook('login', pref, () => this.syncAppearance()); }, /* Vantage's dashboard, where this user may open it: its network path @@ -1470,13 +1563,20 @@ return baseclass.extend({ }, backdropPref() { - const p = storageGet(BACKDROP_KEY); - return (p === 'stars' || p === 'none') ? p : 'grid'; + return this.lookPref('backdrop'); }, setBackdropPref(pref) { - storageSet(BACKDROP_KEY, pref === 'grid' ? null : pref); - window.dispatchEvent(new CustomEvent(BACKDROP_EVENT)); + this.setLook('backdrop', pref, () => this.applyBackdrop()); + }, + + /* the dashboard reads the one in force from data-vt-backdrop */ + applyBackdrop() { + const v = this.backdropPref(); + if (this.root.getAttribute('data-vt-backdrop') !== v) { + this.root.setAttribute('data-vt-backdrop', v); + window.dispatchEvent(new CustomEvent(BACKDROP_EVENT)); + } this.syncAppearance(); }, @@ -1495,11 +1595,42 @@ return baseclass.extend({ } const mq = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)'); if (mq && mq.addEventListener) mq.addEventListener('change', () => { if (this.themePref() === 'auto') this.applyTheme(); }); + /* a login that may save: this browser's private picks no longer count */ + if (this.lookState() === 'yes') Object.keys(LOOK).forEach(n => storageSet(LOOK[n].own, null)); + /* another tab of this browser changed one, or saved one on the router */ + const keys = [ LOOK_SYNC ]; + Object.keys(LOOK).forEach(n => keys.push(LOOK[n].own, LOOK[n].before)); window.addEventListener('storage', ev => { - if (ev.key === THEME_KEY) this.applyTheme(); - else if (ev.key === LOGIN_KEY || ev.key === BACKDROP_KEY) this.syncAppearance(); + if (keys.indexOf(ev.key) < 0) return; + if (ev.key === LOOK_SYNC) { + let m = null; + try { m = JSON.parse(ev.newValue); } catch (e) {} + if (m && Object.prototype.hasOwnProperty.call(LOOK, m.name) && LOOK[m.name].ok.indexOf(m.value) >= 0) + setLookAttr(this.root, m.name, m.value); + } + this.applyTheme(); + this.applyBackdrop(); + }); + /* the dashboard's own picker (Customize), saved as Appearance's */ + window.addEventListener(LOOK_SET_EVENT, ev => { + if (ev.detail && LOOK.backdrop.ok.indexOf(ev.detail) >= 0) { + ev.preventDefault(); + this.setBackdropPref(ev.detail); + } + }); + /* Customize's Done, for a login that may save; for any other it + stays in that browser, which the dashboard says */ + window.addEventListener(VIEW_SAVE_EVENT, ev => { + const d = ev.detail, values = {}; + if (this.lookState() !== 'yes' || !d || !d.values || typeof d.done !== 'function') return; + Object.keys(d.values).forEach(n => { if (viewValue(n, d.values[n])) values[n] = d.values[n]; }); + if (!Object.keys(values).length) return; + ev.preventDefault(); + this.lookChain = (this.lookChain || Promise.resolve()).then(() => lookWrite(values)) + .then(() => d.done(true), () => d.done(false)).catch(() => {}); }); this.applyTheme(); + this.applyBackdrop(); }, /* Appearance, under the colour-theme button: the colour theme, the @@ -1535,7 +1666,10 @@ return baseclass.extend({ [ 'auto', _('Auto', 'vantage-theme'), 'auto' ], [ 'light', _('Light', 'vantage-theme'), 'sun' ], [ 'dark', _('Dark', 'vantage-theme'), 'moon' ] ], v => this.setTheme(v)), group('vt-login', _('Login background'), [ [ 'grid', login.grid ], [ 'stars', login.stars ], [ 'none', login.none ] ], v => this.setLoginPref(v)) - ].concat(this.hasDashboard() ? [ this.backdropGroup() ] : [])); + ].concat(this.hasDashboard() ? [ this.backdropGroup() ] : [], [ + /* where the picks are kept, when not for every browser (syncAppearance) */ + (this.appearNote = E('p', { 'class': 'vt-appear-note', 'role': 'status', 'hidden': 'hidden' })) + ])); box.addEventListener('keydown', ev => { if (ev.key === 'Escape') { ev.preventDefault(); ev.stopPropagation(); this.closeAppearance(true); } else if (ev.key === 'Tab') { @@ -1561,6 +1695,14 @@ return baseclass.extend({ if (!this.appear) return; const now = { 'vt-colour': this.themePref(), 'vt-login': this.loginPref(), 'vt-backdrop': this.backdropPref() }; Array.prototype.forEach.call(this.appear.querySelectorAll('input[type="radio"]'), r => { r.checked = (now[r.name] === r.value); }); + const state = this.lookState(); + const note = state === 'relogin' ? _('Log in again to save Appearance for every browser.') + : state !== 'yes' ? _('Saved in this browser only.') + : this.lookFailed ? _('Could not save this for every browser. Try again.') : ''; + if (this.appearNote) { + if (this.appearNote.textContent !== note) this.appearNote.textContent = note; + this.appearNote.hidden = !note; + } }, openAppearance(btn) { diff --git a/luci-theme-vantage/htdocs/luci-static/vantage/login.js b/luci-theme-vantage/htdocs/luci-static/vantage/login.js index 4a9d73928..901afc629 100644 --- a/luci-theme-vantage/htdocs/luci-static/vantage/login.js +++ b/luci-theme-vantage/htdocs/luci-static/vantage/login.js @@ -1,16 +1,19 @@ /* * Vantage theme - login page backdrop, over the page grid: packets running * along the grid lines (the default) or a starfield flown through, as - * picked under Appearance (localStorage vantage.login, per browser: unset, - * "stars" or "none"). One canvas, no libraries: a frame is a handful of - * batched draws, at most about 60 a second, and nothing runs while the + * picked under Appearance: saved for every browser on the router + * (sysauth.ut's data-vt-look-login), else in this browser (localStorage + * vantage.login.own for one who may not save it for everyone, vantage.login + * from before; menu-vantage.js lookValue). One canvas, no libraries: a + * frame is a handful of batched draws, at most about 60 a second, and nothing runs while the * window is in the background. With reduced motion it draws one still * frame. Logging in speeds it up while the form posts. */ (function () { 'use strict'; - var pick = null; - try { pick = localStorage.getItem('vantage.login'); } catch (e) {} + var v = [ null, document.documentElement.getAttribute('data-vt-look-login'), null ], ok = [ 'grid', 'stars', 'none' ], pick = 'grid', i; + try { v[0] = localStorage.getItem('vantage.login.own'); v[2] = localStorage.getItem('vantage.login'); } catch (e) {} + for (i = 2; i >= 0; i--) if (ok.indexOf(v[i]) >= 0) pick = v[i]; if (pick === 'none') return; var cv = document.createElement('canvas'), ctx = cv.getContext && cv.getContext('2d'); if (!ctx || typeof Path2D !== 'function') return; diff --git a/luci-theme-vantage/htdocs/luci-static/vantage/vantage.css b/luci-theme-vantage/htdocs/luci-static/vantage/vantage.css index f865357ea..14f6d5ce2 100644 --- a/luci-theme-vantage/htdocs/luci-static/vantage/vantage.css +++ b/luci-theme-vantage/htdocs/luci-static/vantage/vantage.css @@ -623,6 +623,9 @@ a.vt-crumb:hover { color: var(--text); } } .vt-appearance[hidden] { display: none; } .vt-appear-set { min-width: 0; margin: 0; padding: 0; border: 0; } +/* where the picks are kept, when not for every browser */ +.vt-appear-note { max-width: 32ch; margin: 0; color: var(--text-3); font-size: var(--fs-sm); line-height: 1.4; } +.vt-appear-note[hidden] { display: none; } .vt-appear-set > legend { margin: 0 0 6px; padding: 0; color: var(--text-3); font-size: var(--fs-micro); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; } .vt-appear-track { display: flex; background: var(--seg-bg); border-radius: var(--r-lg); box-shadow: inset 0 0 0 1px var(--line); } .vt-appear-opt { diff --git a/luci-theme-vantage/po/templates/vantage-theme.pot b/luci-theme-vantage/po/templates/vantage-theme.pot index 51f2b938a..719ca5668 100644 --- a/luci-theme-vantage/po/templates/vantage-theme.pot +++ b/luci-theme-vantage/po/templates/vantage-theme.pot @@ -13,7 +13,7 @@ msgid_plural "%d more chains at this hook" msgstr[0] "" msgstr[1] "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1350 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1403 msgctxt "vantage-theme" msgid "%d result" msgid_plural "%d results" @@ -56,7 +56,7 @@ msgctxt "vantage-theme" msgid "Accept" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1270 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1323 msgid "Actions" msgstr "" @@ -65,22 +65,22 @@ msgctxt "nft match any traffic" msgid "Any packet" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1258 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1259 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1260 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1263 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1267 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1533 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:84 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1311 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1312 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1313 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1316 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1320 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1664 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:132 msgctxt "vantage-theme" msgid "Appearance" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:41 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:48 msgid "Authorization Required" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Auto" msgstr "" @@ -95,7 +95,7 @@ msgctxt "vantage-theme" msgid "Back to the calling chain" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:72 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:120 msgctxt "vantage-theme" msgid "Breadcrumb" msgstr "" @@ -113,17 +113,17 @@ msgctxt "vantage-theme" msgid "Bridged between ports" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Buffered" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:430 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:434 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:483 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:487 msgid "Cache" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Cached" msgstr "" @@ -142,19 +142,19 @@ msgctxt "vantage-theme" msgid "Chains no rule jumps to directly" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:491 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:544 msgid "Channel" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:897 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:950 msgid "Collapse navigation" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1534 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1665 msgid "Colour theme" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1294 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1347 msgid "Command palette" msgstr "" @@ -173,7 +173,11 @@ msgctxt "vantage-theme" msgid "Continues in %s, then comes back here" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1701 +msgid "Could not save this for every browser. Try again." +msgstr "" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Dark" msgstr "" @@ -197,8 +201,8 @@ msgstr "" msgid "Egress" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:897 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:57 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:950 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:105 msgid "Expand navigation" msgstr "" @@ -215,7 +219,7 @@ msgid "" "their counters see only its first packets." msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1260 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1313 msgid "Follow system theme" msgstr "" @@ -233,17 +237,17 @@ msgid "" "if br_netfilter is enabled; the ruleset doesn't show that.)" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:421 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:435 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:474 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:488 msgctxt "vantage-theme" msgid "Free" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgid "Grid packets" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:52 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:100 msgctxt "vantage-theme" msgid "Home" msgstr "" @@ -260,9 +264,9 @@ msgstr "" msgid "IPv6 traffic table \"%h\"" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:429 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:433 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:482 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:486 msgctxt "vantage-theme" msgid "In use" msgstr "" @@ -276,11 +280,11 @@ msgctxt "vantage-theme" msgid "Input" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:45 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:52 msgid "Invalid username and/or password! Please try again." msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1290 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1343 msgid "Jump to a page or action…" msgstr "" @@ -289,27 +293,31 @@ msgctxt "vantage-theme" msgid "Leaves unmatched unchanged" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Light" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:23 -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:57 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:28 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:64 msgid "Log in" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1269 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:87 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1699 +msgid "Log in again to save Appearance for every browser." +msgstr "" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1322 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:135 msgid "Log out" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1263 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1537 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1316 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1668 msgid "Login background" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:51 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:99 msgctxt "vantage-theme" msgid "Main navigation" msgstr "" @@ -319,13 +327,13 @@ msgctxt "vantage-theme" msgid "Masquerade" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:404 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:419 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:457 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:472 msgid "Memory" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1806 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1823 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1948 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1965 msgctxt "vantage-theme" msgid "More actions" msgstr "" @@ -343,8 +351,8 @@ msgstr "" msgid "Network device table \"%h\"" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1267 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1526 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1320 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1657 msgid "Network path background" msgstr "" @@ -353,7 +361,7 @@ msgctxt "vantage-theme" msgid "Next rule" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1348 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1401 msgid "No matching pages" msgstr "" @@ -367,17 +375,17 @@ msgctxt "vantage-theme" msgid "No rules: %s" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgctxt "vantage-theme" msgid "None" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1165 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1218 #: luci-theme-vantage/ucode/template/themes/vantage/header.ut:17 msgid "Not found" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1185 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1238 msgid "Other pages in %s" msgstr "" @@ -391,7 +399,7 @@ msgctxt "vantage-theme" msgid "Packet path" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:93 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:141 msgid "Page tabs" msgstr "" @@ -405,7 +413,7 @@ msgctxt "vantage-theme" msgid "Passes unmatched" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:54 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:61 msgid "Password" msgstr "" @@ -434,7 +442,7 @@ msgctxt "vantage-theme" msgid "Reject" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1292 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1345 msgctxt "vantage-theme" msgid "Results" msgstr "" @@ -454,13 +462,17 @@ msgctxt "vantage-theme" msgid "Rules table" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1290 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:75 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:77 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1700 +msgid "Saved in this browser only." +msgstr "" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1343 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:123 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:125 msgid "Search pages" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1269 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1322 msgid "Session" msgstr "" @@ -471,33 +483,33 @@ msgid_plural "Show %d more rules" msgstr[0] "" msgstr[1] "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1963 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:2105 msgid "Show full description" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1952 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:2094 msgid "Show full help: %s" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:48 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:96 msgid "Skip to content" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgid "Starfield" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:456 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:509 msgid "Storage" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:442 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:444 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:495 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:497 msgctxt "vantage-theme" msgid "Swap" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Swap free" msgstr "" @@ -506,12 +518,12 @@ msgctxt "vantage-theme" msgid "This device" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:421 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:474 msgctxt "vantage-theme" msgid "Total" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:408 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:461 msgid "Total Available" msgstr "" @@ -525,22 +537,29 @@ msgctxt "vantage-theme" msgid "Unchanged" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1258 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1311 msgid "Use dark theme" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1259 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1312 msgid "Use light theme" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:408 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:461 msgid "Used" msgstr "" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:50 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:57 msgid "Username" msgstr "" +#: luci-theme-vantage/root/usr/share/rpcd/acl.d/luci-theme-vantage.json:3 +msgid "" +"Vantage theme: save its Appearance (colour mode, login and network path " +"backgrounds) and the dashboard's chart style and layouts for every browser, " +"in /etc/config/vantage_theme only" +msgstr "" + #: luci-theme-vantage/htdocs/luci-static/resources/vantage-theme/nftflow.js:454 msgctxt "vantage-theme" msgid "Verdict map %s" @@ -551,16 +570,16 @@ msgctxt "vantage-theme" msgid "View" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:484 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:537 msgid "Wireless" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:425 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:478 msgctxt "vantage-theme" msgid "available" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1300 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1353 msgid "close" msgstr "" @@ -574,12 +593,12 @@ msgctxt "vantage-theme" msgid "drops unmatched %s" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "free" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1298 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1351 msgid "navigate" msgstr "" @@ -598,7 +617,7 @@ msgctxt "vantage-theme" msgid "on %s" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1299 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1352 msgctxt "vantage-theme" msgid "open" msgstr "" @@ -608,9 +627,9 @@ msgctxt "vantage-theme" msgid "priority %d" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:430 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:434 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:483 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:487 msgid "reclaimable" msgstr "" @@ -619,12 +638,12 @@ msgctxt "vantage-theme" msgid "rules drop some" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "total" msgstr "" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "used" msgstr "" diff --git a/luci-theme-vantage/po/zh_Hans/vantage-theme.po b/luci-theme-vantage/po/zh_Hans/vantage-theme.po index 349beedd2..a451d451e 100644 --- a/luci-theme-vantage/po/zh_Hans/vantage-theme.po +++ b/luci-theme-vantage/po/zh_Hans/vantage-theme.po @@ -21,7 +21,7 @@ msgid "%d more chain at this hook" msgid_plural "%d more chains at this hook" msgstr[0] "此钩子还有 %d 条链" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1350 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1403 msgctxt "vantage-theme" msgid "%d result" msgid_plural "%d results" @@ -62,7 +62,7 @@ msgctxt "vantage-theme" msgid "Accept" msgstr "接受" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1270 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1323 msgid "Actions" msgstr "操作" @@ -71,22 +71,22 @@ msgctxt "nft match any traffic" msgid "Any packet" msgstr "任意数据包" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1258 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1259 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1260 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1263 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1267 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1533 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:84 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1311 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1312 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1313 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1316 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1320 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1664 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:132 msgctxt "vantage-theme" msgid "Appearance" msgstr "外观" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:41 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:48 msgid "Authorization Required" msgstr "需要授权" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Auto" msgstr "自动" @@ -101,7 +101,7 @@ msgctxt "vantage-theme" msgid "Back to the calling chain" msgstr "返回调用链" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:72 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:120 msgctxt "vantage-theme" msgid "Breadcrumb" msgstr "面包屑" @@ -119,17 +119,17 @@ msgctxt "vantage-theme" msgid "Bridged between ports" msgstr "端口间桥接" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Buffered" msgstr "已缓冲" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:430 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:434 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:483 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:487 msgid "Cache" msgstr "缓存" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Cached" msgstr "已缓存" @@ -148,19 +148,19 @@ msgctxt "vantage-theme" msgid "Chains no rule jumps to directly" msgstr "没有规则直接跳转到的链" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:491 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:544 msgid "Channel" msgstr "信道" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:897 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:950 msgid "Collapse navigation" msgstr "收起导航" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1534 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1665 msgid "Colour theme" msgstr "颜色主题" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1294 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1347 msgid "Command palette" msgstr "命令面板" @@ -179,7 +179,11 @@ msgctxt "vantage-theme" msgid "Continues in %s, then comes back here" msgstr "转入 %s,随后返回此处" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1701 +msgid "Could not save this for every browser. Try again." +msgstr "无法为所有浏览器保存此设置,请重试。" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Dark" msgstr "深色" @@ -203,8 +207,8 @@ msgstr "丢弃未匹配流量" msgid "Egress" msgstr "出口" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:897 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:57 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:950 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:105 msgid "Expand navigation" msgstr "展开导航" @@ -223,7 +227,7 @@ msgstr "" "流量卸载已开启:一条转发连接建立后,它的数据包可以跳过 prerouting、forward " "和 postrouting,因此这些链和它们的计数器只会看到该连接最初的数据包。" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1260 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1313 msgid "Follow system theme" msgstr "跟随系统主题" @@ -244,17 +248,17 @@ msgstr "" "达 input、forward 或 output 链,这里也没有桥接链会过滤它们。(启用 " "br_netfilter 时内核可以把它们交给 IP 链;规则集不体现这一点。)" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:421 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:435 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:474 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:488 msgctxt "vantage-theme" msgid "Free" msgstr "空闲" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgid "Grid packets" msgstr "网格数据包" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:52 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:100 msgctxt "vantage-theme" msgid "Home" msgstr "首页" @@ -271,9 +275,9 @@ msgstr "IPv4/IPv6 流量表 \"%h\"" msgid "IPv6 traffic table \"%h\"" msgstr "IPv6 流量表 \"%h\"" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:429 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:433 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:482 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:486 msgctxt "vantage-theme" msgid "In use" msgstr "已用" @@ -287,11 +291,11 @@ msgctxt "vantage-theme" msgid "Input" msgstr "输入" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:45 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:52 msgid "Invalid username and/or password! Please try again." msgstr "用户名或密码错误,请重试。" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1290 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1343 msgid "Jump to a page or action…" msgstr "跳转到页面或操作…" @@ -300,27 +304,31 @@ msgctxt "vantage-theme" msgid "Leaves unmatched unchanged" msgstr "未匹配流量保持原样" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1535 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1666 msgctxt "vantage-theme" msgid "Light" msgstr "浅色" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:23 -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:57 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:28 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:64 msgid "Log in" msgstr "登录" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1269 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:87 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1699 +msgid "Log in again to save Appearance for every browser." +msgstr "重新登录后即可为所有浏览器保存外观设置。" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1322 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:135 msgid "Log out" msgstr "退出登录" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1263 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1537 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1316 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1668 msgid "Login background" msgstr "登录背景" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:51 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:99 msgctxt "vantage-theme" msgid "Main navigation" msgstr "主导航" @@ -330,13 +338,13 @@ msgctxt "vantage-theme" msgid "Masquerade" msgstr "伪装(NAT)" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:404 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:419 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:457 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:472 msgid "Memory" msgstr "内存" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1806 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1823 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1948 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1965 msgctxt "vantage-theme" msgid "More actions" msgstr "更多操作" @@ -354,8 +362,8 @@ msgstr "网络" msgid "Network device table \"%h\"" msgstr "网络设备表 \"%h\"" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1267 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1526 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1320 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1657 msgid "Network path background" msgstr "网络路径背景" @@ -364,7 +372,7 @@ msgctxt "vantage-theme" msgid "Next rule" msgstr "下一条规则" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1348 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1401 msgid "No matching pages" msgstr "没有匹配的页面" @@ -378,17 +386,17 @@ msgctxt "vantage-theme" msgid "No rules: %s" msgstr "无规则:%s" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgctxt "vantage-theme" msgid "None" msgstr "无" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1165 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1218 #: luci-theme-vantage/ucode/template/themes/vantage/header.ut:17 msgid "Not found" msgstr "未找到" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1185 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1238 msgid "Other pages in %s" msgstr "%s 中的其他页面" @@ -402,7 +410,7 @@ msgctxt "vantage-theme" msgid "Packet path" msgstr "数据包路径" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:93 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:141 msgid "Page tabs" msgstr "页面标签页" @@ -416,7 +424,7 @@ msgctxt "vantage-theme" msgid "Passes unmatched" msgstr "放行未匹配流量" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:54 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:61 msgid "Password" msgstr "密码" @@ -445,7 +453,7 @@ msgctxt "vantage-theme" msgid "Reject" msgstr "拒绝" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1292 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1345 msgctxt "vantage-theme" msgid "Results" msgstr "结果" @@ -465,13 +473,17 @@ msgctxt "vantage-theme" msgid "Rules table" msgstr "规则表" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1290 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:75 -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:77 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1700 +msgid "Saved in this browser only." +msgstr "仅保存在此浏览器中。" + +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1343 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:123 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:125 msgid "Search pages" msgstr "搜索页面" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1269 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1322 msgid "Session" msgstr "会话" @@ -481,33 +493,33 @@ msgid "Show %d more rule" msgid_plural "Show %d more rules" msgstr[0] "再显示 %d 条规则" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1963 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:2105 msgid "Show full description" msgstr "显示完整描述" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1952 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:2094 msgid "Show full help: %s" msgstr "显示完整帮助:%s" -#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:48 +#: luci-theme-vantage/ucode/template/themes/vantage/header.ut:96 msgid "Skip to content" msgstr "跳至正文" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1458 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1552 msgid "Starfield" msgstr "星空" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:456 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:509 msgid "Storage" msgstr "存储" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:442 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:444 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:495 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:497 msgctxt "vantage-theme" msgid "Swap" msgstr "交换空间" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:409 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:462 msgid "Swap free" msgstr "空闲交换空间" @@ -516,12 +528,12 @@ msgctxt "vantage-theme" msgid "This device" msgstr "本设备" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:421 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:474 msgctxt "vantage-theme" msgid "Total" msgstr "总计" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:408 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:461 msgid "Total Available" msgstr "总可用" @@ -535,22 +547,29 @@ msgctxt "vantage-theme" msgid "Unchanged" msgstr "不变" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1258 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1311 msgid "Use dark theme" msgstr "使用深色主题" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1259 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1312 msgid "Use light theme" msgstr "使用浅色主题" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:408 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:461 msgid "Used" msgstr "已用" -#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:50 +#: luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut:57 msgid "Username" msgstr "用户名" +#: luci-theme-vantage/root/usr/share/rpcd/acl.d/luci-theme-vantage.json:3 +msgid "" +"Vantage theme: save its Appearance (colour mode, login and network path " +"backgrounds) and the dashboard's chart style and layouts for every browser, " +"in /etc/config/vantage_theme only" +msgstr "Vantage 主题:为所有浏览器保存其外观设置(颜色模式、登录页与网络路径背景)以及仪表盘的图表样式和布局,仅写入 /etc/config/vantage_theme" + #: luci-theme-vantage/htdocs/luci-static/resources/vantage-theme/nftflow.js:454 msgctxt "vantage-theme" msgid "Verdict map %s" @@ -561,16 +580,16 @@ msgctxt "vantage-theme" msgid "View" msgstr "视图" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:484 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:537 msgid "Wireless" msgstr "无线" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:425 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:478 msgctxt "vantage-theme" msgid "available" msgstr "可用" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1300 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1353 msgid "close" msgstr "关闭" @@ -584,12 +603,12 @@ msgctxt "vantage-theme" msgid "drops unmatched %s" msgstr "丢弃未匹配的 %s" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "free" msgstr "空闲" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1298 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1351 msgid "navigate" msgstr "移动" @@ -608,7 +627,7 @@ msgctxt "vantage-theme" msgid "on %s" msgstr "接口 %s" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1299 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:1352 msgctxt "vantage-theme" msgid "open" msgstr "打开" @@ -618,9 +637,9 @@ msgctxt "vantage-theme" msgid "priority %d" msgstr "优先级 %d" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:420 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:430 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:434 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:473 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:483 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:487 msgid "reclaimable" msgstr "可回收" @@ -629,16 +648,23 @@ msgctxt "vantage-theme" msgid "rules drop some" msgstr "部分规则会丢弃" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "total" msgstr "总计" -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:471 -#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:475 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:524 +#: luci-theme-vantage/htdocs/luci-static/resources/menu-vantage.js:528 msgid "used" msgstr "已用" +#~ msgid "" +#~ "Vantage theme: save its Appearance (colour mode, login and network path " +#~ "backgrounds) for every browser, in /etc/config/vantage_theme only" +#~ msgstr "" +#~ "Vantage 主题:为所有浏览器保存其外观设置(颜色模式、登录页与网络路径背" +#~ "景),仅写入 /etc/config/vantage_theme" + #~ msgctxt "vantage-theme" #~ msgid "Press" #~ msgstr "按" diff --git a/luci-theme-vantage/root/etc/config/vantage_theme b/luci-theme-vantage/root/etc/config/vantage_theme new file mode 100644 index 000000000..2ca9ce0c3 --- /dev/null +++ b/luci-theme-vantage/root/etc/config/vantage_theme @@ -0,0 +1,14 @@ +# Vantage theme settings (luci-theme-vantage). +# +# Appearance for every browser on this router, as picked under the theme's +# Appearance button; an option left out keeps each browser's own pick: +# +# option theme 'auto' auto, light or dark +# option login 'grid' the login page's background: grid, stars or none +# option backdrop 'grid' the dashboard's network path background, likewise +# +# The dashboard's Customize saves here too: its chart style (option chart) and +# one layout per screen size (option layout_wide, layout_mid, layout_narrow and +# the same with _wired), which are best changed there. + +config appearance 'appearance' diff --git a/luci-theme-vantage/root/usr/share/rpcd/acl.d/luci-theme-vantage.json b/luci-theme-vantage/root/usr/share/rpcd/acl.d/luci-theme-vantage.json new file mode 100644 index 000000000..c4bd30798 --- /dev/null +++ b/luci-theme-vantage/root/usr/share/rpcd/acl.d/luci-theme-vantage.json @@ -0,0 +1,11 @@ +{ + "luci-theme-vantage": { + "description": "Vantage theme: save its Appearance (colour mode, login and network path backgrounds) and the dashboard's chart style and layouts for every browser, in /etc/config/vantage_theme only", + "write": { + "ubus": { + "uci": [ "set", "commit", "revert" ] + }, + "uci": [ "vantage_theme" ] + } + } +} diff --git a/luci-theme-vantage/ucode/template/themes/vantage/header.ut b/luci-theme-vantage/ucode/template/themes/vantage/header.ut index 5166f0b13..a73c52347 100644 --- a/luci-theme-vantage/ucode/template/themes/vantage/header.ut +++ b/luci-theme-vantage/ucode/template/themes/vantage/header.ut @@ -16,11 +16,48 @@ const found = !!dispatched?.action?.type && dispatched.action.type != 'firstchild'; const page_title = !authed ? null : !found ? _('Not found') : dispatched?.title ? striptags(_(dispatched.title)) : null; const lang = entityencode(dispatcher.lang ?? 'en', true); - const boardinfo = ubus.call("system", "board"); - const hostname = striptags(boardinfo?.hostname ?? '?'); + /* Appearance for every browser (/etc/config/vantage_theme): a value the + theme knows, else '' (each browser keeps its own pick). Logged in only: + nothing is read for an anonymous 404 or CSRF page */ + const look = (opt, ok) => { const v = authed ? uci.get('vantage_theme', 'appearance', opt) : null; return (type(v) == 'string' && index(ok, v) >= 0) ? v : ''; }; + const look_theme = look('theme', [ 'auto', 'light', 'dark' ]); + const look_login = look('login', [ 'grid', 'stars', 'none' ]); + const look_backdrop = look('backdrop', [ 'grid', 'stars', 'none' ]); + /* The dashboard's chart style and layouts, saved with it. A layout passes + only in the form vantage.layout reads, 'wide=hero:0:4 chart:0:2:h;mid=default' */ + const look_chart = look('chart', [ 'overlay', 'log', 'mirror', 'mirror-split', 'lanes' ]); + const look_layout = (() => { + let out = []; + if (authed) + for (let k in [ 'wide', 'mid', 'narrow', 'wide_wired', 'mid_wired', 'narrow_wired' ]) { + const v = uci.get('vantage_theme', 'appearance', 'layout_' + k); + if (type(v) == 'string' && match(v, /^(default|[a-z]{1,8}:[0-3]:[1-4](:h)?( [a-z]{1,8}:[0-3]:[1-4](:h)?){0,7})$/)) + push(out, k + '=' + v); + } + return join(';', out); + })(); + /* May this login save it for every browser? 'yes'; 'relogin' when rpcd + would grant the theme's group at a new login and no reload of rpcd + has given it to this one yet (the install's reload reaches open + logins); 'no' otherwise, and without the config's section. Only the + word reaches the page. */ + const look_save = (() => { + if (!authed || type(uci.get_all('vantage_theme', 'appearance')) != 'object') return 'no'; + const held = ctx.authacl?.['access-group']?.['luci-theme-vantage']; + if (type(held) == 'array' && index(held, 'write') >= 0) return 'yes'; + let would = false; + uci.foreach('rpcd', 'login', s => { + if (s.username !== ctx.authuser) return; + for (let p in (type(s.write) == 'array' ? s.write : [ s.write ])) + if (type(p) == 'string' && wildcard('luci-theme-vantage', p)) would = true; + }); + return would ? 'relogin' : 'no'; + })(); +const boardinfo = ubus.call("system", "board"); +const hostname = striptags(boardinfo?.hostname ?? '?'); -%} - + @@ -28,11 +65,22 @@ {{ page_title ? entityencode(page_title, true) + ' · ' : '' }}LuCI diff --git a/luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut b/luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut index 30354fe88..23c4704e7 100644 --- a/luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut +++ b/luci-theme-vantage/ucode/template/themes/vantage/sysauth.ut @@ -5,18 +5,23 @@ fuser is attacker-controlled (formvalue also reads the query string): it is only tested, never echoed; the error is generic. The form posts back to the requested URL (no action attribute). The inline script is data-free: the - HTTPS probe reads its port list from an entity-encoded data attribute. + HTTPS probe reads its port list from an entity-encoded data attribute. The + Appearance saved for every browser (/etc/config/vantage_theme) comes as + data attributes of values the theme knows only. -#} {% let tls = uci.get('uhttpd', 'main', 'listen_https') ?? []; if (type(tls) == 'string') tls = split(tls, /\s+/); const tls_ports = uniq(filter(map(tls, e => +(match(e, /\d+$/)?.[0] ?? 0)), p => (p > 0 && p <= 65535))); + const look = (opt, ok) => { const v = uci.get('vantage_theme', 'appearance', opt); return (type(v) == 'string' && index(ok, v) >= 0) ? v : ''; }; + const look_theme = look('theme', [ 'auto', 'light', 'dark' ]); + const look_login = look('login', [ 'grid', 'stars', 'none' ]); const boardinfo = ubus.call("system", "board"); const hostname = striptags(boardinfo?.hostname ?? '?'); -%} - + @@ -25,8 +30,10 @@ {{ entityencode(_('Log in'), true) }} · LuCI