🗽 Sync 2026-11-11 15:31:38

This commit is contained in:
github-actions[bot] committed 2026-11-11 15:31:38 +08:00
1 parent da9e4bea36
commit 2e3c0a9b33
189 files changed
+29796 -10432

No files matched your search

+21 -10
View File
@@ -15,7 +15,7 @@ AGENTFLOW_HASH_aarch64:=7790a94a0a04e57d196165ef96177475125c1b24fe24321f6927a55b
PKG_NAME:=agentflow PKG_NAME:=agentflow
PKG_VERSION:=0.3.5 PKG_VERSION:=0.3.5
PKG_RELEASE:=15 PKG_RELEASE:=16
AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH) AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH)
AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH)) AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH))
@@ -52,16 +52,28 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/agentflow /etc/config/agentflow
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/30-agentflow.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/agentflow/agentflow-plugin.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json 2>/dev/null)" = "/usr/share/agentflow/agentflow-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json registration="$${root}$${directory}/30-agentflow.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/agentflow/agentflow-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkease/apps.d/30-agentflow.json 2>/dev/null)" = "/usr/share/agentflow/agentflow-plugin.json" ]; then done
rm -f /usr/share/linkease/apps.d/30-agentflow.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -77,14 +89,13 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config $(1)/usr/share/agentflow/www $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config $(1)/usr/share/agentflow/www $(1)/usr/share/linkease/apps.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/agentflow $(1)/usr/sbin/agentflow $(INSTALL_BIN) $(PKG_BUILD_DIR)/agentflow $(1)/usr/sbin/agentflow
$(INSTALL_BIN) ./files/agentflow.init $(1)/etc/init.d/agentflow $(INSTALL_BIN) ./files/agentflow.init $(1)/etc/init.d/agentflow
$(INSTALL_BIN) ./files/agentflow.uci-default $(1)/etc/uci-defaults/09-agentflow $(INSTALL_BIN) ./files/agentflow.uci-default $(1)/etc/uci-defaults/09-agentflow
$(INSTALL_CONF) ./files/agentflow.config $(1)/etc/config/agentflow $(INSTALL_CONF) ./files/agentflow.config $(1)/etc/config/agentflow
$(INSTALL_DATA) ./files/agentflow-plugin.json $(1)/usr/share/agentflow/agentflow-plugin.json $(INSTALL_DATA) ./files/agentflow-plugin.json $(1)/usr/share/agentflow/agentflow-plugin.json
$(INSTALL_DATA) ./files/www/logo.svg $(1)/usr/share/agentflow/www/logo.svg $(INSTALL_DATA) ./files/www/logo.svg $(1)/usr/share/agentflow/www/logo.svg
ln -sf /usr/share/agentflow/agentflow-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/30-agentflow.json
ln -sf /usr/share/agentflow/agentflow-plugin.json $(1)/usr/share/linkease/apps.d/30-agentflow.json ln -sf /usr/share/agentflow/agentflow-plugin.json $(1)/usr/share/linkease/apps.d/30-agentflow.json
endef endef
+21 -10
View File
@@ -11,7 +11,7 @@ PKG_ARCH_BAIDUDRIVE:=$(ARCH)
PKG_NAME:=baidudrive PKG_NAME:=baidudrive
PKG_VERSION:=1.0.6 PKG_VERSION:=1.0.6
PKG_RELEASE:=22 PKG_RELEASE:=23
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/baidudrive-runtime-v$(PKG_VERSION)/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/baidudrive-runtime-v$(PKG_VERSION)/
PKG_HASH:=skip PKG_HASH:=skip
@@ -41,16 +41,28 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/baidudrive /etc/config/baidudrive
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/baidudrive/baidudrive-plugin.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json 2>/dev/null)" = "/usr/share/baidudrive/baidudrive-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json registration="$${root}$${directory}/10-baidudrive-plugin.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/baidudrive/baidudrive-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkease/apps.d/10-baidudrive-plugin.json 2>/dev/null)" = "/usr/share/baidudrive/baidudrive-plugin.json" ]; then done
rm -f /usr/share/linkease/apps.d/10-baidudrive-plugin.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -61,11 +73,10 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/baidudrive $(1)/usr/share/baidudrive/www $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(1)/opt/baidunas-sdk $(1)/opt/baidunas-glibc $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/baidudrive $(1)/usr/share/baidudrive/www $(1)/usr/share/linkease/apps.d $(1)/opt/baidunas-sdk $(1)/opt/baidunas-glibc $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/baidudrive.$(PKG_ARCH_BAIDUDRIVE) $(1)/usr/sbin/baidudrive $(INSTALL_BIN) $(PKG_BUILD_DIR)/baidudrive.$(PKG_ARCH_BAIDUDRIVE) $(1)/usr/sbin/baidudrive
$(CP) $(PKG_BUILD_DIR)/web/dist/. $(1)/usr/share/baidudrive/www/ $(CP) $(PKG_BUILD_DIR)/web/dist/. $(1)/usr/share/baidudrive/www/
$(INSTALL_DATA) ./files/baidudrive-plugin.json $(1)/usr/share/baidudrive/baidudrive-plugin.json $(INSTALL_DATA) ./files/baidudrive-plugin.json $(1)/usr/share/baidudrive/baidudrive-plugin.json
ln -sf /usr/share/baidudrive/baidudrive-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json
ln -sf /usr/share/baidudrive/baidudrive-plugin.json $(1)/usr/share/linkease/apps.d/10-baidudrive-plugin.json ln -sf /usr/share/baidudrive/baidudrive-plugin.json $(1)/usr/share/linkease/apps.d/10-baidudrive-plugin.json
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/baiduNas $(1)/opt/baidunas-sdk/baiduNas $(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/baiduNas $(1)/opt/baidunas-sdk/baiduNas
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/P2PClient.bin $(1)/opt/baidunas-sdk/P2PClient.bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/P2PClient.bin $(1)/opt/baidunas-sdk/P2PClient.bin
+21 -10
View File
@@ -10,7 +10,7 @@ PKG_ARCH_DOCKERMANAGER:=$(ARCH)
PKG_NAME:=dockermanager PKG_NAME:=dockermanager
PKG_VERSION:=0.1.2 PKG_VERSION:=0.1.2
PKG_RELEASE:=9 PKG_RELEASE:=10
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/dockermanager-runtime-v$(PKG_VERSION)/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/dockermanager-runtime-v$(PKG_VERSION)/
PKG_HASH:=skip PKG_HASH:=skip
@@ -37,16 +37,28 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/dockermanager /etc/config/dockermanager
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/20-dockermanager-plugin.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/dockermanager/dockermanager-plugin.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/20-dockermanager-plugin.json 2>/dev/null)" = "/usr/share/dockermanager/dockermanager-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkeasefull/desktop-apps.d/20-dockermanager-plugin.json registration="$${root}$${directory}/20-dockermanager-plugin.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/dockermanager/dockermanager-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkease/apps.d/20-dockermanager-plugin.json 2>/dev/null)" = "/usr/share/dockermanager/dockermanager-plugin.json" ]; then done
rm -f /usr/share/linkease/apps.d/20-dockermanager-plugin.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -57,12 +69,11 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/dockermanager/www $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(1)/etc/init.d $(1)/etc/config $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/dockermanager/www $(1)/usr/share/linkease/apps.d $(1)/etc/init.d $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/docker-manager.$(PKG_ARCH_DOCKERMANAGER) $(1)/usr/sbin/docker-manager $(INSTALL_BIN) $(PKG_BUILD_DIR)/docker-manager.$(PKG_ARCH_DOCKERMANAGER) $(1)/usr/sbin/docker-manager
$(CP) $(PKG_BUILD_DIR)/www/* $(1)/usr/share/dockermanager/www/ $(CP) $(PKG_BUILD_DIR)/www/* $(1)/usr/share/dockermanager/www/
$(INSTALL_DATA) ./files/logo.svg $(1)/usr/share/dockermanager/www/logo.svg $(INSTALL_DATA) ./files/logo.svg $(1)/usr/share/dockermanager/www/logo.svg
$(INSTALL_DATA) ./files/dockermanager-plugin.json $(1)/usr/share/dockermanager/dockermanager-plugin.json $(INSTALL_DATA) ./files/dockermanager-plugin.json $(1)/usr/share/dockermanager/dockermanager-plugin.json
ln -sf /usr/share/dockermanager/dockermanager-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/20-dockermanager-plugin.json
ln -sf /usr/share/dockermanager/dockermanager-plugin.json $(1)/usr/share/linkease/apps.d/20-dockermanager-plugin.json ln -sf /usr/share/dockermanager/dockermanager-plugin.json $(1)/usr/share/linkease/apps.d/20-dockermanager-plugin.json
$(INSTALL_BIN) ./files/dockermanager.init $(1)/etc/init.d/dockermanager $(INSTALL_BIN) ./files/dockermanager.init $(1)/etc/init.d/dockermanager
$(INSTALL_CONF) ./files/dockermanager.config $(1)/etc/config/dockermanager $(INSTALL_CONF) ./files/dockermanager.config $(1)/etc/config/dockermanager
+9 -6
View File
@@ -6,21 +6,24 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=dufs PKG_NAME:=dufs
PKG_VERSION:=0.47.0 PKG_VERSION:=0.47.0
PKG_RELEASE:=3 PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-vendor.tar.zst
PKG_SOURCE_URL:=https://codeload.github.com/sigoden/dufs/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=@OPENWRT
PKG_SOURCE_PROTO:=cargo-vendor-github
PKG_VENDOR_REPO:=sigoden/dufs
PKG_VENDOR_TAG:=v$(PKG_VERSION)
PKG_VENDOR_HASH:=bab9d4fa1654adc6c88523b61bb8697f575334248cf554282e1f87e2329c0569
PKG_HASH:=skip PKG_HASH:=skip
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org> PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=Apache-2.0 MIT PKG_LICENSE:=Apache-2.0 MIT
PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT
PKG_BUILD_DEPENDS:=rust/host
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk include $(INCLUDE_DIR)/rust-package.mk
define Package/dufs define Package/dufs
SECTION:=net SECTION:=net
@@ -28,7 +31,7 @@ define Package/dufs
SUBMENU:=Web Servers/Proxies SUBMENU:=Web Servers/Proxies
TITLE:=A distinctive utility file server TITLE:=A distinctive utility file server
URL:=https://github.com/sigoden/dufs URL:=https://github.com/sigoden/dufs
DEPENDS:=$(RUST_ARCH_DEPENDS) @!(i386||mips64) +liblzma DEPENDS:=$(RUST_PKG_DEPENDS) @!(i386||mips64) +liblzma
endef endef
define Package/dufs/description define Package/dufs/description
+16 -6
View File
@@ -9,8 +9,8 @@ include $(TOPDIR)/rules.mk
PKG_ARCH_FASTNET:=$(ARCH) PKG_ARCH_FASTNET:=$(ARCH)
PKG_NAME:=fastnet PKG_NAME:=fastnet
PKG_VERSION:=0.8.1 PKG_VERSION:=0.8.9
PKG_RELEASE:=9 PKG_RELEASE:=10
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/fastnet-runtime-v$(PKG_VERSION)/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/fastnet-runtime-v$(PKG_VERSION)/
@@ -33,11 +33,17 @@ endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then if [ -z "$${IPKG_INSTROOT:-}" ]; then
if [ "$$(readlink /usr/share/linkease/apps.d/17-fastnet.json 2>/dev/null)" = "/usr/share/fastnet/fastnet-plugin.json" ]; then /etc/init.d/fastnet stop 2>/dev/null || true
rm -f /usr/share/linkease/apps.d/17-fastnet.json
fi
fi fi
root="$${IPKG_INSTROOT:-}"
for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
registration="$${root}$${directory}/17-fastnet.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/fastnet/fastnet-plugin.json" ]; then
rm -f "$${registration}"
fi
done
rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
exit 0 exit 0
endef endef
@@ -51,6 +57,9 @@ endef
define Package/$(PKG_NAME)/postinst define Package/$(PKG_NAME)/postinst
#!/bin/sh #!/bin/sh
# Maintain the old desktop entry without a second manifest or file owner.
root="$${IPKG_INSTROOT:-}"
sh "$${root}/usr/share/fastnet/register-desktop.sh" || exit $$?
if [ -z "$${IPKG_INSTROOT}" ]; then if [ -z "$${IPKG_INSTROOT}" ]; then
[ -f /etc/uci-defaults/fastnet ] && /etc/uci-defaults/fastnet && rm -f /etc/uci-defaults/fastnet [ -f /etc/uci-defaults/fastnet ] && /etc/uci-defaults/fastnet && rm -f /etc/uci-defaults/fastnet
exit 0 exit 0
@@ -70,6 +79,7 @@ define Package/$(PKG_NAME)/install
$(INSTALL_BIN) ./files/fastnet.init $(1)/etc/init.d/fastnet $(INSTALL_BIN) ./files/fastnet.init $(1)/etc/init.d/fastnet
$(INSTALL_BIN) ./files/fastnet.uci-default $(1)/etc/uci-defaults/fastnet $(INSTALL_BIN) ./files/fastnet.uci-default $(1)/etc/uci-defaults/fastnet
$(INSTALL_DATA) ./files/fastnet-plugin.json $(1)/usr/share/fastnet/fastnet-plugin.json $(INSTALL_DATA) ./files/fastnet-plugin.json $(1)/usr/share/fastnet/fastnet-plugin.json
$(INSTALL_BIN) ./files/register-desktop.sh $(1)/usr/share/fastnet/register-desktop.sh
ln -sf /usr/share/fastnet/fastnet-plugin.json $(1)/usr/share/linkease/apps.d/17-fastnet.json ln -sf /usr/share/fastnet/fastnet-plugin.json $(1)/usr/share/linkease/apps.d/17-fastnet.json
endef endef
+24 -4
View File
@@ -29,9 +29,13 @@
} }
}, },
"config": { "config": {
"providerOrder": ["uci"], "providerOrder": [
"uci"
],
"providers": { "providers": {
"uci": {"type": "uci"} "uci": {
"type": "uci"
}
} }
}, },
"window": { "window": {
@@ -39,6 +43,22 @@
"height": 760, "height": 760,
"singleton": true "singleton": true
}, },
"capabilities": ["speed-test", "diagnostics", "network"], "capabilities": [
"categories": ["network", "service"] "speed-test",
"diagnostics",
"network"
],
"categories": [
"network",
"service"
],
"backend": {
"type": "http",
"scheme": "http",
"host": "127.0.0.1",
"portFromUci": "fastnet.@fastnet[0].port",
"defaultPort": 3200,
"upstreamBasePath": "/",
"pathMode": "strip-public-base"
}
} }
+1
View File
@@ -21,6 +21,7 @@ start_service() {
procd_open_instance procd_open_instance
procd_set_param limits nofile="65535 65535" procd_set_param limits nofile="65535 65535"
procd_set_param command /usr/sbin/FastNet web --addr "$addr" --no-open procd_set_param command /usr/sbin/FastNet web --addr "$addr" --no-open
procd_set_param env FASTNET_CARD_SOCKET=/var/run/fastnet-card.sock FASTNET_CARD_STATE=/etc/fastnet/card-state.json
[ -n "$token" ] && procd_append_param command --token "$token" [ -n "$token" ] && procd_append_param command --token "$token"
[ "$logger" = 1 ] && procd_set_param stderr 1 [ "$logger" = 1 ] && procd_set_param stderr 1
procd_set_param respawn procd_set_param respawn
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
# Called by the owning plugin and its metadata migration hook.
set -e
root="${IPKG_INSTROOT:-}"
manifest="/usr/share/fastnet/fastnet-plugin.json"
legacy="${root}/usr/share/linkeasefull/desktop-apps.d/17-fastnet.json"
[ -f "${root}${manifest}" ] || exit 0
# Replace only the exact historical metadata payload; preserve custom entries.
if [ -f "${legacy}" ] && [ ! -L "${legacy}" ] && [ "$(sha256sum "${legacy}" | cut -d ' ' -f 1)" = "9ca279c3baca876bed3a4abe23d5edd69940fcaff4db17f27237e02c24cbabef" ]; then
rm -f "${legacy}"
fi
if [ ! -e "${legacy}" ] && [ ! -L "${legacy}" ]; then
mkdir -p "${legacy%/*}"
ln -s "${manifest}" "${legacy}"
fi
+16 -10
View File
@@ -12,7 +12,7 @@ PKG_ARCH_ISTOREENHANCE:=$(ARCH)
PKG_NAME:=istoreenhance PKG_NAME:=istoreenhance
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable # use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=0.9.0 PKG_SOURCE_DATE:=0.9.0
PKG_RELEASE:=16 PKG_RELEASE:=17
ARCH_HEXCODE:= ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
ARCH_HEXCODE=8664 ARCH_HEXCODE=8664
@@ -56,6 +56,13 @@ endef
define Package/$(PKG_NAME)/postinst define Package/$(PKG_NAME)/postinst
#!/bin/sh #!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/20-kspeeder.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/kspeeder/kspeeder-plugin.json "$${legacy}" || exit $$?
fi
if [ -z "$${IPKG_INSTROOT}" ]; then if [ -z "$${IPKG_INSTROOT}" ]; then
[ -f /etc/uci-defaults/istoreenhance ] && /etc/uci-defaults/istoreenhance && rm -f /etc/uci-defaults/istoreenhance [ -f /etc/uci-defaults/istoreenhance ] && /etc/uci-defaults/istoreenhance && rm -f /etc/uci-defaults/istoreenhance
exit 0 exit 0
@@ -64,14 +71,14 @@ endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/20-kspeeder.json 2>/dev/null)" = "/usr/share/kspeeder/kspeeder-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkeasefull/desktop-apps.d/20-kspeeder.json registration="$${root}$${directory}/20-kspeeder.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/kspeeder/kspeeder-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkease/apps.d/20-kspeeder.json 2>/dev/null)" = "/usr/share/kspeeder/kspeeder-plugin.json" ]; then done
rm -f /usr/share/linkease/apps.d/20-kspeeder.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -82,7 +89,7 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/usr/share/kspeeder/www $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/usr/share/kspeeder/www $(1)/usr/share/linkease/apps.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iStoreEnhance.$(PKG_ARCH_ISTOREENHANCE) $(1)/usr/sbin/iStoreEnhance $(INSTALL_BIN) $(PKG_BUILD_DIR)/iStoreEnhance.$(PKG_ARCH_ISTOREENHANCE) $(1)/usr/sbin/iStoreEnhance
$(INSTALL_CONF) ./files/istoreenhance.config $(1)/etc/config/istoreenhance $(INSTALL_CONF) ./files/istoreenhance.config $(1)/etc/config/istoreenhance
$(INSTALL_BIN) ./files/istoreenhance.init $(1)/etc/init.d/istoreenhance $(INSTALL_BIN) ./files/istoreenhance.init $(1)/etc/init.d/istoreenhance
@@ -92,7 +99,6 @@ define Package/$(PKG_NAME)/install
$(CP) $(KSPEEDER_WEB_ROOT)/* $(1)/usr/share/kspeeder/www/; \ $(CP) $(KSPEEDER_WEB_ROOT)/* $(1)/usr/share/kspeeder/www/; \
fi fi
$(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kspeeder/www/logo.png $(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
ln -sf /usr/share/kspeeder/kspeeder-plugin.json $(1)/usr/share/linkease/apps.d/20-kspeeder.json ln -sf /usr/share/kspeeder/kspeeder-plugin.json $(1)/usr/share/linkease/apps.d/20-kspeeder.json
endef endef
+21 -10
View File
@@ -11,7 +11,7 @@ PKG_ARCH_kai:=$(ARCH)
PKG_NAME:=kai PKG_NAME:=kai
PKG_VERSION:=0.0.28 PKG_VERSION:=0.0.28
PKG_RELEASE:=12 PKG_RELEASE:=13
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/kai-runtime-v$(PKG_VERSION)/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/kai-runtime-v$(PKG_VERSION)/
PKG_HASH:=skip PKG_HASH:=skip
@@ -39,16 +39,28 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/kai /etc/config/kai
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/05-kai-plugin.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/kai/kai-plugin.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkease/apps.d/05-kai-plugin.json 2>/dev/null)" = "/usr/share/kai/kai-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkease/apps.d/05-kai-plugin.json registration="$${root}$${directory}/05-kai-plugin.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/kai/kai-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/05-kai-plugin.json 2>/dev/null)" = "/usr/share/kai/kai-plugin.json" ]; then done
rm -f /usr/share/linkeasefull/desktop-apps.d/05-kai-plugin.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -59,7 +71,7 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec $(1)/etc/init.d $(1)/etc/config $(1)/usr/share/kai/www $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec $(1)/etc/init.d $(1)/etc/config $(1)/usr/share/kai/www $(1)/usr/share/linkease/apps.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/kai.$(PKG_ARCH_kai) $(1)/usr/sbin/kai_bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/kai.$(PKG_ARCH_kai) $(1)/usr/sbin/kai_bin
$(INSTALL_BIN) ./files/kai-session-launch $(1)/usr/libexec/kai-session-launch $(INSTALL_BIN) ./files/kai-session-launch $(1)/usr/libexec/kai-session-launch
$(INSTALL_BIN) ./files/kai.init $(1)/etc/init.d/kai $(INSTALL_BIN) ./files/kai.init $(1)/etc/init.d/kai
@@ -67,7 +79,6 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DATA) ./files/kai-plugin.json $(1)/usr/share/kai/kai-plugin.json $(INSTALL_DATA) ./files/kai-plugin.json $(1)/usr/share/kai/kai-plugin.json
$(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kai/www/logo.png $(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kai/www/logo.png
ln -sf /usr/share/kai/kai-plugin.json $(1)/usr/share/linkease/apps.d/05-kai-plugin.json ln -sf /usr/share/kai/kai-plugin.json $(1)/usr/share/linkease/apps.d/05-kai-plugin.json
ln -sf /usr/share/kai/kai-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/05-kai-plugin.json
endef endef
$(eval $(call BuildPackage,$(PKG_NAME))) $(eval $(call BuildPackage,$(PKG_NAME)))
+21 -11
View File
@@ -9,13 +9,12 @@ include $(TOPDIR)/rules.mk
KAIPLUS_ARCH_x86_64:=amd64 KAIPLUS_ARCH_x86_64:=amd64
KAIPLUS_ARCH_aarch64:=arm64 KAIPLUS_ARCH_aarch64:=arm64
KAIPLUS_ARCH:=$(KAIPLUS_ARCH_$(ARCH)) KAIPLUS_ARCH:=$(KAIPLUS_ARCH_$(ARCH))
KAIPLUS_HASH_x86_64:=945d1bcd7871426a10a77089512328e01e1db292f5dafbcf4e5c6b38f5a15cce KAIPLUS_HASH_x86_64:=945d1bcd7871426a10a77089512328e01e1db292f5dafbcf4e5c6b38f5a15cce
KAIPLUS_HASH_aarch64:=8ea9ce946e42f95b02f98749869d4990008d7221705beb51a9a90c00a1b00f83 KAIPLUS_HASH_aarch64:=8ea9ce946e42f95b02f98749869d4990008d7221705beb51a9a90c00a1b00f83
PKG_NAME:=kaiplus PKG_NAME:=kaiplus
PKG_VERSION:=1.0.11 PKG_VERSION:=1.0.11
PKG_RELEASE:=17 PKG_RELEASE:=18
KAIPLUS_URL_FILE:=kaiplus-linux-$(KAIPLUS_ARCH) KAIPLUS_URL_FILE:=kaiplus-linux-$(KAIPLUS_ARCH)
KAIPLUS_DOWNLOAD:=$(KAIPLUS_URL_FILE)-$(KAIPLUS_HASH_$(ARCH)) KAIPLUS_DOWNLOAD:=$(KAIPLUS_URL_FILE)-$(KAIPLUS_HASH_$(ARCH))
@@ -52,16 +51,28 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/kaiplus /etc/config/kaiplus
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/kaiplus/kaiplus-plugin.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then root="$${IPKG_INSTROOT:-}"
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json 2>/dev/null)" = "/usr/share/kaiplus/kaiplus-plugin.json" ]; then for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
rm -f /usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json registration="$${root}$${directory}/00-kaiplus-plugin.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/kaiplus/kaiplus-plugin.json" ]; then
rm -f "$${registration}"
fi fi
if [ "$$(readlink /usr/share/linkease/apps.d/00-kaiplus-plugin.json 2>/dev/null)" = "/usr/share/kaiplus/kaiplus-plugin.json" ]; then done
rm -f /usr/share/linkease/apps.d/00-kaiplus-plugin.json rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
fi
fi
exit 0 exit 0
endef endef
@@ -77,11 +88,10 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/kaiplus $(1)/usr/share/linkease/apps.d $(1)/usr/share/linkeasefull/desktop-apps.d $(1)/etc/init.d $(1)/etc/config $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/kaiplus $(1)/usr/share/linkease/apps.d $(1)/etc/init.d $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/kaiplus $(1)/usr/sbin/kaiplus $(INSTALL_BIN) $(PKG_BUILD_DIR)/kaiplus $(1)/usr/sbin/kaiplus
$(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kaiplus/logo.png $(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kaiplus/logo.png
$(INSTALL_DATA) ./files/kaiplus-plugin.json $(1)/usr/share/kaiplus/kaiplus-plugin.json $(INSTALL_DATA) ./files/kaiplus-plugin.json $(1)/usr/share/kaiplus/kaiplus-plugin.json
ln -sf /usr/share/kaiplus/kaiplus-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json
ln -sf /usr/share/kaiplus/kaiplus-plugin.json $(1)/usr/share/linkease/apps.d/00-kaiplus-plugin.json ln -sf /usr/share/kaiplus/kaiplus-plugin.json $(1)/usr/share/linkease/apps.d/00-kaiplus-plugin.json
$(INSTALL_BIN) ./files/kaiplus.init $(1)/etc/init.d/kaiplus $(INSTALL_BIN) ./files/kaiplus.init $(1)/etc/init.d/kaiplus
$(INSTALL_CONF) ./files/kaiplus.config $(1)/etc/config/kaiplus $(INSTALL_CONF) ./files/kaiplus.config $(1)/etc/config/kaiplus
+79
View File
@@ -0,0 +1,79 @@
#
# Copyright (C) 2006-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# Used by rrdtool only, no need to update it
include $(TOPDIR)/rules.mk
PKG_NAME:=libart
PKG_VERSION:=2.3.21
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)_lgpl-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=@GNOME/$(PKG_NAME)_lgpl/2.3
PKG_HASH:=skip
PKG_LICENSE:=LGPL-2.0-or-later
PKG_LICENSE_FILES:=COPYING
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)_lgpl-$(PKG_VERSION)
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/libart
SECTION:=libs
CATEGORY:=Libraries
TITLE:=An high-performance 2D graphics library
URL:=http://www.levien.com/libart/
endef
define Package/libart/description
A library of functions for 2D graphics supporting a superset of the
PostScript imaging model, designed to be integrated with graphics,
artwork, and illustration programs. It is written in optimized C, and
is fully compatible with C++. With a small footprint of 10,000 lines of
code, it is especially suitable for embedded applications.
endef
CONFIGURE_ARGS += \
--enable-shared \
--disable-static
TARGET_CFLAGS += $(FPIC)
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/bin $(2)/bin $(1)/usr/include $(1)/usr/lib/pkgconfig
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/bin/libart2-config \
$(1)/usr/bin/
$(SED) \
's,^\(prefix\|exec_prefix\)=.*,\1=$(STAGING_DIR)/usr,g' \
$(1)/usr/bin/libart2-config
$(LN) $(STAGING_DIR)/usr/bin/libart2-config $(2)/bin/
$(CP) \
$(PKG_INSTALL_DIR)/usr/include/libart-2.0 \
$(1)/usr/include/
$(CP) \
$(PKG_INSTALL_DIR)/usr/lib/libart_lgpl_2.so* \
$(1)/usr/lib/
$(INSTALL_DATA) \
$(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libart-2.0.pc \
$(1)/usr/lib/pkgconfig/
endef
define Package/libart/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libart_lgpl_2.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libart))
+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-cf-optimizer PKG_NAME:=luci-app-cf-optimizer
PKG_VERSION:=1.0.0 PKG_VERSION:=1.0.0
PKG_RELEASE:=1 PKG_RELEASE:=2
PKG_LICENSE:=Apache-2.0 PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Dante <dante@seckv.com> PKG_MAINTAINER:=Dante <dante@seckv.com>
@@ -21,12 +21,11 @@ start_service() {
procd_set_param respawn 3600 5 0 procd_set_param respawn 3600 5 0
procd_set_param stdout 1 procd_set_param stdout 1
procd_set_param stderr 1 procd_set_param stderr 1
procd_set_param pidfile /var/run/cf-optimizer/cf-optimizer.pid
procd_close_instance procd_close_instance
} }
stop_service() { stop_service() {
rm -f /var/run/cf-optimizer/cf-optimizer.pid :
} }
service_stopped() { service_stopped() {
@@ -39,10 +38,8 @@ service_stopped() {
} }
reload_service() { reload_service() {
"$PROG" sync-hosts >/dev/null 2>&1
stop stop
start start
"$PROG" run >/dev/null 2>&1 &
} }
service_triggers() { service_triggers() {
@@ -123,6 +123,7 @@ sync_hosts() {
mkdir -p "$(dirname "$HOSTS_FILE")" mkdir -p "$(dirname "$HOSTS_FILE")"
> "$hosts_tmp" > "$hosts_tmp"
echo "# Auto-generated by cf-optimizer sync on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp" echo "# Auto-generated by cf-optimizer sync on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp"
local d
for d in $domains; do for d in $domains; do
echo "$current_ip $d" >> "$hosts_tmp" echo "$current_ip $d" >> "$hosts_tmp"
done done
@@ -146,18 +147,19 @@ load_candidate_ips() {
if [ "$ip_source" = "custom" ] || [ "$ip_source" = "mixed" ]; then if [ "$ip_source" = "custom" ] || [ "$ip_source" = "mixed" ]; then
append_custom_ip() { append_custom_ip() {
local item="$1" local _item="$1"
[ -z "$item" ] && return local _base_prefix _host
[ -z "$_item" ] && return
# 若为 CIDR 简单网段 (如 /24),取前 3 个 IP # 若为 CIDR 简单网段 (如 /24),取前 3 个 IP
case "$item" in case "$_item" in
*/*) */*)
local base_prefix=$(echo "$item" | cut -d'/' -f1 | cut -d'.' -f1-3) _base_prefix=$(echo "$_item" | cut -d'/' -f1 | cut -d'.' -f1-3)
for host in 1 2 3; do for _host in 1 2 3; do
echo "$base_prefix.$host" >> "$out_file" echo "$_base_prefix.$_host" >> "$out_file"
done done
;; ;;
*) *)
echo "$item" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' >> "$out_file" echo "$_item" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' >> "$out_file"
;; ;;
esac esac
} }
@@ -225,14 +227,15 @@ run_optimization() {
local target_colos="" local target_colos=""
append_target_colo() { append_target_colo() {
local item="$1" local _item="$1"
[ -z "$item" ] && return local _colo _clean_colo
for c in $item; do [ -z "$_item" ] && return
local clean_c=$(echo "$c" | tr 'a-z' 'A-Z' | tr -d ' \t\r\n') for _colo in $_item; do
if [ -n "$clean_c" ]; then _clean_colo=$(echo "$_colo" | tr 'a-z' 'A-Z' | tr -d ' \t\r\n')
if [ -n "$_clean_colo" ]; then
case " $target_colos " in case " $target_colos " in
*" $clean_c "*) ;; *" $_clean_colo "*) ;;
*) target_colos="$target_colos $clean_c" ;; *) target_colos="$target_colos $_clean_colo" ;;
esac esac
fi fi
done done
@@ -246,22 +249,23 @@ run_optimization() {
fi fi
check_colo_allowed() { check_colo_allowed() {
local colo="$1" local _colo="$1"
[ -z "$colo" ] && return 0 [ -z "$_colo" ] && return 0
[ "$colo_filter_mode" = "none" ] && return 0 [ "$colo_filter_mode" = "none" ] && return 0
local match=0 local _match=0
for c in $target_colos; do local _tc
if [ "$c" = "$colo" ]; then for _tc in $target_colos; do
match=1 if [ "$_tc" = "$_colo" ]; then
_match=1
break break
fi fi
done done
if [ "$colo_filter_mode" = "exclude" ]; then if [ "$colo_filter_mode" = "exclude" ]; then
[ "$match" -eq 1 ] && return 1 || return 0 [ "$_match" -eq 1 ] && return 1 || return 0
elif [ "$colo_filter_mode" = "include" ]; then elif [ "$colo_filter_mode" = "include" ]; then
[ "$match" -eq 1 ] && return 0 || return 1 [ "$_match" -eq 1 ] && return 0 || return 1
fi fi
return 0 return 0
} }
@@ -339,6 +343,7 @@ run_optimization() {
# 阶段二:轮询交叉时序采样(跨越完整测试时段,精准捕获阶段性丢包与网络毛刺) # 阶段二:轮询交叉时序采样(跨越完整测试时段,精准捕获阶段性丢包与网络毛刺)
mkdir -p "$TMP_DIR/samples" mkdir -p "$TMP_DIR/samples"
local seq
for seq in $(seq 1 "$sample_count"); do for seq in $(seq 1 "$sample_count"); do
while read -r ip; do while read -r ip; do
[ -z "$ip" ] && continue [ -z "$ip" ] && continue
@@ -518,6 +523,7 @@ run_optimization() {
mkdir -p "$(dirname "$HOSTS_FILE")" mkdir -p "$(dirname "$HOSTS_FILE")"
> "$hosts_tmp" > "$hosts_tmp"
echo "# Auto-generated by cf-optimizer on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp" echo "# Auto-generated by cf-optimizer on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp"
local d
for d in $domains; do for d in $domains; do
echo "$final_ip $d" >> "$hosts_tmp" echo "$final_ip $d" >> "$hosts_tmp"
done done
@@ -609,6 +615,7 @@ apply_fast_failover() {
mkdir -p "$(dirname "$HOSTS_FILE")" mkdir -p "$(dirname "$HOSTS_FILE")"
> "$hosts_tmp" > "$hosts_tmp"
echo "# Auto-generated by cf-optimizer failover on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp" echo "# Auto-generated by cf-optimizer failover on $(date '+%Y-%m-%d %H:%M:%S')" >> "$hosts_tmp"
local d
for d in $domains; do for d in $domains; do
echo "$target_ip $d" >> "$hosts_tmp" echo "$target_ip $d" >> "$hosts_tmp"
done done
@@ -758,8 +765,9 @@ check_health_and_failover() {
} }
daemon_loop() { daemon_loop() {
mkdir -p "$RUN_DIR"
echo $$ > "$PID_FILE" echo $$ > "$PID_FILE"
trap 'rm -f "$PID_FILE"; exit 0' INT TERM EXIT trap 'rm -f "$PID_FILE"; [ -f "$RUN_DIR/task.lock/pid" ] && [ "$(cat "$RUN_DIR/task.lock/pid" 2>/dev/null)" = "$$" ] && rm -rf "$RUN_DIR/task.lock"; exit 0' INT TERM EXIT
log "守护进程启动 [PID: $$]" log "守护进程启动 [PID: $$]"
@@ -358,7 +358,7 @@ return view.extend({
o.titleref = L.url("admin", "system", "package-manager") o.titleref = L.url("admin", "system", "package-manager")
o.rawhtml = true; o.rawhtml = true;
o.title = '<b>' + _("DNS requests via TCP not supported") + '</b>'; o.title = '<b>' + _("DNS requests via TCP not supported") + '</b>';
o.cfgvalue = function() { return _("BusyBox's nslookup and hostip do not support TCP " + o.cfgvalue = function() { return _("BusyBox's nslookup does not support TCP " +
"instead of the default UDP when sending requests to the DNS server!") + "instead of the default UDP when sending requests to the DNS server!") +
"<br />- " + "<br />- " +
_("Install 'bind-host' or 'knot-host' or 'drill' package if you know you need TCP for DNS requests.")}; _("Install 'bind-host' or 'knot-host' or 'drill' package if you know you need TCP for DNS requests.")};
@@ -372,7 +372,7 @@ return view.extend({
o.cfgvalue = function() { return _("BusyBox's nslookup in the current compiled version " + o.cfgvalue = function() { return _("BusyBox's nslookup in the current compiled version " +
"does not handle given DNS Servers correctly!") + "does not handle given DNS Servers correctly!") +
"<br />- " + "<br />- " +
_("You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' package, " + _("You should install 'bind-host' or 'knot-host' or 'drill' package, " +
"if you need to specify a DNS server to detect your registered IP.")}; "if you need to specify a DNS server to detect your registered IP.")};
} }
+5 -5
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.2-1\n" "Project-Id-Version: luci-app-ddns 2.4.2-1\n"
"POT-Creation-Date: 2016-09-25 10:43+0200\n" "POT-Creation-Date: 2016-09-25 10:43+0200\n"
"PO-Revision-Date: 2026-09-08 12:39+0000\n" "PO-Revision-Date: 2026-11-04 16:54+0000\n"
"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" "Last-Translator: Dirk Brenken <dibdot@users.noreply.hosted.weblate.org>\n"
"Language-Team: German <https://hosted.weblate.org/projects/openwrt/" "Language-Team: German <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsddns/de/>\n" "luciapplicationsddns/de/>\n"
"Language: de\n" "Language: de\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.9.1\n" "X-Generator: Weblate 2026.11.1.dev0\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: .\n" "X-Poedit-Basepath: .\n"
@@ -393,7 +393,7 @@ msgstr "Service installieren"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:810 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:810
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:860 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:860
msgid "Interface" msgid "Interface"
msgstr "Interface" msgstr "Schnittstelle"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1005 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1005
msgid "Interval to force an update at the DDNS Provider" msgid "Interval to force an update at the DDNS Provider"
@@ -716,7 +716,7 @@ msgstr "Status-Verzeichnis"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:564 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:564
msgid "Stop" msgid "Stop"
msgstr "Stopp" msgstr "Stoppen"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201
msgid "Stop DDNS" msgid "Stop DDNS"
+64 -51
View File
@@ -2,8 +2,9 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.0-1\n" "Project-Id-Version: luci-app-ddns 2.4.0-1\n"
"POT-Creation-Date: 2016-01-30 11:07+0100\n" "POT-Creation-Date: 2016-01-30 11:07+0100\n"
"PO-Revision-Date: 2025-05-08 13:02+0000\n" "PO-Revision-Date: 2026-11-05 07:53+0000\n"
"Last-Translator: hmzs <hmzs@1szer1.hu>\n" "Last-Translator: Kövecses József <kovecses@users.noreply.hosted.weblate.org>"
"\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsddns/hu/>\n" "luciapplicationsddns/hu/>\n"
"Language: hu\n" "Language: hu\n"
@@ -11,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.12-dev\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423
msgid "\"../\" not allowed in path for Security Reason." msgid "\"../\" not allowed in path for Security Reason."
@@ -36,7 +37,7 @@ msgstr "Nem nyilvános IP-k engedélyezése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:604 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:604
msgid "Basic Settings" msgid "Basic Settings"
msgstr "Alapszintű beállítások" msgstr "Alapbeállítások"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:902 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:902
msgid "Bind Network" msgid "Bind Network"
@@ -52,7 +53,7 @@ msgid ""
"when sending requests to the DNS server!" "when sending requests to the DNS server!"
msgstr "" msgstr ""
"A BusyBox nslookup és hostip függvényei az alapértelmezett UDP helyett nem " "A BusyBox nslookup és hostip függvényei az alapértelmezett UDP helyett nem "
"támogatják a TCP-t, amikor kéréseket küldenek a DNS-kiszolgálónak!" "támogatják a TCP-t, amikor kéréseket küldenek a DNS-szervernek!"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:372 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:372
msgid "" msgid ""
@@ -60,17 +61,19 @@ msgid ""
"Servers correctly!" "Servers correctly!"
msgstr "" msgstr ""
"A BusyBox nslookup függvénye az aktuális verzióban nem kezeli helyesen a " "A BusyBox nslookup függvénye az aktuális verzióban nem kezeli helyesen a "
"megadott DNS-kiszolgálókat!" "megadott DNS-szervereket!"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:443 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:443
msgid "CA cert bundle file" msgid "CA cert bundle file"
msgstr "" msgstr "CA-tanúsítványcsomag fájlja"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:444 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:444
msgid "" msgid ""
"CA certificate bundle file that will be used to download services data. Set " "CA certificate bundle file that will be used to download services data. Set "
"IGNORE to skip certificate validation." "IGNORE to skip certificate validation."
msgstr "" msgstr ""
"A szolgáltatásadatok letöltéséhez használt CA-tanúsítványcsomag fájlja. A "
"tanúsítvány-ellenőrzés kihagyásához adja meg az IGNORE értéket."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:532 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:532
msgid "Cancel" msgid "Cancel"
@@ -86,7 +89,7 @@ msgstr "Ellenőrzés mértékegysége"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:27 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:27
msgid "Configuration" msgid "Configuration"
msgstr "Beállítás" msgstr "Beállítások"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:226 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:226
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1133 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1133
@@ -115,8 +118,8 @@ msgstr "Jelenlegi beállítás:"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:276 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:276
msgid "Currently DDNS updates are not started at boot or on interface events." msgid "Currently DDNS updates are not started at boot or on interface events."
msgstr "" msgstr ""
"Jelenleg a DDNS frissítések nincsenek elindítva a rendszerindításkor vagy a " "Jelenleg a DDNS frissítések nincsenek elindítva a rendszerindításkor vagy az "
"csatolóeseményeknél." "interfészeseményeknél."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:725 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:725
msgid "Custom update script for updating your DDNS Provider." msgid "Custom update script for updating your DDNS Provider."
@@ -133,7 +136,7 @@ msgstr "Egyéni frissítő parancsfájl"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:284 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:284
msgid "DDNS" msgid "DDNS"
msgstr "" msgstr "DDNS"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:207 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:207
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:279 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:279
@@ -160,7 +163,7 @@ msgstr "a TCP-n keresztüli DNS-kérések nem támogatottak"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:923 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:923
msgid "DNS-Server" msgid "DNS-Server"
msgstr "DNS-kiszolgáló" msgstr "DNS-szerver"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:401 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:401
msgid "Date format" msgid "Date format"
@@ -174,7 +177,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:861 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:861
msgid "Defines the interface to read systems IP-Address from" msgid "Defines the interface to read systems IP-Address from"
msgstr "" msgstr ""
"Meghatározza azt a csatolót, amelyből a rendszerek IP-címeit olvasni kell" "Meghatározza azt az interfészt, amelyből a rendszerek IP-címeit olvasni kell"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:843 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:843
msgid "Defines the network to read systems IP-Address from" msgid "Defines the network to read systems IP-Address from"
@@ -218,7 +221,7 @@ msgstr "Hiba"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1039 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1039
msgid "Error Max Retry Counter" msgid "Error Max Retry Counter"
msgstr "" msgstr "Hiba esetén az újrapróbálkozások legnagyobb száma"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1049 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1049
msgid "Error Retry Interval" msgid "Error Retry Interval"
@@ -243,7 +246,7 @@ msgstr "Fájl"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:709 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:709
msgid "Follow instructions found on their WEB page." msgid "Follow instructions found on their WEB page."
msgstr "" msgstr "Kövesse a webhelyükön található utasításokat."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:403 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:403
msgid "For supported codes look here" msgid "For supported codes look here"
@@ -263,7 +266,7 @@ msgstr "TCP kényszerítése a DNS-en"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1030 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1030
msgid "Force Unit" msgid "Force Unit"
msgstr "" msgstr "Kényszerítés mértékegysége"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:947 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:947
msgid "Format" msgid "Format"
@@ -279,11 +282,11 @@ msgid ""
"interface." "interface."
msgstr "" msgstr ""
"A GNU Wget az adott hálózat IP-jét fogja használni, a cURL a fizikai " "A GNU Wget az adott hálózat IP-jét fogja használni, a cURL a fizikai "
"csatolót fogja használni." "interfészt fogja használni."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:265 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:265
msgid "Global Settings" msgid "Global Settings"
msgstr "" msgstr "Globális beállítások"
#: applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json:3 #: applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json:3
msgid "Grant access to ddns procedures" msgid "Grant access to ddns procedures"
@@ -345,7 +348,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:384 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:384
msgid "If using secure communication you should verify server certificates!" msgid "If using secure communication you should verify server certificates!"
msgstr "" msgstr ""
"Biztonságos kommunikáció használatakor ellenőriznie kell a kiszolgáló " "Biztonságos kommunikáció használatakor ellenőriznie kell a szerver "
"tanúsítványait!" "tanúsítványait!"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:325 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:325
@@ -359,7 +362,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:962 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:962
msgid "Info" msgid "Info"
msgstr "Infó" msgstr "Információ"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:264 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:264
msgid "Information" msgid "Information"
@@ -378,15 +381,17 @@ msgid ""
"Install 'ca-certificates' package or needed certificates by hand into /etc/" "Install 'ca-certificates' package or needed certificates by hand into /etc/"
"ssl/certs default directory" "ssl/certs default directory"
msgstr "" msgstr ""
"Telepítse a 'ca-certificates' csomagot, vagy másolja kézzel a szükséges "
"tanúsítványokat az alapértelmezett /etc/ssl/certs könyvtárba"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:668 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:668
msgid "Install Service" msgid "Install Service"
msgstr "" msgstr "Szolgáltatás telepítése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:810 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:810
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:860 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:860
msgid "Interface" msgid "Interface"
msgstr "Csatoló" msgstr "Interfész"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1005 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1005
msgid "Interval to force an update at the DDNS Provider" msgid "Interval to force an update at the DDNS Provider"
@@ -424,7 +429,7 @@ msgstr "Naplózás fájlba"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:956 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:956
msgid "Log to syslog" msgid "Log to syslog"
msgstr "Naplózás a rendszernaplóba" msgstr "Naplózás a rendszernaplóba (syslog)"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:619 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:619
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1129 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1129
@@ -434,7 +439,7 @@ msgstr "Gépnév keresése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:805 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:805
msgid "Method used to determine the system IP-Address to send in updates" msgid "Method used to determine the system IP-Address to send in updates"
msgstr "" msgstr "A frissítésekben küldendő rendszer-IP-cím meghatározásának módja"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:491 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:491
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1123 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1123
@@ -454,12 +459,12 @@ msgid ""
"Neither GNU Wget with SSL nor cURL is installed to support secure updates " "Neither GNU Wget with SSL nor cURL is installed to support secure updates "
"via HTTPS protocol." "via HTTPS protocol."
msgstr "" msgstr ""
"Sem az SSL-lel rendelkező GNU Wget, sem a cURL nincs telepítve a HTTPS " "Sem az SSL-lel rendelkező GNU Wget, sem a cURL nincs telepítve a HTTPS-"
"protokollon keresztüli biztonságos frissítések támogatásához." "protokollon keresztüli biztonságos frissítések támogatásához."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:613 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:613
msgid "Neither from LuCI interface nor from console." msgid "Neither from LuCI interface nor from console."
msgstr "" msgstr "Sem a LuCI felületéről, sem a konzolról."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:808 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:808
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:842 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:842
@@ -480,7 +485,7 @@ msgstr "Soha"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:494 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:494
msgid "New DDns Service…" msgid "New DDns Service…"
msgstr "Új DDNS szolgáltatás…" msgstr "Új DDNS-szolgáltatás…"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1144 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1144
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:28 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:28
@@ -489,7 +494,7 @@ msgstr "Következő frissítés"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1144 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1144
msgid "Next Verify" msgid "Next Verify"
msgstr "" msgstr "Következő ellenőrzés"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:227 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:227
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1134 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1134
@@ -540,18 +545,20 @@ msgstr "ELHAGYHATÓ: a kommunikációhoz használandó hálózat"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:945 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:945
msgid "OPTIONAL: Proxy-Server for detection and updates." msgid "OPTIONAL: Proxy-Server for detection and updates."
msgstr "ELHAGYHATÓ: proxy-kiszolgáló a felismeréshez és a frissítésekhez." msgstr "ELHAGYHATÓ: proxy-szerver a felismeréshez és a frissítésekhez."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:924 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:924
msgid "OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'." msgid "OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'."
msgstr "" msgstr ""
"ELHAGYHATÓ: nem alapértelmezett DNS-kiszolgáló használata a „Regisztrált IP” " "ELHAGYHATÓ: nem alapértelmezett DNS-szerver használata a „Regisztrált IP” "
"felismeréséhez." "felismeréséhez."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1040 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1040
msgid "" msgid ""
"On Error the script will stop execution after the given number of retries." "On Error the script will stop execution after the given number of retries."
msgstr "" msgstr ""
"Hiba esetén a parancsfájl a megadott számú újrapróbálkozás után leállítja a "
"végrehajtást."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:767 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:767
msgid "Optional Encoded Parameter" msgid "Optional Encoded Parameter"
@@ -575,7 +582,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:944 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:944
msgid "PROXY-Server" msgid "PROXY-Server"
msgstr "Proxy-kiszolgáló" msgstr "Proxy-szerver"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:758 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:758
msgid "Password" msgid "Password"
@@ -599,7 +606,7 @@ msgstr "Nyomja meg a [Beolvasás] gombot"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:717 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:717
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:739 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:739
msgid "Provide either an Update Script OR an Update URL" msgid "Provide either an Update Script OR an Update URL"
msgstr "" msgstr "Adjon meg vagy egy frissítő parancsfájlt, VAGY egy frissítési URL-t"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1068 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1068
msgid "Read / Reread log file" msgid "Read / Reread log file"
@@ -607,7 +614,7 @@ msgstr "Naplófájl olvasása vagy újraolvasása"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:691 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:691
msgid "Really switch service?" msgid "Really switch service?"
msgstr "" msgstr "Biztosan vált szolgáltatást?"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1129 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1129
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:30 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/status/include/70_ddns.js:30
@@ -624,7 +631,7 @@ msgstr "A szolgáltatás újratöltése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:747 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:747
msgid "Replaces [DOMAIN] in Update-URL (URL-encoded)" msgid "Replaces [DOMAIN] in Update-URL (URL-encoded)"
msgstr "" msgstr "Lecseréli a [DOMAIN] értéket a frissítési URL-ben (URL-kódoltan)"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:759 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:759
msgid "Replaces [PASSWORD] in Update-URL (URL-encoded)" msgid "Replaces [PASSWORD] in Update-URL (URL-encoded)"
@@ -641,7 +648,7 @@ msgstr "DDns újraindítása"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1057 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1057
msgid "Retry Unit" msgid "Retry Unit"
msgstr "" msgstr "Újrapróbálkozás mértékegysége"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:17 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:17
msgid "Run once" msgid "Run once"
@@ -655,23 +662,23 @@ msgstr "Fut"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:811 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:811
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:868 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:868
msgid "Script" msgid "Script"
msgstr "Parancsfájl" msgstr "Szkript"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:517 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:517
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:655 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:655
msgid "Select a service" msgid "Select a service"
msgstr "" msgstr "Válasszon szolgáltatást"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:518 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:518
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:657 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:657
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:677 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:677
msgid "Service doesn't support this IP type" msgid "Service doesn't support this IP type"
msgstr "" msgstr "A szolgáltatás nem támogatja ezt az IP-típust"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:656 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:656
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:667 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:667
msgid "Service not installed" msgid "Service not installed"
msgstr "" msgstr "A szolgáltatás nincs telepítve"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:455 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:455
msgid "Services" msgid "Services"
@@ -679,21 +686,23 @@ msgstr "Szolgáltatások"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:450 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:450
msgid "Services URL Download" msgid "Services URL Download"
msgstr "" msgstr "Szolgáltatáslista letöltési URL-je"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:294 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:294
msgid "Services list last update" msgid "Services list last update"
msgstr "" msgstr "A szolgáltatáslista utolsó frissítése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1007 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1007
msgid "Setting this parameter to 0 will force the script to only run once" msgid "Setting this parameter to 0 will force the script to only run once"
msgstr "" msgstr "Ha ezt a paramétert 0-ra állítja, a parancsfájl csak egyszer fut le"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:451 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:451
msgid "" msgid ""
"Source URL for services file. Defaults to the master openwrt ddns package " "Source URL for services file. Defaults to the master openwrt ddns package "
"repo." "repo."
msgstr "" msgstr ""
"A szolgáltatásfájl forrás-URL-je. Alapértelmezés szerint az openwrt ddns "
"csomag fő tárolója."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201
msgid "Start DDNS" msgid "Start DDNS"
@@ -713,7 +722,7 @@ msgstr "Állapotkönyvtár"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:564 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:564
msgid "Stop" msgid "Stop"
msgstr "Megállítás" msgstr "Leállítás"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:201
msgid "Stop DDNS" msgid "Stop DDNS"
@@ -725,11 +734,11 @@ msgstr "A szolgáltatás leállítása"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:19 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:19
msgid "Stopped" msgid "Stopped"
msgstr "Megállítva" msgstr "Leállítva"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:692 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:692
msgid "Switch service" msgid "Switch service"
msgstr "" msgstr "Szolgáltatás váltása"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1042 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1042
msgid "The default setting of '0' will retry infinitely." msgid "The default setting of '0' will retry infinitely."
@@ -754,10 +763,12 @@ msgid ""
"This is only a problem with multiple WAN interfaces and your DDNS provider " "This is only a problem with multiple WAN interfaces and your DDNS provider "
"is unreachable via one of them." "is unreachable via one of them."
msgstr "" msgstr ""
"Ez csak akkor jelent problémát, ha több WAN-interfész van, és a DDNS-"
"szolgáltató valamelyiken keresztül nem érhető el."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1084 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1084
msgid "This is the current content of the log file in %h for this service." msgid "This is the current content of the log file in %h for this service."
msgstr "" msgstr "Ez a szolgáltatás naplófájljának (%h) jelenlegi tartalma."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:210 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:210
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:277 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:277
@@ -770,7 +781,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:892 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:892
msgid "This will be autoset to the selected interface" msgid "This will be autoset to the selected interface"
msgstr "Ez automatikusan be lesz állítva a kiválasztott csatolóhoz" msgstr "Ez automatikusan be lesz állítva a kiválasztott interfészhez"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:606 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:606
msgid "Timer Settings" msgid "Timer Settings"
@@ -794,11 +805,11 @@ msgstr "Ismeretlen"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:301 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:301
msgid "Update DDns Services List" msgid "Update DDns Services List"
msgstr "" msgstr "DDns-szolgáltatáslista frissítése"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:682 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:682
msgid "Update URL" msgid "Update URL"
msgstr "" msgstr "Frissítési URL"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:707 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:707
msgid "Update URL for updating your DDNS Provider." msgid "Update URL for updating your DDNS Provider."
@@ -824,7 +835,7 @@ msgstr "Felhasználónév"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:371 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:371
msgid "Using specific DNS Server not supported" msgid "Using specific DNS Server not supported"
msgstr "Bizonyos DNS-kiszolgáló használata nem támogatott" msgstr "Bizonyos DNS-szerver használata nem támogatott"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:989 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:989
msgid "Values below 5 minutes == 300 seconds are not supported" msgid "Values below 5 minutes == 300 seconds are not supported"
@@ -876,6 +887,8 @@ msgid ""
"You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' " "You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' "
"package, if you need to specify a DNS server to detect your registered IP." "package, if you need to specify a DNS server to detect your registered IP."
msgstr "" msgstr ""
"Ha DNS-szervert kell megadnia a regisztrált IP-cím észleléséhez, telepítse a "
"'bind-host', 'knot-host', 'drill' vagy 'hostip' csomagot."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:323 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:323
msgid "" msgid ""
@@ -945,7 +958,7 @@ msgstr "másodperc"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:791 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:791
msgid "to run HTTPS without verification of server certificates (insecure)" msgid "to run HTTPS without verification of server certificates (insecure)"
msgstr "" msgstr ""
"HTTPS futtatásához a kiszolgáló tanúsítványainak ellenőrzése nélkül (nem " "HTTPS futtatásához a szerver tanúsítványainak ellenőrzése nélkül (nem "
"biztonságos)" "biztonságos)"
#~ msgid "DDns" #~ msgid "DDns"
+8 -6
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.0-1\n" "Project-Id-Version: luci-app-ddns 2.4.0-1\n"
"POT-Creation-Date: 2016-01-30 11:07+0100\n" "POT-Creation-Date: 2016-01-30 11:07+0100\n"
"PO-Revision-Date: 2026-05-26 15:21+0000\n" "PO-Revision-Date: 2026-11-05 21:33+0000\n"
"Last-Translator: Stefano Mora <iegghilba@gmail.com>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Italian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsddns/it/>\n" "luciapplicationsddns/it/>\n"
"Language: it\n" "Language: it\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.6.dev0\n" "X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423
msgid "\"../\" not allowed in path for Security Reason." msgid "\"../\" not allowed in path for Security Reason."
@@ -28,7 +28,7 @@ msgstr "Aggiungi un nuovo servizio..."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:605 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:605
msgid "Advanced Settings" msgid "Advanced Settings"
msgstr "Impostazioni Avanzate" msgstr "Impostazioni avanzate"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:392 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:392
msgid "Allow non-public IPs" msgid "Allow non-public IPs"
@@ -469,7 +469,7 @@ msgstr "Rete"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:887 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:887
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:905 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:905
msgid "Network on which the ddns-updater scripts will be started" msgid "Network on which the ddns-updater scripts will be started"
msgstr "Rete su cui lo script di aggiornamento DDNS sara avviato" msgstr "Rete su cui lo script di aggiornamento DDNS sarà avviato"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:228 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:228
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1148 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1148
@@ -749,6 +749,8 @@ msgid ""
"This is only a problem with multiple WAN interfaces and your DDNS provider " "This is only a problem with multiple WAN interfaces and your DDNS provider "
"is unreachable via one of them." "is unreachable via one of them."
msgstr "" msgstr ""
"Questo è un problema solo con interfacce WAN multiple e il tuo fornitore "
"DDNS è irraggiungibile tramite una di esse."
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1084 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1084
msgid "This is the current content of the log file in %h for this service." msgid "This is the current content of the log file in %h for this service."
@@ -794,7 +796,7 @@ msgstr "Aggiorna l'elenco dei servizi DDNS"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:682 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:682
msgid "Update URL" msgid "Update URL"
msgstr "" msgstr "URL di aggiornamento"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:707 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:707
msgid "Update URL for updating your DDNS Provider." msgid "Update URL for updating your DDNS Provider."
+2 -2
View File
@@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.0-1\n" "Project-Id-Version: luci-app-ddns 2.4.0-1\n"
"POT-Creation-Date: 2016-01-30 11:07+0100\n" "POT-Creation-Date: 2016-01-30 11:07+0100\n"
"PO-Revision-Date: 2026-10-18 16:40+0000\n" "PO-Revision-Date: 2026-10-22 07:52+0000\n"
"Last-Translator: Monarch <monarch.scrap-0p@users.noreply.hosted.weblate.org>" "Last-Translator: Monarch <monarch.scrap-0p@users.noreply.hosted.weblate.org>"
"\n" "\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Japanese <https://hosted.weblate.org/projects/openwrt/"
@@ -37,7 +37,7 @@ msgstr "非パブリック IP を許可"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:604 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:604
msgid "Basic Settings" msgid "Basic Settings"
msgstr "基本設定" msgstr "一般設定"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:902 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:902
msgid "Bind Network" msgid "Bind Network"
+2 -2
View File
@@ -1,6 +1,6 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-18 18:18+0000\n" "PO-Revision-Date: 2026-10-20 02:18+0000\n"
"Last-Translator: Hyeonjeong Lee <hayden@users.noreply.hosted.weblate.org>\n" "Last-Translator: Hyeonjeong Lee <hayden@users.noreply.hosted.weblate.org>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Korean <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsddns/ko/>\n" "luciapplicationsddns/ko/>\n"
@@ -745,7 +745,7 @@ msgid ""
"force_interval set to '0')" "force_interval set to '0')"
msgstr "" msgstr ""
"이는 DDNS 스크립트를 별도로 실행하는 경우의 기본값입니다. (예: " "이는 DDNS 스크립트를 별도로 실행하는 경우의 기본값입니다. (예: "
"force_interval을 '0'으로 설정한 cron을 통해)" "force_interval을 '0'으로 설정한 상태로 cron을 통해)"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:892 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:892
msgid "This will be autoset to the selected interface" msgid "This will be autoset to the selected interface"
+5 -5
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.0-1\n" "Project-Id-Version: luci-app-ddns 2.4.0-1\n"
"POT-Creation-Date: 2016-01-30 11:07+0100\n" "POT-Creation-Date: 2016-01-30 11:07+0100\n"
"PO-Revision-Date: 2026-09-29 13:09+0000\n" "PO-Revision-Date: 2026-11-01 06:11+0000\n"
"Last-Translator: Pavel Borecki <pavel.borecki@gmail.com>\n" "Last-Translator: LucasMZ <git@lucasmz.dev>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"openwrt/luciapplicationsddns/pt_BR/>\n" "openwrt/luciapplicationsddns/pt_BR/>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 2026.10.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423
msgid "\"../\" not allowed in path for Security Reason." msgid "\"../\" not allowed in path for Security Reason."
@@ -356,7 +356,7 @@ msgstr ""
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:962 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:962
msgid "Info" msgid "Info"
msgstr "Informação (Info)" msgstr "Informações"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:264 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:264
msgid "Information" msgid "Information"
@@ -699,7 +699,7 @@ msgstr "Estado"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1116 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1116
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Estado"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:410 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:410
msgid "Status directory" msgid "Status directory"
+5 -5
View File
@@ -2,8 +2,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: luci-app-ddns 2.4.0-1\n" "Project-Id-Version: luci-app-ddns 2.4.0-1\n"
"POT-Creation-Date: 2016-01-30 11:07+0100\n" "POT-Creation-Date: 2016-01-30 11:07+0100\n"
"PO-Revision-Date: 2026-03-18 02:23+0000\n" "PO-Revision-Date: 2026-11-04 21:31+0000\n"
"Last-Translator: CRISTIAN ANDREI <cristianvdr@gmail.com>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Romanian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsddns/ro/>\n" "luciapplicationsddns/ro/>\n"
"Language: ro\n" "Language: ro\n"
@@ -12,7 +12,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n" "20)) ? 1 : 2;\n"
"X-Generator: Weblate 5.17-dev\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:423
msgid "\"../\" not allowed in path for Security Reason." msgid "\"../\" not allowed in path for Security Reason."
@@ -617,7 +617,7 @@ msgstr "IP înregistrat"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:565 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:565
msgid "Reload" msgid "Reload"
msgstr "Reîncărcați" msgstr "Reîncărcare"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:550 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:550
msgid "Reload this service" msgid "Reload this service"
@@ -709,7 +709,7 @@ msgstr "Stat"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1116 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:1116
msgid "Status" msgid "Status"
msgstr "Stare" msgstr "Status"
#: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:410 #: applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js:410
msgid "Status directory" msgid "Status directory"
+18 -11
View File
@@ -2,7 +2,7 @@
'use strict'; 'use strict';
import { readfile, popen, stat, glob } from 'fs'; import { readfile, writefile, mkdir, popen, stat, glob } from 'fs';
import { init_enabled } from 'luci.sys'; import { init_enabled } from 'luci.sys';
import { isnan } from 'math'; import { isnan } from 'math';
import { cursor } from 'uci'; import { cursor } from 'uci';
@@ -115,8 +115,12 @@ const methods = {
if (section == '.anonymous') if (section == '.anonymous')
return; return;
if (stat(`${rundir}/${section}.ip`)?.type == 'file') { // ddns-scripts runs a service only if it is enabled; it is disabled by default
ip = readfile(`${rundir}/${section}.ip`); const enabled = s['enabled'] in [ '1', 'on', 'true', 'yes', 'enabled' ];
const ipFile = `${rundir}/${section}.ip`;
if (stat(ipFile)?.type == 'file') {
ip = readfile(ipFile);
} else { } else {
const dnsServer = s['dns_server'] || ''; const dnsServer = s['dns_server'] || '';
const forceIpVersion = int(s['force_ipversion'] || 0); const forceIpVersion = int(s['force_ipversion'] || 0);
@@ -136,7 +140,14 @@ const methods = {
if (length(dnsServer) > 0) push(command, '-d', shellquote(dnsServer)); if (length(dnsServer) > 0) push(command, '-d', shellquote(dnsServer));
push(command, '-- get_registered_ip'); push(command, '-- get_registered_ip');
const result = system(`${join(' ', command)}`); /* Without a working DNS the lookup takes 10 s or more, and LuCI fetches
this status together with the rest of a page such as the Overview. So the
lookup runs in the background, and the helper writes its result to the IP
file for a later call. The file is created empty first, so that the calls
in between do not start the lookup again. */
mkdir(rundir);
writefile(ipFile, '');
system(`${join(' ', command)} >/dev/null 2>&1 &`);
} }
lastUpdate = int(readfile(`${rundir}/${section}.update`) || 0); lastUpdate = int(readfile(`${rundir}/${section}.update`) || 0);
@@ -178,9 +189,9 @@ const methods = {
nextUpdate = 'Verify'; nextUpdate = 'Verify';
} else if (forcedUpdateInterval === 0) { } else if (forcedUpdateInterval === 0) {
nextUpdate = 'Run once'; nextUpdate = 'Run once';
} else if (pid == 0 && s['enabled'] == '0') { } else if (pid == 0 && !enabled) {
nextUpdate = 'Disabled'; nextUpdate = 'Disabled';
} else if (pid == 0 && s['enabled'] != '0') { } else if (pid == 0) {
nextUpdate = 'Stopped'; nextUpdate = 'Stopped';
} }
@@ -287,15 +298,11 @@ const methods = {
res['has_bindhost'] = cache['has_bindhost'] || hasBindHost(); res['has_bindhost'] = cache['has_bindhost'] || hasBindHost();
const hasHostIp = () => {
return hasCommand('hostip');
};
const hasNslookup = () => { const hasNslookup = () => {
return hasCommand('nslookup'); return hasCommand('nslookup');
}; };
res['has_dnsserver'] = cache['has_bindhost'] || hasNslookup() || hasHostIp() || hasBindHost(); res['has_dnsserver'] = cache['has_bindhost'] || hasNslookup() || hasBindHost();
const checkCerts = () => { const checkCerts = () => {
let present = false; let present = false;
+32 -2
View File
@@ -8,8 +8,38 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for ddnsto LUCI_TITLE:=LuCI support for ddnsto
LUCI_DEPENDS:=+ddnsto +block-mount LUCI_DEPENDS:=+ddnsto +block-mount
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
PKG_VERSION:=4.2.2-r1 PKG_VERSION:=4.2.2-r3
PKG_RELEASE:=3 PKG_RELEASE:=4
define Package/luci-app-ddnsto/postinst
#!/bin/sh
# Maintain the old desktop entry without a second manifest or file owner.
root="$${IPKG_INSTROOT:-}"
sh "$${root}/usr/share/ddnsto/register-desktop.sh" || exit $$?
icon="$${root}/usr/share/linkeasefull/app-meta/ddnsto/logo.png"
if [ "$$(readlink "$${icon}" 2>/dev/null)" = "/www/luci-static/resources/app-icons/ddnsto.png" ]; then
rm -f "$${icon}"
fi
rmdir "$${root}/usr/share/linkeasefull/app-meta/ddnsto" "$${root}/usr/share/linkeasefull/app-meta" 2>/dev/null || true
if [ -z "$${IPKG_INSTROOT}" ]; then
rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
rm -rf /tmp/luci-modulecache/
fi
exit 0
endef
define Package/luci-app-ddnsto/prerm
#!/bin/sh
root="$${IPKG_INSTROOT:-}"
for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
registration="$${root}$${directory}/16-ddnsto.json"
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/ddnsto/ddnsto-plugin.json" ]; then
rm -f "$${registration}"
fi
done
rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
@@ -0,0 +1,46 @@
{
"schemaVersion": 1,
"id": "ddnsto",
"name": "DDNSTO",
"icon": "logo.png",
"staticRoot": "/usr/share/ddnsto/www",
"desktop": {
"mode": "builtin",
"component": "LuciContainer",
"props": {
"initialPath": "/cgi-bin/luci/admin/services/ddnsto",
"contentOnly": true,
"isolation": "scoped-dom-css",
"mountIds": [
"root",
"app"
],
"hideChrome": true,
"preloadScripts": [
"/luci-static/linkeasefull-embed/embed-prelude.js"
],
"preloadStyles": [
"/luci-static/linkeasefull-embed/embed.css"
]
}
},
"standalone": {
"url": "/cgi-bin/luci/admin/services/ddnsto"
},
"window": {
"width": 980,
"height": 700,
"singleton": true
},
"capabilities": [
"ddnsto",
"openwrt",
"luci",
"network"
],
"categories": [
"network",
"service",
"openwrt"
]
}
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
# Called by the owning plugin and its metadata migration hook.
set -e
root="${IPKG_INSTROOT:-}"
manifest="/usr/share/ddnsto/ddnsto-plugin.json"
legacy="${root}/usr/share/linkeasefull/desktop-apps.d/16-ddnsto.json"
[ -f "${root}${manifest}" ] || exit 0
# Replace only the exact historical metadata payload; preserve custom entries.
if [ -f "${legacy}" ] && [ ! -L "${legacy}" ] && [ "$(sha256sum "${legacy}" | cut -d ' ' -f 1)" = "a72a8b3e529c91b2a3bc32ef695e5f7dc2935e332fcbd3201f985e05c2c8763d" ]; then
rm -f "${legacy}"
fi
if [ ! -e "${legacy}" ] && [ ! -L "${legacy}" ]; then
mkdir -p "${legacy%/*}"
ln -s "${manifest}" "${legacy}"
fi
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1 @@
/usr/share/ddnsto/ddnsto-plugin.json
+4 -4
View File
@@ -1,14 +1,14 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-09-28 18:23+0000\n" "PO-Revision-Date: 2026-11-04 21:09+0000\n"
"Last-Translator: Pavel Borecki <pavel.borecki@gmail.com>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Czech <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/cs/>\n" "luciapplicationsdockerman/cs/>\n"
"Language: cs\n" "Language: cs\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n" "Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n"
"X-Generator: Weblate 2026.10.dev0\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -2083,7 +2083,7 @@ msgstr "Varování"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1078 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1078
msgid "WebSocket" msgid "WebSocket"
msgstr "" msgstr "WebSocket"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1087 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1087
msgid "WebSocket Console" msgid "WebSocket Console"
+4 -4
View File
@@ -1,14 +1,14 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-09-24 06:06+0000\n" "PO-Revision-Date: 2026-11-04 16:54+0000\n"
"Last-Translator: Pavel Borecki <pavel.borecki@gmail.com>\n" "Last-Translator: Dirk Brenken <dibdot@users.noreply.hosted.weblate.org>\n"
"Language-Team: German <https://hosted.weblate.org/projects/openwrt/" "Language-Team: German <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/de/>\n" "luciapplicationsdockerman/de/>\n"
"Language: de\n" "Language: de\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.10.dev0\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -1793,7 +1793,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:372 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:372
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1804 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1804
msgid "Stop" msgid "Stop"
msgstr "Stopp" msgstr "Stoppen"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:155 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:155
msgctxt "daemon stop action" msgctxt "daemon stop action"
+16 -16
View File
@@ -1,14 +1,14 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-13 21:56+0000\n" "PO-Revision-Date: 2026-11-06 10:18+0000\n"
"Last-Translator: Pavel Borecki <pavelbo@users.noreply.hosted.weblate.org>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: French <https://hosted.weblate.org/projects/openwrt/" "Language-Team: French <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/fr/>\n" "luciapplicationsdockerman/fr/>\n"
"Language: fr\n" "Language: fr\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 2026.11.dev0\n" "X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -32,7 +32,7 @@ msgstr "Une liste de capacités kernel a ajouter au conteneur"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Action" msgid "Action"
msgstr "" msgstr "Action"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825
msgid "Action unavailable:" msgid "Action unavailable:"
@@ -44,7 +44,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:582 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:582
msgid "Add" msgid "Add"
msgstr "Add" msgstr "Ajouter"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:315 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:315
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:620 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:620
@@ -61,7 +61,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634
msgid "Advanced" msgid "Advanced"
msgstr "" msgstr "Avancé"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590
msgid "Aliases" msgid "Aliases"
@@ -250,7 +250,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1189 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1189
msgid "Clear" msgid "Clear"
msgstr "" msgstr "Nettoyer"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:617 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:617
msgid "Click to add a new tag to this image" msgid "Click to add a new tag to this image"
@@ -437,7 +437,7 @@ msgstr "Aperçu des conteneurs"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:421 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:421
msgid "Create" msgid "Create"
msgstr "" msgstr "Créer"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:979 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:979
msgid "Create container" msgid "Create container"
@@ -1290,7 +1290,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249
msgid "No" msgid "No"
msgstr "" msgstr "Non"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878
msgid "No additional networks available to connect" msgid "No additional networks available to connect"
@@ -1418,7 +1418,7 @@ msgstr "Réseau overlay"
#: applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json:19 #: applications/luci-app-dockerman/root/usr/share/luci/menu.d/luci-app-dockerman.json:19
msgid "Overview" msgid "Overview"
msgstr "Aperçu" msgstr "Vue d'ensemble"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:847 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:847
msgid "PID" msgid "PID"
@@ -1667,7 +1667,7 @@ msgstr "Exécuter la commande"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141
msgid "Running" msgid "Running"
msgstr "" msgstr "En cours d'exécution"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833
msgid "Running Processes" msgid "Running Processes"
@@ -1794,7 +1794,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:88 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:88
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:145 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:145
msgid "Stopped" msgid "Stopped"
msgstr "" msgstr "Arrêté"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1098 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1098
msgid "Streams:" msgid "Streams:"
@@ -1952,7 +1952,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Type" msgid "Type"
msgstr "" msgstr "Type"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135
msgid "Type command here... (Ctrl+D to detach)" msgid "Type command here... (Ctrl+D to detach)"
@@ -2042,7 +2042,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240
msgid "Version" msgid "Version"
msgstr "" msgstr "Version"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374
msgid "Volume (named)" msgid "Volume (named)"
@@ -2080,7 +2080,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
msgid "Yes" msgid "Yes"
msgstr "" msgstr "Oui"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323
msgid "attach" msgid "attach"
@@ -2210,7 +2210,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757
msgid "none" msgid "none"
msgstr "" msgstr "aucun"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337
msgid "oom" msgid "oom"
+5 -4
View File
@@ -1,7 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-09-02 17:28+0000\n" "PO-Revision-Date: 2026-10-27 05:52+0000\n"
"Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n" "Last-Translator: Aindriú Mac Giolla Eoin "
"<aindriu80@users.noreply.hosted.weblate.org>\n"
"Language-Team: Irish <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Irish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/ga/>\n" "luciapplicationsdockerman/ga/>\n"
"Language: ga\n" "Language: ga\n"
@@ -9,7 +10,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :(n>" "Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :(n>"
"6 && n<11) ? 3 : 4;\n" "6 && n<11) ? 3 : 4;\n"
"X-Generator: Weblate 2026.9.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -1823,7 +1824,7 @@ msgstr "Sruthanna:"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:103 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:103
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:191 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:191
msgid "Subnet" msgid "Subnet"
msgstr "Folíon" msgstr "Fo-líonra"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:460 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:460
msgid "Subpath" msgid "Subpath"
File diff suppressed because it is too large. Load diff
+20 -19
View File
@@ -1,14 +1,15 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-08-18 10:04+0000\n" "PO-Revision-Date: 2026-10-23 20:11+0000\n"
"Last-Translator: Fiqri Ardyansyah <fiqri0927936@gmail.com>\n" "Last-Translator: \"Hamake D. Arayanai\" "
"<hamakedarayanai@users.noreply.hosted.weblate.org>\n"
"Language-Team: Indonesian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Indonesian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/id/>\n" "luciapplicationsdockerman/id/>\n"
"Language: id\n" "Language: id\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.9.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -32,11 +33,11 @@ msgstr "Daftar kapabilitas kernel untuk ditambahkan ke kontainer"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Action" msgid "Action"
msgstr "" msgstr "Tindakan"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825
msgid "Action unavailable:" msgid "Action unavailable:"
msgstr "" msgstr "Tindakan tidak tersedia:"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Actor" msgid "Actor"
@@ -57,27 +58,27 @@ msgstr "Tambah perangkat host ke kontainer"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:681 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:681
msgid "Added Capabilities" msgid "Added Capabilities"
msgstr "" msgstr "Kemampuan Tambahan"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634
msgid "Advanced" msgid "Advanced"
msgstr "" msgstr "Lanjutan"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590
msgid "Aliases" msgid "Aliases"
msgstr "" msgstr "Nama lain"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1924 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1924
msgid "Aliases (optional):" msgid "Aliases (optional):"
msgstr "" msgstr "Nama lain (opsional):"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:342 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:342
msgid "All Subtypes" msgid "All Subtypes"
msgstr "" msgstr "Semua Subtipe"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:73 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:73
msgid "All Types" msgid "All Types"
msgstr "" msgstr "Semua Jenis"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:647 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:647
msgid "Allocates an ephemeral host port for all of a container's exposed ports" msgid "Allocates an ephemeral host port for all of a container's exposed ports"
@@ -116,7 +117,7 @@ msgstr "Sudah ada"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:431 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:431
msgid "Back to Containers" msgid "Back to Containers"
msgstr "" msgstr "Kembali ke Kontainer"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:48 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:48
msgid "Base device" msgid "Base device"
@@ -124,7 +125,7 @@ msgstr "Perangkat pokok"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:373 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:373
msgid "Bind (host directory)" msgid "Bind (host directory)"
msgstr "" msgstr "Bind (direktori host)"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:306 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:306
msgid "Bind mount a volume" msgid "Bind mount a volume"
@@ -132,7 +133,7 @@ msgstr "Pasang memperlihatkan volume"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:740 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:740
msgid "BlkIO Stats" msgid "BlkIO Stats"
msgstr "" msgstr "Statistik BlkIO"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:675 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:675
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:738 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:738
@@ -158,7 +159,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:206 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:206
msgid "Build an image." msgid "Build an image."
msgstr "" msgstr "Bangun sebuah citra."
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:72 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:72
msgid "" msgid ""
@@ -178,19 +179,19 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:690 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:690
msgid "CPU Period" msgid "CPU Period"
msgstr "" msgstr "Periode CPU"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:625 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:625
msgid "CPU Period (microseconds)" msgid "CPU Period (microseconds)"
msgstr "" msgstr "Periode CPU (mikrodetik)"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:696 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:696
msgid "CPU Quota" msgid "CPU Quota"
msgstr "" msgstr "Kuota CPU"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:628 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:628
msgid "CPU Quota (microseconds)" msgid "CPU Quota (microseconds)"
msgstr "" msgstr "Kuota CPU (mikrodetik)"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:631 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:631
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:702 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:702
+19 -19
View File
@@ -1,14 +1,14 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-13 21:56+0000\n" "PO-Revision-Date: 2026-11-05 22:13+0000\n"
"Last-Translator: Pavel Borecki <pavelbo@users.noreply.hosted.weblate.org>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Italian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/it/>\n" "luciapplicationsdockerman/it/>\n"
"Language: it\n" "Language: it\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.11.dev0\n" "X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -32,7 +32,7 @@ msgstr "Una lista di capacità del kernel da aggiungere al contenitore"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Action" msgid "Action"
msgstr "" msgstr "Azione"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825
msgid "Action unavailable:" msgid "Action unavailable:"
@@ -61,7 +61,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:634
msgid "Advanced" msgid "Advanced"
msgstr "" msgstr "Avanzato"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:590
msgid "Aliases" msgid "Aliases"
@@ -246,7 +246,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1189 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1189
msgid "Clear" msgid "Clear"
msgstr "" msgstr "Cancella"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:617 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:617
msgid "Click to add a new tag to this image" msgid "Click to add a new tag to this image"
@@ -321,7 +321,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1521 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1521
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1533 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1533
msgid "Connected" msgid "Connected"
msgstr "" msgstr "Connesso"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1063 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1063
msgid "Connected to container console" msgid "Connected to container console"
@@ -433,7 +433,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:421 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:421
msgid "Create" msgid "Create"
msgstr "" msgstr "Crea"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:979 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:979
msgid "Create container" msgid "Create container"
@@ -1280,7 +1280,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249
msgid "No" msgid "No"
msgstr "" msgstr "No"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878
msgid "No additional networks available to connect" msgid "No additional networks available to connect"
@@ -1653,7 +1653,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141
msgid "Running" msgid "Running"
msgstr "" msgstr "In esecuzione"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833
msgid "Running Processes" msgid "Running Processes"
@@ -1738,7 +1738,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:161 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:161
msgid "State" msgid "State"
msgstr "" msgstr "Stato"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:703 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:703
msgid "Stats" msgid "Stats"
@@ -1780,7 +1780,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:88 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:88
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:145 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:145
msgid "Stopped" msgid "Stopped"
msgstr "" msgstr "Fermato"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1098 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1098
msgid "Streams:" msgid "Streams:"
@@ -1790,7 +1790,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:103 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:103
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:191 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:191
msgid "Subnet" msgid "Subnet"
msgstr "" msgstr "Sottorete"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:460 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:460
msgid "Subpath" msgid "Subpath"
@@ -1884,7 +1884,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Time" msgid "Time"
msgstr "" msgstr "Orario"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:376 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:376
msgid "Tmpfs" msgid "Tmpfs"
@@ -1936,7 +1936,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Type" msgid "Type"
msgstr "" msgstr "Tipo"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135
msgid "Type command here... (Ctrl+D to detach)" msgid "Type command here... (Ctrl+D to detach)"
@@ -1954,7 +1954,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1640 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1640
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1683 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1683
msgid "Unknown error" msgid "Unknown error"
msgstr "" msgstr "Errore sconosciuto"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:485 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:485
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:250 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:250
@@ -2026,7 +2026,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240
msgid "Version" msgid "Version"
msgstr "" msgstr "Versione"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374
msgid "Volume (named)" msgid "Volume (named)"
@@ -2064,7 +2064,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
msgid "Yes" msgid "Yes"
msgstr "" msgstr "Si"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323
msgid "attach" msgid "attach"
@@ -2194,7 +2194,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757
msgid "none" msgid "none"
msgstr "" msgstr "nessuno"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337
msgid "oom" msgid "oom"
+5 -6
View File
@@ -1,8 +1,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-18 16:40+0000\n" "PO-Revision-Date: 2026-11-01 06:11+0000\n"
"Last-Translator: Janderson Vieira Santos " "Last-Translator: LucasMZ <git@lucasmz.dev>\n"
"<ritew@users.noreply.hosted.weblate.org>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"openwrt/luciapplicationsdockerman/pt_BR/>\n" "openwrt/luciapplicationsdockerman/pt_BR/>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
@@ -771,7 +770,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:77 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:77
msgid "Fatal" msgid "Fatal"
msgstr "Fatal" msgstr "Fatais"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:924 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:924
msgid "File" msgid "File"
@@ -979,7 +978,7 @@ msgstr "Índice do Endereço do Servidor"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network.js:57 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network.js:57
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:161 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:161
msgid "Info" msgid "Info"
msgstr "Informação (Info)" msgstr "Informações"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network.js:73 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network.js:73
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:72 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/network_new.js:72
@@ -1762,7 +1761,7 @@ msgstr "Condição geral"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:721 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:721
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:840 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:840
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Estado"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1109 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1109
msgid "Stderr" msgid "Stderr"
+14 -14
View File
@@ -1,7 +1,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-13 21:56+0000\n" "PO-Revision-Date: 2026-11-05 09:04+0000\n"
"Last-Translator: Pavel Borecki <pavelbo@users.noreply.hosted.weblate.org>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Romanian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsdockerman/ro/>\n" "luciapplicationsdockerman/ro/>\n"
"Language: ro\n" "Language: ro\n"
@@ -9,7 +9,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n" "20)) ? 1 : 2;\n"
"X-Generator: Weblate 2026.11.dev0\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -33,7 +33,7 @@ msgstr "O listă de capabilități de kernel care trebuie adăugate la container
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Action" msgid "Action"
msgstr "" msgstr "Acţiune"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1825
msgid "Action unavailable:" msgid "Action unavailable:"
@@ -954,7 +954,7 @@ msgstr "Prezentare generală a imaginilor"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:359 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:359
msgid "Import" msgid "Import"
msgstr "Importați" msgstr "Importare"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:202 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:202
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:212 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:212
@@ -1291,7 +1291,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:249
msgid "No" msgid "No"
msgstr "" msgstr "Nu"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1878
msgid "No additional networks available to connect" msgid "No additional networks available to connect"
@@ -1668,7 +1668,7 @@ msgstr "Executați comanda"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:84
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:141
msgid "Running" msgid "Running"
msgstr "" msgstr "Rulare"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:833
msgid "Running Processes" msgid "Running Processes"
@@ -1764,7 +1764,7 @@ msgstr "Statistici"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:721 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:721
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:840 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:840
msgid "Status" msgid "Status"
msgstr "Stare" msgstr "Status"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1109 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1109
msgid "Stderr" msgid "Stderr"
@@ -1936,7 +1936,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/volumes.js:45 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/volumes.js:45
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/volumes.js:111 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/volumes.js:111
msgid "Total" msgid "Total"
msgstr "" msgstr "Total"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:170 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:170
msgid "Total Memory" msgid "Total Memory"
@@ -1953,7 +1953,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:63
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/events.js:249
msgid "Type" msgid "Type"
msgstr "" msgstr "Tip"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1135
msgid "Type command here... (Ctrl+D to detach)" msgid "Type command here... (Ctrl+D to detach)"
@@ -2043,7 +2043,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/overview.js:240
msgid "Version" msgid "Version"
msgstr "" msgstr "Versiune"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:374
msgid "Volume (named)" msgid "Volume (named)"
@@ -2081,7 +2081,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:679
msgid "Yes" msgid "Yes"
msgstr "" msgstr "Da"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:323
msgid "attach" msgid "attach"
@@ -2203,7 +2203,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:409 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:409
msgid "network" msgid "network"
msgstr "" msgstr "rețea"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:410 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:410
msgid "node" msgid "node"
@@ -2211,7 +2211,7 @@ msgstr ""
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:757
msgid "none" msgid "none"
msgstr "" msgstr "niciuna"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:337
msgid "oom" msgid "oom"
+3 -3
View File
@@ -1,6 +1,6 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-10-01 12:16+0000\n" "PO-Revision-Date: 2026-10-25 04:14+0000\n"
"Last-Translator: SnIPeRSnIPeR <snipersniper@users.noreply.hosted.weblate.org>" "Last-Translator: SnIPeRSnIPeR <snipersniper@users.noreply.hosted.weblate.org>"
"\n" "\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Russian <https://hosted.weblate.org/projects/openwrt/"
@@ -10,7 +10,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 2026.10.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -1576,7 +1576,7 @@ msgstr "Открыть порт(ы) контейнера хосту"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:361 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:361
msgid "Pull" msgid "Pull"
msgstr "Скачать" msgstr "Запрашивать"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:362 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:362
msgid "Push" msgid "Push"
+12 -13
View File
@@ -1,15 +1,14 @@
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2026-08-17 17:58+0000\n" "PO-Revision-Date: 2026-10-20 09:40+0000\n"
"Last-Translator: 加尼瑪空格把變數都破壞了! " "Last-Translator: TCP <tcp@users.noreply.hosted.weblate.org>\n"
"<roc_fe@users.noreply.hosted.weblate.org>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/" "Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/openwrt/luciapplicationsdockerman/zh_Hant/>\n" "projects/openwrt/luciapplicationsdockerman/zh_Hant/>\n"
"Language: zh_Hant\n" "Language: zh_Hant\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.9.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:505
msgid "/mnt/path" msgid "/mnt/path"
@@ -250,7 +249,7 @@ msgstr "點選以新增標籤至此映像檔"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:531 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:531
msgid "Click to remove this tag" msgid "Click to remove this tag"
msgstr "點選以刪除此標籤" msgstr "點選以移除此標籤"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:213 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/networks.js:213
msgid "Click to view this network" msgid "Click to view this network"
@@ -536,7 +535,7 @@ msgstr "已斷線"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:536 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:536
msgid "Do you want to remove the tag \"%s\"?" msgid "Do you want to remove the tag \"%s\"?"
msgstr "刪除標籤 「%s」嗎?" msgstr "移除標籤 「%s」嗎?"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:16 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:16
msgid "Docker - Configuration" msgid "Docker - Configuration"
@@ -792,11 +791,11 @@ msgstr "僅適用於本地 dockerd socket 實例。"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:301 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/containers.js:301
msgid "Force Remove" msgid "Force Remove"
msgstr "強制刪除" msgstr "強制移除"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:423 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:423
msgid "Force remove" msgid "Force remove"
msgstr "強制刪除" msgstr "強制移除"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1314 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1314
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:771 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js:771
@@ -1593,15 +1592,15 @@ msgstr "Registry 鏡像"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:424 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:424
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1808 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1808
msgid "Remove" msgid "Remove"
msgstr "刪除" msgstr "移除"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1815 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container.js:1815
msgid "Remove container?" msgid "Remove container?"
msgstr "刪除容器?" msgstr "移除容器?"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:535 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:535
msgid "Remove tag" msgid "Remove tag"
msgstr "刪除標籤" msgstr "移除標籤"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:625 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:625
msgid "Repository" msgid "Repository"
@@ -1837,7 +1836,7 @@ msgstr "標籤新增成功"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:554 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/images.js:554
msgid "Tag removed successfully" msgid "Tag removed successfully"
msgstr "標籤刪除成功" msgstr "標籤移除成功"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:105 #: applications/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/configuration.js:105
msgid "The first match is used." msgid "The first match is used."
@@ -2225,7 +2224,7 @@ msgstr "重新載入"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:376 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:376
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:393 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:393
msgid "remove" msgid "remove"
msgstr "刪除" msgstr "移除"
#: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:339 #: applications/luci-app-dockerman/htdocs/luci-static/resources/dockerman/common.js:339
msgid "rename" msgid "rename"
+22 -2
View File
@@ -7,12 +7,32 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for fastnet LUCI_TITLE:=LuCI support for fastnet
LUCI_DEPENDS:=+fastnet +luci-lib-linkeaseauth +linkease-app-entry LUCI_DEPENDS:=+fastnet +luci-lib-linkeaseauth +linkease-app-entry
# APK uses -rN; OPKG uses -N for runtime package releases.
LUCI_EXTRA_DEPENDS:=fastnet (>=0.8.9-$(if $(CONFIG_USE_APK),r)1)
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
PKG_VERSION:=0.8.1-r5 PKG_VERSION:=0.8.9-r1
PKG_RELEASE:=7 PKG_RELEASE:=8
# Preserve LuCI translation version ordering when upgrading older git-* packages.
PKG_PO_VERSION:=git-26.313.00000-082
LUCI_MINIFY_CSS:=0 LUCI_MINIFY_CSS:=0
LUCI_MINIFY_JS:=0 LUCI_MINIFY_JS:=0
define Package/luci-app-fastnet/postinst
#!/bin/sh
set -e
"$${IPKG_INSTROOT}/usr/libexec/fastnet-card-register" install
if [ -z "$${IPKG_INSTROOT}" ]; then
rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null || true
fi
endef
define Package/luci-app-fastnet/prerm
#!/bin/sh
"$${IPKG_INSTROOT}/usr/libexec/fastnet-card-register" remove
endef
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature # call BuildPackage - OpenWrt buildroot signature
+65 -1
View File
@@ -1,10 +1,15 @@
module("luci.controller.fastnet", package.seeall) module("luci.controller.fastnet", package.seeall)
function index() function index()
for _,action in ipairs({"summary","run","task","cancel"}) do
entry({"admin","services","fastnet","card",action},call("action_card_"..action)).leaf=true
end
if not nixio.fs.access("/etc/config/fastnet") then return end if not nixio.fs.access("/etc/config/fastnet") then return end
entry({"admin", "services", "fastnet"}, cbi("fastnet"), _("FastNet"), 50).dependent = true entry({"admin", "services", "fastnet"}, cbi("fastnet"), _("FastNet"), 50).dependent = true
entry({"admin", "services", "fastnet", "status"}, call("action_status")).leaf = true entry({"admin", "services", "fastnet", "status"}, call("action_status")).leaf = true
entry({"admin", "services", "fastnet", "browser-origin"}, call("action_browser_origin")).leaf = true
entry({"admin", "services", "fastnet", "embed"}, call("action_embed")).leaf = true
local open = entry({"admin", "services", "fastnet", "open"}, call("action_open")) local open = entry({"admin", "services", "fastnet", "open"}, call("action_open"))
open.leaf = true open.leaf = true
open.dependent = false open.dependent = false
@@ -30,5 +35,64 @@ function action_status()
end end
function action_open() function action_open()
compat():open("fastnet") local dispatcher = require "luci.dispatcher"
require("luci.http").redirect(dispatcher.build_url("admin", "services", "fastnet", "embed") .. "?standalone=1")
end
-- Only the launch metadata passes through LuCI. The iframe and all test data
-- connect to the configured FastNet service port in the browser.
function action_embed()
local http = require "luci.http"
local ctx = require("luci.dispatcher").context
if http.getenv("REQUEST_METHOD") ~= "GET" then http.status(405); return end
if not ctx.authsession or ctx.authuser ~= "root" then http.status(403); return end
local authority = http.getenv("HTTP_HOST") or ""
local host = authority:match("^(%[[%x:%.]+%]):?%d*$") or authority:match("^([%w%.%-]+):?%d*$")
local uci = require("luci.model.uci").cursor()
local port = tonumber(uci:get_first("fastnet", "fastnet", "port") or "3200")
if uci:get_first("fastnet", "fastnet", "enabled") == "0" or not host or not port or port % 1 ~= 0 or port < 1 or port > 65535 then
http.status(503); return
end
local url = "http://" .. host .. ":" .. tostring(port) .. "/webui/"
local query = {}
if http.formvalue("standalone") ~= "1" then
query[#query+1] = "embed=quickstart"
query[#query+1] = "theme=" .. (http.formvalue("theme") == "dark" and "dark" or "light")
end
if http.formvalue("view") == "history" then query[#query+1] = "view=history" end
local token = uci:get_first("fastnet", "fastnet", "token") or ""
if token ~= "" then query[#query+1] = "token=" .. http.urlencode(token) end
if #query > 0 then url = url .. "?" .. table.concat(query, "&") end
http.header("Cache-Control", "no-store")
http.header("Referrer-Policy", "no-referrer")
if http.formvalue("format") == "json" then
http.prepare_content("application/json"); http.write_json({url=url})
else
http.redirect(url)
end
end
function action_card_summary() require("luci.model.fastnet.card").new():handle("summary") end
function action_card_run() require("luci.model.fastnet.card").new():handle("run") end
function action_card_task() require("luci.model.fastnet.card").new():handle("task") end
function action_card_cancel() require("luci.model.fastnet.card").new():handle("cancel") end
-- uHTTPd owns REMOTE_ADDR. The app proxy's loopback peer and browser-provided
-- forwarded headers cannot stand in for the real browser in LAN capability UI.
function action_browser_origin()
local http = require "luci.http"
local ctx = require("luci.dispatcher").context
if not ctx.authsession or ctx.authuser ~= "root" then http.status(403); return end
if http.getenv("REQUEST_METHOD") ~= "GET" then http.status(405); return end
local address = http.getenv("REMOTE_ADDR")
if type(address) ~= "string" or address == "" or #address > 64 or not address:match("^[%x:%.]+$") then http.status(503); return end
local loopback = address == "::1" or address:match("^127%.") ~= nil or address:match("^::ffff:127%.") ~= nil
local local_address = loopback
for _, entry in ipairs(require("nixio").getifaddrs() or {}) do
if entry.addr == address then local_address = true; break end
end
http.prepare_content("application/json")
http.header("Cache-Control", "no-store")
http.header("X-Content-Type-Options", "nosniff")
http.write_json({isLoopback=loopback,isLocal=local_address,isLocalInterface=local_address})
end end
@@ -0,0 +1,150 @@
-- The public authenticated adapter. No shell commands, core tokens or probes.
local M = {}
local SOCKET = "/var/run/fastnet-card.sock"
local STATE = "/etc/fastnet/card-state.json"
local MAX_BODY, MAX_RESPONSE = 1024, 8192
local function socket_request(method, path, body)
local nixio = require "nixio"
local socket = nixio.socket("unix", "stream")
if not socket then return nil, nil, "service_unavailable" end
local deadline = os.time() + 6
local function timeout()
local remaining = deadline - os.time()
if remaining <= 0 then return false end
socket:setopt("socket", "sndtimeo", remaining)
socket:setopt("socket", "rcvtimeo", remaining)
return true
end
local function fail(reason) socket:close(); return nil, nil, reason end
timeout()
if not socket:connect(SOCKET) then return fail("service_unavailable") end
body = body or ""
local request = method .. " /api/card/" .. path .. " HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: " .. #body .. "\r\n\r\n" .. body
local offset = 1
while offset <= #request do
if not timeout() then return fail("upstream_timeout") end
local sent = socket:send(request:sub(offset))
if not sent or sent <= 0 then return fail("upstream_timeout") end
offset = offset + sent
end
local chunks, length = {}, 0
while true do
if not timeout() then return fail("upstream_timeout") end
local chunk = socket:recv(2048)
if not chunk then return fail("upstream_timeout") end
if chunk == "" then break end
length = length + #chunk
if length > MAX_RESPONSE + 4096 then return fail("upstream_too_large") end
chunks[#chunks + 1] = chunk
end
socket:close()
local raw = table.concat(chunks)
local headers, response = raw:match("^(.-)\r\n\r\n(.*)$")
local status = headers and tonumber(headers:match("^HTTP/1%.[01]%s+(%d%d%d)"))
if not status or not headers:lower():match("content%-type:%s*application/json") or #response > MAX_RESPONSE then return nil, nil, "invalid_upstream" end
return status, response
end
local function defaults()
local nixio, fs = require "nixio", require "nixio.fs"
local function read(path, maximum)
local file = nixio.open(path, "r")
if not file then return nil end
local parts, length = {}, 0
while true do
local part=file:read(4096)
if not part then file:close();return nil end
if part=="" then break end
length=length+#part
if length>maximum then file:close();return nil end
parts[#parts+1]=part
end
file:close();return table.concat(parts)
end
return {http=require "luci.http",ctx=require("luci.dispatcher").context,json=require "luci.jsonc",fs=fs,
enabled=function() return require("luci.model.uci").cursor():get_first("fastnet", "fastnet", "enabled") ~= "0" end,
state=function() return read(STATE, 128*1024) end,request=socket_request}
end
function M.new(deps)
local d = deps or defaults()
local http, ctx, json = d.http, d.ctx, d.json
local function reply(status, value)
http.status(status)
http.prepare_content("application/json")
http.header("Cache-Control", "no-store")
http.header("X-Content-Type-Options", "nosniff")
http.write(type(value)=="string" and value or json.stringify(value))
end
local function error_reply(status, code) return reply(status, {error=code}) end
-- jsonc drops null object members when decoding. Forward live core JSON as
-- bytes; reconstruct nullable fields explicitly only for a stopped service.
local function atom(value) return value==nil and "null" or json.stringify(value) end
local function measurement(value)
if type(value)~="table" then return '{"status":"not_tested","value":null,"measuredAt":null,"error":null}' end
return '{"status":'..atom(value.status)..',"value":'..atom(value.value)..',"measuredAt":'..atom(value.measuredAt)..',"error":'..atom(value.error)..',"runId":'..atom(value.runId)..'}'
end
local function stopped_summary(reason)
local raw=d.state();local disk=raw and json.parse(raw) or nil
local latest=type(disk)=="table" and (disk.schemaVersion==1 or disk.schemaVersion==2) and disk.latest or nil
local result="null"
if type(latest)=="table" then
result='{"runId":'..atom(latest.runId)..',"measuredAt":'..atom(latest.measuredAt)..',"download":'..measurement(latest.download)..',"upload":'..measurement(latest.upload)..',"nat":'..measurement(latest.nat)..',"ipv6":'..measurement(latest.ipv6)
if type(latest.bandwidth)=="table" then result=result..',"bandwidth":'..json.stringify(latest.bandwidth) end
result=result..'}'
end
local state = d.enabled() and "unavailable" or "disabled"
return reply(200,'{"schemaVersion":1,"instanceId":"","service":{"state":'..atom(state)..',"reason":'..atom(reason)..'},"latest":'..result..',"latestResults":'..json.stringify(type(disk)=="table" and disk.latestResults or {})..',"task":null}')
end
return {handle=function(_, action)
if type(ctx.authsession)~="string" or ctx.authsession=="" then return error_reply(401,"unauthenticated") end
if ctx.authuser~="root" then return error_reply(403,"forbidden") end
local writing=action=="run" or action=="cancel"
local method=http.getenv("REQUEST_METHOD")
if method~=(writing and "POST" or "GET") then return error_reply(405,"method") end
if not d.fs.access("/etc/config/fastnet") then return error_reply(503,"installation_incomplete") end
if not d.fs.access("/usr/sbin/FastNet") then return error_reply(503,"core_missing") end
local body, path = nil, action
if writing then
local site=http.getenv("HTTP_SEC_FETCH_SITE")
if site and site~="same-origin" and site~="none" then return error_reply(403,"cross_origin") end
local origin=http.getenv("HTTP_ORIGIN")
local secure=http.getenv("HTTPS");local scheme=(secure=="on" or secure=="1") and "https" or "http"
if origin and origin~=scheme.."://"..(http.getenv("HTTP_HOST") or "") then return error_reply(403,"cross_origin") end
-- Some uhttpd builds omit custom CGI headers. The standard LuCI query
-- token is read without consuming the JSON request body.
local csrf=http.getenv("HTTP_X_CSRF_TOKEN") or http.getenv("HTTP_X-CSRF-TOKEN") or http.formvalue("token",true)
if type(ctx.authtoken)~="string" or ctx.authtoken=="" or csrf~=ctx.authtoken then return error_reply(403,"csrf") end
local kind=(http.getenv("CONTENT_TYPE") or ""):match("^%s*([^;]+)")
if kind~="application/json" then return error_reply(422,"content_type") end
local size=tonumber(http.getenv("CONTENT_LENGTH"))
if size and size>MAX_BODY then return error_reply(413,"body_too_large") end
body=http.content()
if type(body)~="string" or #body>MAX_BODY then return error_reply(413,"body_too_large") end
local key=action=="run" and "idempotencyKey" or "id"
local value=body:match('^%s*{%s*"'..key..'"%s*:%s*"([A-Za-z0-9_-]+)"%s*}%s*$')
if not value or #value>(action=="run" and 64 or 96) or #value<(action=="run" and 16 or 1) then return error_reply(422,"invalid_request") end
elseif action=="task" then
local id=http.formvalue("id")
if type(id)~="string" or #id<1 or #id>96 or not id:match("^[A-Za-z0-9_-]+$") then return error_reply(422,"invalid_id") end
path="task?id="..id
elseif action~="summary" then return error_reply(404,"not_found") end
local status, raw, reason=d.request(method,path,body)
if not status then
if action=="summary" and reason=="service_unavailable" then return stopped_summary(reason) end
return error_reply(reason=="service_unavailable" and 503 or 502,reason or "invalid_upstream")
end
local value=type(raw)=="string" and #raw<=MAX_RESPONSE and json.parse(raw) or nil
if type(value)~="table" then return error_reply(502,"invalid_upstream") end
if status>=400 then
local allowed={busy=true,not_found=true,invalid_id=true,invalid_request=true,persistence_failed=true,local_only=true,method=true}
return error_reply(status,allowed[value.error] and value.error or "core_error")
end
if action=="summary" then
if value.schemaVersion~=1 or type(value.service)~="table" then return error_reply(502,"invalid_upstream") end
elseif type(value.id)~="string" or type(value.state)~="string" then return error_reply(502,"invalid_upstream") end
return reply(status,raw)
end}
end
return M
@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
/usr/libexec/fastnet-card-register install || exit 1
rm -f /tmp/luci-indexcache rm -f /tmp/luci-indexcache
exit 0 exit 0
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
set -eu
root=${IPKG_INSTROOT:-}
source="$root/usr/share/fastnet/quickstart/fastnet.json"
target="$root/usr/share/quickstart/cards.d/fastnet.json"
case "${1:-install}" in
install)
[ -f "$source" ] || exit 1
entry=$(sed -n 's/^[[:space:]]*"entry": "\(\/luci-static\/fastnet\/quickstart\/card\.[a-f0-9][a-f0-9]*\.js\)".*/\1/p' "$source")
[ -n "$entry" ] && [ -f "$root/www$entry" ] || exit 1
umask 022
mkdir -p "${target%/*}"
temporary="$target.new.$$"
trap 'rm -f "$temporary"' EXIT HUP INT TERM
cp "$source" "$temporary"
mv -f "$temporary" "$target"
;;
remove)
# Never delete another package's registration, including a replaced file.
if [ -f "$source" ] && cmp -s "$source" "$target"; then rm -f "$target"; fi
;;
*) exit 2 ;;
esac
@@ -0,0 +1,23 @@
{
"schemaVersion": 1,
"id": "plugin.fastnet",
"title": "外网测速",
"glyph": "activity",
"abi": "quickstart-card-v1",
"version": "0.8.9-1",
"apiBase": "/cgi-bin/luci/admin/services/fastnet/card",
"forms": {
"standard": {
"minWidth": 280,
"minHeight": 260
},
"summary": {
"minWidth": 240,
"minHeight": 148
}
},
"stacked": [
"summary"
],
"entry": "/luci-static/fastnet/quickstart/card.dfb0ce55.js"
}
@@ -0,0 +1,398 @@
var D = (n, b, v) => new Promise((e, d) => {
var l = (r) => {
try {
f(v.next(r));
} catch (q) {
d(q);
}
}, a = (r) => {
try {
f(v.throw(r));
} catch (q) {
d(q);
}
}, f = (r) => r.done ? e(r.value) : Promise.resolve(r.value).then(l, a);
f((v = v.apply(n, b)).next());
});
import { defineAsyncComponent as ia, h as W, computed as z, ref as J, onMounted as ua, onUnmounted as pa, openBlock as C, createElementBlock as B, unref as c, normalizeClass as G, createElementVNode as s, createTextVNode as w, toDisplayString as o, createBlock as la, resolveDynamicComponent as oa, withCtx as fa, createCommentVNode as ca, reactive as ma } from "/luci-static/quickstart/card-runtime-v1.js";
const ga = '[data-fastnet-card]{--fn-down:var(--qs-card-accent);position:relative;isolation:isolate;container-type:inline-size;gap:12px;border-radius:inherit}[data-fastnet-card] .qs-card-header h2>svg{color:var(--fn-down)}[data-fastnet-card] .qs-card-primary{background:var(--qs-card-accent);color:var(--qs-card-panel);border-color:transparent;padding:6px 13px;border-radius:9px;font-weight:600}[data-fastnet-card] .qs-card-menu>summary{border-color:transparent;color:var(--qs-card-muted)}[data-fastnet-card] .fn-speed-stage{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;gap:14px;padding:18px 20px;border-radius:14px;border:1px solid var(--qs-card-line);background:var(--qs-card-soft)}[data-fastnet-card] .fn-speed-caption{display:flex;align-items:center;justify-content:space-between;gap:6px;font-size:10px;letter-spacing:.7px;color:var(--qs-card-muted)}[data-fastnet-card] .fn-live{display:flex;align-items:center;gap:5px;letter-spacing:0;white-space:nowrap}[data-fastnet-card] .fn-live:before{content:"";width:5px;height:5px;border-radius:50%;background:var(--qs-card-muted)}[data-fastnet-card] .fn-live.is-active{color:var(--qs-card-accent)}[data-fastnet-card] .fn-live.is-active:before{background:currentColor;box-shadow:0 0 0 3px var(--qs-card-soft)}[data-fastnet-card] .qs-card-metrics{gap:18px;align-items:center;grid-template-columns:1.25fr 1fr}[data-fastnet-card] .qs-card-metrics strong{font-size:clamp(30px,12cqi,52px);line-height:1.15;letter-spacing:-1.7px;font-weight:700;margin-top:4px;color:var(--fn-down)}[data-fastnet-card] .qs-card-metrics>div+div{border-left:1px solid var(--qs-card-line);padding-left:18px}[data-fastnet-card] .qs-card-metrics>div+div strong{font-size:clamp(25px,8cqi,36px);color:var(--qs-card-text);letter-spacing:-.9px}[data-fastnet-card] .qs-card-metrics small{letter-spacing:0}[data-fastnet-card] .qs-card-time{gap:5px;font-size:10px}[data-fastnet-card] .qs-card-statuses{padding:0;border:0;gap:10px}[data-fastnet-card] .qs-card-statuses>div{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:3px 8px;padding:8px 10px;border:1px solid var(--qs-card-line);border-radius:8px;background:var(--qs-card-panel)}[data-fastnet-card] .qs-card-statuses span{display:flex;align-items:center;gap:6px;letter-spacing:.3px;margin:0;flex:none}[data-fastnet-card] .qs-card-statuses i{width:6px;height:6px;border-radius:50%;background:var(--qs-card-muted)}[data-fastnet-card] .qs-card-statuses [data-tone=good] i{background:var(--qs-card-good)}[data-fastnet-card] .qs-card-statuses [data-tone=warning] i{background:var(--qs-card-warning)}[data-fastnet-card].qs-card-summary{gap:3px;background:none}[data-fastnet-card].qs-card-summary .fn-speed-stage{display:block;flex:none;padding:0;border:0;background:none}[data-fastnet-card].qs-card-summary .fn-speed-caption{display:none}[data-fastnet-card].qs-card-summary .qs-card-metrics{grid-template-columns:1fr 1fr;gap:12px}[data-fastnet-card].qs-card-summary .qs-card-metrics strong{font-size:23px;letter-spacing:-.5px;margin:0}[data-fastnet-card].qs-card-summary .qs-card-metrics>div+div{padding:0;border:0}[data-fastnet-card].qs-card-summary .qs-card-statuses>div{padding:0;border:0;background:none;max-width:50%;flex-wrap:nowrap;gap:5px}[data-fastnet-card].qs-card-summary .qs-card-statuses span{margin:0;gap:4px}[data-fastnet-card].qs-card-summary .qs-card-statuses i{width:4px;height:4px}[data-fastnet-card].qs-card-summary .qs-card-primary{padding:2px 7px;border-radius:6px}@media(max-width:600px){[data-fastnet-card]:not(.qs-card-summary) .fn-speed-stage{padding:14px;gap:12px}[data-fastnet-card]:not(.qs-card-summary) .qs-card-metrics strong{font-size:36px}[data-fastnet-card]:not(.qs-card-summary) .qs-card-metrics>div+div strong{font-size:28px}}[data-fastnet-card].fn-dense:not(.qs-card-summary){gap:5px;padding:10px 14px}[data-fastnet-card].fn-dense:not(.qs-card-summary) .fn-speed-stage{padding:6px 12px;gap:3px;min-height:81px;flex-shrink:0}[data-fastnet-card].fn-dense:not(.qs-card-summary) .fn-speed-caption{display:none}[data-fastnet-card].fn-dense:not(.qs-card-summary) .qs-card-metrics strong{font-size:28px;line-height:1.15;margin:0}[data-fastnet-card].fn-dense:not(.qs-card-summary) .qs-card-metrics>div+div strong{font-size:23px}[data-fastnet-card].fn-dense:not(.qs-card-summary) .qs-card-statuses>div{padding:6px 9px}[data-fastnet-card] .fn-lan-summary{flex:none;min-width:0;padding:0 20px;color:var(--qs-card-text)}[data-fastnet-card] .fn-lan-caption{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:2px 8px;font-size:10px;color:var(--qs-card-muted)}[data-fastnet-card] .fn-lan-caption time{font-variant-numeric:tabular-nums;white-space:nowrap}[data-fastnet-card] .fn-lan-metrics{display:grid;grid-template-columns:1.25fr 1fr;gap:18px;margin-top:6px}[data-fastnet-card] .fn-lan-metrics>div{min-width:0}[data-fastnet-card] .fn-lan-metrics>div+div{padding-left:18px;border-left:1px solid var(--qs-card-line)}[data-Line truncated
function ya(n) {
var b, v, e, d;
if ((n == null ? void 0 : n.schemaVersion) !== 1 || !["ready", "disabled", "unavailable"].includes((b = n.service) == null ? void 0 : b.state) || !("latest" in n) || !("task" in n)) throw Error("invalid_summary");
if ((v = n.latest) != null && v.bandwidth) {
const l = n.latest.bandwidth;
if (![l.downloadBps, l.uploadBps].every((a) => typeof a == "number" && Number.isFinite(a) && a >= 0) || !l.measuredAt || !Number.isFinite(Date.parse(l.measuredAt))) throw Error("invalid_bandwidth");
}
if (n.task && !K.includes(n.task.state)) throw Error("invalid_task");
for (const l of ["download", "upload", "nat", "ipv6"]) if (n.latest) {
const a = n.latest[l];
if (!a || !["ok", "unavailable", "error", "not_tested"].includes(a.status) || a.value !== null && (["download", "upload"].includes(l) ? typeof a.value != "number" || !Number.isFinite(a.value) || a.value < 0 : typeof a.value != "string")) throw Error("invalid_measurement");
}
for (const l of ["download", "upload", "lanDownload", "lanUpload", "lanPing"]) {
const a = (d = (e = n.latestResults) == null ? void 0 : e[l]) == null ? void 0 : d.value;
if (a != null && (!Number.isFinite(a) || a < 0)) throw Error("invalid_measurement");
}
return n;
}
function va(n) {
var e, d;
const b = n == null ? void 0 : n.latestResults;
if (b != null && b.download || b != null && b.upload) {
const l = b.download, a = b.upload;
return { downloadBps: (e = l == null ? void 0 : l.value) != null ? e : null, uploadBps: (d = a == null ? void 0 : a.value) != null ? d : null, measuredAt: [l == null ? void 0 : l.measuredAt, a == null ? void 0 : a.measuredAt].filter(Boolean).sort().pop(), mixed: !!(l && a && l.runId !== a.runId) };
}
const v = n == null ? void 0 : n.latest;
return v ? v.bandwidth || { downloadBps: v.download.status === "ok" ? v.download.value : null, uploadBps: v.upload.status === "ok" ? v.upload.value : null, measuredAt: v.measuredAt } : null;
}
function E(n) {
return n == null ? "—" : n > 0 && n < 1e5 ? "<0.1" : (n / 1e6).toLocaleString("en-US", { maximumFractionDigits: n >= 1e8 ? 0 : 1 });
}
function H(n, b) {
return !n || !Number.isFinite(Date.parse(n)) ? "—" : new Date(n).toLocaleString(b === "en" ? "en-GB" : "zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: !1 });
}
function xa(n, b = (e) => e, v = globalThis) {
const e = b({ loading: !1, summary: null, task: null, submitting: !1, cancelling: !1, error: "", errorAction: "read", paused: !1, failures: 0 });
let d = !0, l = !0, a, f, r, q = null, y = 0;
const h = () => {
v.clearTimeout(a), a = void 0, f == null || f.abort(), f = void 0, y++;
}, N = (u) => [401, 403].includes(u == null ? void 0 : u.status) ? "permission" : (u == null ? void 0 : u.status) === 404 ? "upgrade" : "unavailable", S = () => {
d && l && !e.paused && (a = v.setTimeout(k(e.task) ? I : _, k(e.task) ? 2e3 : 15e3));
};
function I() {
return D(this, null, function* () {
if (!d || !l || !k(e.task)) return;
const u = e.task.id, m = ++y;
f = new AbortController();
try {
const g = yield n.request("/task?id=" + encodeURIComponent(u), { signal: f.signal });
if (!d || m !== y) return;
if (g.id !== u || !K.includes(g.state)) throw Error("invalid_task");
if (e.task = g, e.failures = 0, e.error = "", !k(g)) {
q = null, yield _();
return;
}
} catch (g) {
if (!d || m !== y) return;
e.failures++, e.error = N(g), e.errorAction = "read", (e.failures >= 3 || ["permission", "upgrade"].includes(e.error)) && (e.paused = !0);
} finally {
d && m === y && (f = void 0, S());
}
});
}
function _() {
return D(this, null, function* () {
if (h(), !d || !l) return;
const u = y;
e.loading = !0, f = new AbortController();
try {
const m = ya(yield n.request("/summary", { signal: f.signal }));
if (!d || u !== y) return;
e.summary = m, e.task = m.task || m.lastTask || null, e.error = "", e.failures = 0, e.paused = !1, k(e.task) && (q = null);
} catch (m) {
d && u === y && (e.error = N(m), e.errorAction = "read", e.failures++, e.paused = e.failures >= 3 || ["permission", "upgrade"].includes(e.error));
} finally {
d && u === y && (e.loading = !1, f = void 0, S());
}
});
}
function V() {
return D(this, null, function* () {
var m;
if (!d || e.error === "permission" || e.submitting || k(e.task) || e.loading || ((m = e.summary) == null ? void 0 : m.service.state) !== "ready") return;
h();
const u = y;
e.submitting = !0, e.error = "", r = new AbortController(), q || (q = Array.from(crypto.getRandomValues(new Uint8Array(16)), (g) => g.toString(16).padStart(2, "0")).join(""));
try {
const g = yield n.request("/run", { method: "POST", body: JSON.stringify({ idempotencyKey: q }), signal: r.signal });
if (!d) return;
if (!K.includes(g.state)) throw Error("invalid_task");
if (q = null, u !== y) return;
e.task = g, e.paused = !1, e.failures = 0, k(g) ? S() : yield _();
} catch (g) {
if (!d || u !== y) return;
(g == null ? void 0 : g.status) === 409 ? (q = null, yield _()) : (e.error = N(g), e.errorAction = ["permission", "upgrade"].includes(e.error) ? "read" : "run", g != null && g.status && g.status < 500 && (q = null));
} finally {
d && (e.submitting = !1, r = void 0);
}
});
}
function M() {
return D(this, null, function* () {
if (!d || !k(e.task) || e.cancelling) return;
h();
const u = y;
e.cancelling = !0, r = new AbortController();
try {
const m = yield n.request("/cancel", { method: "POST", body: JSON.stringify({ id: e.task.id }), signal: r.signal });
if (!d || u !== y) return;
e.task = m, k(m) ? S() : yield _();
} catch (m) {
d && u === y && (e.error = N(m), e.errorAction = "read", S());
} finally {
d && (e.cancelling = !1, r = void 0);
}
});
}
return { state: e, start: V, stop: M, reload: _, visibility(u) {
l = u, h(), u && _();
}, dispose() {
d = !1, h(), r == null || r.abort();
} };
}
const ba = ["data-task-id"], qa = { class: "qs-card-header" }, ha = {
key: 0,
class: "widget-action-group"
}, wa = {
key: 1,
class: "qs-card-actions"
}, ka = { class: "qs-card-menu" }, _a = ["aria-label"], Aa = { class: "fn-speed-stage" }, Ca = { class: "fn-speed-caption" }, Na = { class: "qs-card-metrics" }, Sa = { class: "qs-card-time" }, Ta = ["datetime"], za = ["aria-label"], Ba = { class: "fn-lan-caption" }, Ra = { class: "fn-lan-route" }, Fa = ["datetime"], Pa = { class: "fn-lan-metrics" }, Da = { class: "fn-lan-label" }, Ea = { class: "fn-lan-label" }, Ia = { class: "qs-card-statuses" }, La = ["data-tone"], Ua = ["title"], Va = ["data-tone"], Ma = ["title"], Oa = {
key: 0,
class: "qs-card-progress",
role: "status"
}, ja = ["disabled"], $a = {
key: 1,
class: "qs-card-alert",
role: "alert"
}, Wa = {
key: 2,
class: "qs-card-alert",
role: "status"
}, Ha = {
__name: "Card",
props: ["context"],
setup(n) {
const b = ia(() => import("./chunk.31ac0177.js")), v = ia({ loader: () => import("./chunk.1932f6b1.js"), timeout: 8e3, errorComponent: { render: () => W("p", { role: "alert", style: "padding:24px" }, [W("span", "FastNet 暂时无法打开 / Unable to open FastNet. "), W("a", { href: "/cgi-bin/luci/admin/services/fastnet/open", target: "_blank", rel: "noopener" }, "新窗口打开 / Open in new window ↗")]) } }), e = n, d = e.context, l = d.locale === "en" ? "en" : "zh-cn", a = (i, t) => l === "en" ? t : i, f = xa(d, ma), r = f.state, q = "/cgi-bin/luci/admin/services/fastnet", y = z(() => va(r.summary)), h = z(() => k(r.task)), N = z(() => {
var i, t, p, x, A, P;
return [(p = (t = (i = r.summary) == null ? void 0 : i.latestResults) == null ? void 0 : t.lanDownload) == null ? void 0 : p.measuredAt, (P = (A = (x = r.summary) == null ? void 0 : x.latestResults) == null ? void 0 : A.lanUpload) == null ? void 0 : P.measuredAt].filter(Boolean).sort().pop();
}), S = { preparing: a("准备测速", "Preparing"), ping: a("检测延迟", "Testing latency"), download: a("测试下载", "Testing download"), upload: a("测试上传", "Testing upload"), nat: a("检测 NAT", "Checking NAT"), ipv6: a("检测 IPv6", "Checking IPv6") }, I = z(() => {
var i, t;
return ((i = r.task) == null ? void 0 : i.state) === "cancel_requested" ? a("正在停止", "Stopping") : S[(t = r.task) == null ? void 0 : t.stage] || a("测速中", "Testing");
}), _ = z(() => r.error === "permission" ? a("登录已失效或权限不足,请重新登录", "Session expired or permission denied; sign in again") : r.error === "upgrade" ? a("插件接口不可用,请检查或升级 FastNet", "Plugin API unavailable; check or update FastNet") : r.paused ? a("连接连续失败,已暂停查询;后台任务继续运行", "Queries paused after repeated failures; the background task continues") : a("暂时无法确认结果,保留已有数据", "Result unavailable; existing data retained")), V = z(() => [{ id: "details", label: a("查看上次结果", "Last result details") }, { id: "history", label: a("测速历史", "Test history") }, { id: "reload", label: a("重新读取", "Reload") }, { id: "settings", label: a("插件设置", "Plugin settings") }, { id: "full", label: a("完整 FastNet", "Full FastNet") }]);
function M(i) {
i === "details" ? X() : i === "history" ? T("history") : i === "reload" ? f.reload() : i === "settings" ? window.open(q, "_blank", "noopener") : i === "full" && T();
}
const u = J(!1), m = J(null), g = J(!1);
let R, F, O = !0;
function Q(i) {
var p, x;
const t = (x = (p = r.summary) == null ? void 0 : p.latest) == null ? void 0 : x[i];
return j(i) || (t == null ? void 0 : t.status) === "error" ? "warning" : (t == null ? void 0 : t.status) === "ok" ? "good" : "neutral";
}
function T(i) {
var p, x;
const t = (p = i == null ? void 0 : i.currentTarget) == null ? void 0 : p.closest("details");
t == null || t.removeAttribute("open"), (x = t == null ? void 0 : t.querySelector("summary")) == null || x.focus({ preventScroll: !0 }), u.value = !0, f.visibility(!1), d.openDetails(v, { context: d, locale: l, view: i === "history" ? "history" : "quick" }, { wide: !0, headerAction: { href: q + "/open", label: a("新窗口打开", "Open in new window") }, onClose() {
u.value = !1, f.visibility(!document.hidden && !u.value && O);
} });
}
const j = (i) => {
var t, p, x;
return !h.value && !!((x = (p = (t = r.summary) == null ? void 0 : t.lastTask) == null ? void 0 : p.issues) != null && x[i]);
};
function L(i) {
var x, A;
const t = (A = (x = r.summary) == null ? void 0 : x.latest) == null ? void 0 : A[i];
let p;
return !t || t.status === "not_tested" ? p = a("未检测", "Not tested") : t.status === "error" ? p = a("检测失败", "Probe failed") : t.status === "unavailable" ? p = a("不可用", "Unavailable") : i === "ipv6" ? p = /部分|准备度 [0-9]\/10/.test(t.value) ? a("部分可用", "Partly available") : a("可用", "Available") : p = /port.?restricted/i.test(t.value) ? a("端口受限锥形", "Port Restricted Cone") : /restricted.*cone/i.test(t.value) ? a("受限锥形", "Restricted Cone") : /full.?cone/i.test(t.value) ? a("全锥形", "Full Cone") : /symmetric/i.test(t.value) ? a("对称型", "Symmetric") : t.value, j(i) ? p + " · " + a("本次失败", "latest failed") : p;
}
function X(i) {
var p, x;
const t = (p = i == null ? void 0 : i.currentTarget) == null ? void 0 : p.closest("details");
t == null || t.removeAttribute("open"), (x = t == null ? void 0 : t.querySelector("summary")) == null || x.focus({ preventScroll: !0 }), d.openDetails(b, { state: r, locale: l, stamp: H, mbps: E });
}
function U() {
f.visibility(!document.hidden && !u.value && O);
}
return ua(() => {
R = new ResizeObserver(() => {
var i;
g.value = ((i = m.value) == null ? void 0 : i.clientHeight) < 380;
}), m.value && R.observe(m.value), F = new IntersectionObserver((i) => {
var t;
O = ((t = i[0]) == null ? void 0 : t.isIntersecting) !== !1, U();
}), m.value && F.observe(m.value), document.addEventListener("visibilitychange", U), U();
}), pa(() => {
R == null || R.disconnect(), F == null || F.disconnect(), document.removeEventListener("visibilitychange", U), f.dispose();
}), (i, t) => {
var p, x, A, P, Y, Z, aa, ta, ea, sa, na, ra, da;
return C(), B("article", {
ref_key: "root",
ref: m,
class: G(["qs-card-content", { "qs-card-summary": c(d).form === "summary", "fn-dense": g.value }]),
"data-fastnet-card": "",
"data-task-id": h.value ? c(r).task.id : void 0
}, [
s("header", qa, [
s("h2", null, [
t[4] || (t[4] = s("svg", {
viewBox: "0 0 24 24",
"aria-hidden": "true"
}, [
s("path", { d: "M3 12h4l3-8 4 16 3-8h4" })
], -1)),
w(o(a("外网测速", "Internet speed")), 1)
]),
(p = c(d).components) != null && p.PrimaryAction && ((x = c(d).components) != null && x.Menu) ? (C(), B("div", ha, [
(C(), la(oa(c(d).components.PrimaryAction), {
icon: "activity",
"data-fastnet-test": "",
onClick: T
}, {
default: fa(() => [
w(o(h.value ? a("查看进度", "View progress") : a("测速", "Test")), 1)
]),
_: 1
})),
(C(), la(oa(c(d).components.Menu), {
label: a("外网测速更多操作", "Internet speed actions"),
items: V.value,
onSelect: M
}, null, 40, ["label", "items"]))
])) : (C(), B("div", wa, [
s("button", {
class: "qs-card-primary",
"data-fastnet-test": "",
onClick: T
}, o(h.value ? a("查看进度", "View progress") : a("测速", "Test")), 1),
s("details", ka, [
s("summary", {
"aria-label": a("外网测速更多操作", "Internet speed actions")
}, "⋮", 8, _a),
s("div", null, [
s("button", {
"data-fastnet-details": "",
onClick: X
}, o(a("查看上次结果", "Last result details")), 1),
s("button", {
onClick: t[0] || (t[0] = ($) => T("history"))
}, o(a("测速历史", "Test history")), 1),
s("button", {
onClick: t[1] || (t[1] = ($) => c(f).reload())
}, o(a("重新读取", "Reload")), 1),
s("a", {
href: q,
target: "_blank",
rel: "noopener"
}, o(a("插件设置", "Plugin settings")), 1),
s("button", { onClick: T }, o(a("完整 FastNet", "Full FastNet")), 1)
])
])
]))
]),
s("div", Aa, [
s("div", Ca, [
s("span", null, "WAN · " + o(a("最近有效结果", "LATEST VALID RESULTS")), 1),
s("span", {
class: G(["fn-live", { "is-active": h.value }])
}, o(h.value ? I.value : (A = y.value) != null && A.measuredAt ? a("已保存", "Saved") : a("等待测速", "Ready to test")), 3)
]),
s("div", Na, [
s("div", null, [
s("span", null, "↓ " + o(a("上次下载", "Last download")), 1),
s("strong", null, [
w(o(c(E)((P = y.value) == null ? void 0 : P.downloadBps)), 1),
t[5] || (t[5] = s("small", null, "Mbps", -1))
])
]),
s("div", null, [
s("span", null, "↑ " + o(a("上次上传", "Last upload")), 1),
s("strong", null, [
w(o(c(E)((Y = y.value) == null ? void 0 : Y.uploadBps)), 1),
t[6] || (t[6] = s("small", null, "Mbps", -1))
])
])
]),
s("p", Sa, [
w(o(a("上次测速", "Last tested")) + " ", 1),
s("time", {
datetime: ((Z = y.value) == null ? void 0 : Z.measuredAt) || void 0
}, o((aa = y.value) != null && aa.measuredAt ? c(H)(y.value.measuredAt, c(l)) : a("尚未测速", "No test yet")), 9, Ta)
])
]),
s("section", {
class: "fn-lan-summary",
"aria-label": a("内网测速结果", "LAN speed results")
}, [
s("div", Ba, [
s("span", null, [
t[7] || (t[7] = w("LAN ", -1)),
s("span", Ra, "· " + o(a("浏览器 → 路由器", "Browser → Router")), 1)
]),
s("time", {
datetime: N.value || void 0
}, o(c(H)(N.value, c(l))), 9, Fa)
]),
s("div", Pa, [
s("div", null, [
s("span", Da, o(a("下载", "Download")), 1),
s("strong", null, [
w("↓ " + o(c(E)((sa = (ea = (ta = c(r).summary) == null ? void 0 : ta.latestResults) == null ? void 0 : ea.lanDownload) == null ? void 0 : sa.value)), 1),
t[8] || (t[8] = s("small", null, "Mbps", -1))
])
]),
s("div", null, [
s("span", Ea, o(a("上传", "Upload")), 1),
s("strong", null, [
w("↑ " + o(c(E)((da = (ra = (na = c(r).summary) == null ? void 0 : na.latestResults) == null ? void 0 : ra.lanUpload) == null ? void 0 : da.value)), 1),
t[9] || (t[9] = s("small", null, "Mbps", -1))
])
])
])
], 8, za),
s("div", Ia, [
s("div", {
"data-tone": Q("nat")
}, [
t[10] || (t[10] = s("span", null, [
s("i", { "aria-hidden": "true" }),
w("NAT")
], -1)),
s("strong", {
title: L("nat")
}, o(L("nat")), 9, Ua)
], 8, La),
s("div", {
"data-tone": Q("ipv6")
}, [
t[11] || (t[11] = s("span", null, [
s("i", { "aria-hidden": "true" }),
w("IPv6")
], -1)),
s("strong", {
class: G({ "qs-card-warning": j("ipv6") }),
title: L("ipv6")
}, o(L("ipv6")), 11, Ma)
], 8, Va)
]),
h.value ? (C(), B("div", Oa, [
s("span", null, [
w(o(I.value), 1),
s("small", null, o(a("上次有效结果保持显示", "Previous valid results remain visible")), 1)
]),
s("button", {
disabled: c(r).cancelling || c(r).task.state === "cancel_requested",
onClick: t[2] || (t[2] = ($) => c(f).stop())
}, o(c(r).cancelling || c(r).task.state === "cancel_requested" ? a("正在停止", "Stopping") : a("停止", "Stop")), 9, ja)
])) : ca("", !0),
c(r).error ? (C(), B("p", $a, [
w(o(_.value) + " ", 1),
s("button", {
onClick: t[3] || (t[3] = ($) => c(r).errorAction === "run" ? T() : c(f).reload())
}, o(c(r).paused ? a("恢复查询", "Resume queries") : a("重试", "Retry")), 1)
])) : c(r).summary && c(r).summary.service.state !== "ready" ? (C(), B("p", Wa, [
w(o(c(r).summary.service.state === "disabled" ? a("服务未启用", "Service disabled") : a("服务暂不可用", "Service unavailable")) + " ", 1),
s("a", { href: q }, o(a("打开设置", "Open settings")), 1)
])) : ca("", !0)
], 10, ba);
};
}
};
if (!document.getElementById("fastnet-card-v1-style")) {
const n = document.createElement("style");
n.id = "fastnet-card-v1-style", n.textContent = ga, document.head.appendChild(n);
}
const Ka = 1;
export {
Ka as apiVersion,
Ha as default
};
@@ -0,0 +1,120 @@
var S = (p, d, t) => new Promise((_, o) => {
var u = (i) => {
try {
n(t.next(i));
} catch (a) {
o(a);
}
}, f = (i) => {
try {
n(t.throw(i));
} catch (a) {
o(a);
}
}, n = (i) => i.done ? _(i.value) : Promise.resolve(i.value).then(u, f);
n((t = t.apply(p, d)).next());
});
import { ref as v, computed as B, watch as H, onMounted as L, onUnmounted as O, openBlock as w, createElementBlock as g, createElementVNode as x, createCommentVNode as y, toDisplayString as b } from "/luci-static/quickstart/card-runtime-v1.js";
function R(p, d = location) {
const t = new URL(p);
if (t.protocol !== "http:" || t.hostname !== d.hostname || t.pathname !== "/webui/" || t.username || t.password || t.hash) throw Error("invalid_direct_target");
return { url: t.href, origin: t.origin, mixedContent: d.protocol === "https:" };
}
const j = ".fn-web-dialog{width:100%;min-width:0;min-height:0;display:flex;flex-direction:column;background:var(--qs-card-panel);color:var(--qs-card-text)}.fn-web-frame{position:relative;flex:1;min-height:0}.fn-web-frame iframe{display:block;border:0;width:100%;height:100%;background:var(--qs-card-panel)}.fn-web-loading{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:24px;text-align:center;background:var(--qs-card-panel);color:var(--qs-card-muted)}.fn-web-loading strong{color:var(--qs-card-text);font-size:16px}.fn-web-loading p{font-size:12px;line-height:1.7;max-width:360px;margin:0}.fn-web-loading button{font:inherit;color:var(--qs-card-accent);border:1px solid var(--qs-card-line);background:var(--qs-card-soft);padding:10px 20px;border-radius:8px;cursor:pointer}.fn-web-loading a{color:var(--qs-card-accent);font-size:14px}.fn-web-footnote{font-size:10px;color:var(--qs-card-muted);line-height:1.6;margin:0!important;padding:9px 20px;border-top:1px solid var(--qs-card-line)}@media(max-width:600px){.fn-web-footnote{padding:8px 14px}}", U = {
class: "fn-web-dialog",
"data-fastnet-web-dialog": ""
}, W = { class: "fn-web-frame" }, A = ["src", "title"], D = ["role"], M = ["href"], V = { class: "fn-web-footnote" }, J = {
__name: "WebDialog",
props: ["context", "locale", "view"],
emits: ["close"],
setup(p, { emit: d }) {
if (!document.getElementById("fastnet-web-v1-style")) {
const e = document.createElement("style");
e.id = "fastnet-web-v1-style", e.textContent = j, document.head.appendChild(e);
}
const t = p, _ = d, o = (e, r) => t.locale === "en" ? r : e, u = v(null), f = v(!1), n = v(!1), i = v(0), a = v(null), P = B(() => {
if (!a.value) return "";
const e = new URL(a.value.url);
return e.searchParams.delete("embed"), e.searchParams.delete("theme"), e.href;
});
let c, s, k = !1;
function z() {
clearTimeout(c), c = setTimeout(() => {
f.value || (n.value = !0);
}, 15e3);
}
function T() {
return S(this, null, function* () {
s == null || s.abort(), s = new AbortController();
const e = s;
clearTimeout(c), a.value = null, f.value = !1, n.value = !1, i.value++, z();
try {
const r = yield fetch("/cgi-bin/luci/admin/services/fastnet/embed?format=json&theme=" + t.context.theme.effective + (t.view === "history" ? "&view=history" : ""), { credentials: "same-origin", cache: "no-store", redirect: "error", signal: e.signal });
if (!r.ok) throw Error("launch_unavailable");
const l = R((yield r.json()).url);
if (k || e.signal.aborted) return;
a.value = l, l.mixedContent && clearTimeout(c);
} catch (r) {
!k && !e.signal.aborted && (clearTimeout(c), n.value = !0);
}
});
}
function q() {
var e, r;
a.value && ((r = (e = u.value) == null ? void 0 : e.contentWindow) == null || r.postMessage({ type: "quickstart:theme", theme: t.context.theme.effective }, a.value.origin));
}
function C(e) {
var r, l, h, N, F, E;
if (!(!a.value || e.origin !== a.value.origin || e.source !== ((r = u.value) == null ? void 0 : r.contentWindow))) {
if (((l = e.data) == null ? void 0 : l.type) === "fastnet:ready")
clearTimeout(c), f.value = !0, n.value = !1, q();
else if (((h = e.data) == null ? void 0 : h.type) === "fastnet:close") _("close");
else if (((N = e.data) == null ? void 0 : N.type) === "fastnet:focus") {
const m = (F = u.value) == null ? void 0 : F.closest("section.network-dialog");
(E = (m == null ? void 0 : m.querySelector(e.data.backward ? "[data-network-dialog-close]" : "[data-network-dialog-open]")) || (m == null ? void 0 : m.querySelector("[data-network-dialog-close]"))) == null || E.focus();
}
}
}
return H(() => t.context.theme.effective, q), L(() => {
window.addEventListener("message", C), T();
}), O(() => {
k = !0, s == null || s.abort(), clearTimeout(c), window.removeEventListener("message", C);
}), (e, r) => {
var l, h;
return w(), g("div", U, [
x("div", W, [
a.value && !n.value && !a.value.mixedContent ? (w(), g("iframe", {
key: i.value,
ref_key: "frame",
ref: u,
src: a.value.url,
title: o("FastNet 完整测速界面", "FastNet speed test interface"),
referrerpolicy: "origin"
}, null, 8, A)) : y("", !0),
f.value ? y("", !0) : (w(), g("div", {
key: 1,
class: "fn-web-loading",
role: n.value ? "alert" : "status"
}, [
x("strong", null, b((l = a.value) != null && l.mixedContent ? o("在新窗口中直接测速", "Test directly in a new window") : n.value ? o("FastNet 页面暂时无法加载", "FastNet could not be loaded") : o("正在打开 FastNet…", "Opening FastNet…")), 1),
x("p", null, b((h = a.value) != null && h.mixedContent ? o("当前 HTTPS 页面无法嵌入 HTTP 测速服务,请在新窗口打开 FastNet。", "This HTTPS page cannot embed the HTTP service. Open FastNet in a new window.") : n.value ? o("可以重试,或在新窗口中打开。请确认插件服务已启用。", "Retry or open in a new window. Check that the plugin service is enabled.") : o("打开页面不会自动测速;请在子窗口中点击开始。", "Opening the page does not start a test. Select Start inside the window.")), 1),
a.value && (n.value || a.value.mixedContent) ? (w(), g("a", {
key: 0,
href: P.value,
target: "_blank",
rel: "noopener noreferrer"
}, b(o("打开 FastNet ↗", "Open FastNet ↗")), 9, M)) : y("", !0),
n.value ? (w(), g("button", {
key: 1,
onClick: T
}, b(o("重新加载", "Reload")), 1)) : y("", !0)
], 8, D))
]),
x("p", V, b(o("核心已接受的测速继续运行;关闭窗口将中断浏览器测量,已保存结果保留。", "Accepted core tests continue. Browser tests stop when closed; saved results remain.")), 1)
]);
};
}
};
export {
J as default
};
@@ -0,0 +1,41 @@
import { openBlock as d, createElementBlock as i, createElementVNode as l, toDisplayString as s, Fragment as N, renderList as g, createTextVNode as h, unref as y, createCommentVNode as P } from "/luci-static/quickstart/card-runtime-v1.js";
const k = { class: "qs-card-details" }, D = { key: 0 }, T = {
href: "/cgi-bin/luci/admin/services/fastnet/open",
target: "_blank",
rel: "noopener"
}, x = {
__name: "Details",
props: ["state", "locale", "stamp", "mbps"],
setup(c) {
const o = c, b = o.stamp, w = o.mbps, _ = ["download", "upload", "nat", "ipv6", "lanPing", "lanDownload", "lanUpload"], e = (a, t) => o.locale === "en" ? t : a, f = { download: e("下载", "Download"), upload: e("上传", "Upload"), nat: "NAT", ipv6: "IPv6", lanPing: e("内网延迟", "LAN latency"), lanDownload: e("内网下载", "LAN download"), lanUpload: e("内网上传", "LAN upload") };
function p(a) {
var t, n, r, u;
return ((n = (t = o.state.summary) == null ? void 0 : t.latestResults) == null ? void 0 : n[a]) || ((u = (r = o.state.summary) == null ? void 0 : r.latest) == null ? void 0 : u[a]);
}
function A(a) {
const t = p(a);
return !t || t.status === "not_tested" ? e("未检测", "Not tested") : t.status === "error" ? e("检测失败", "Probe failed") : t.status === "unavailable" ? e("不可用", "Unavailable") : a === "lanPing" ? t.value.toFixed(1) + " ms" : /download|upload/i.test(a) ? w(t.value) + " Mbps" : t.value;
}
return (a, t) => (d(), i("div", k, [
l("p", null, s(e("默认外网出口 · 路由器 → 互联网", "Default WAN route · Router → Internet")), 1),
l("dl", null, [
(d(), i(N, null, g(_, (n) => {
var r, u, m, v;
return d(), i(N, { key: n }, [
l("dt", null, s(f[n]), 1),
l("dd", null, [
h(s(A(n)), 1),
l("small", null, s(y(b)((r = p(n)) == null ? void 0 : r.measuredAt, c.locale)), 1),
(v = (m = (u = c.state.summary) == null ? void 0 : u.lastTask) == null ? void 0 : m.issues) != null && v[n] ? (d(), i("span", D, s(e("本次探测失败,保留上次有效结果", "Latest probe failed; previous valid result retained")), 1)) : P("", !0)
])
], 64);
}), 64))
]),
l("p", null, s(e("测速会使用外网上传和下载带宽。NAT 与 IPv6 分别反映各自检测时间的结果。", "Testing uses WAN upload and download bandwidth. NAT and IPv6 describe their own detection times.")), 1),
l("a", T, s(e("打开完整 FastNet", "Open full FastNet")), 1)
]));
}
};
export {
x as default
};
@@ -0,0 +1,30 @@
{
"schemaVersion": 1,
"abi": "quickstart-card-v1",
"vue": "3.5.44",
"compiler": "3.5.44",
"version": "0.8.9-1",
"sourceCommit": "082bf1e42911b8fdfed7ac421518ee990952b304",
"sourceFiles": {
"quickstart-card/manifest.json": "0f8b3a0dc15803c27243288e97ebea098ba2894c26b836293ed656f9396104d1",
"quickstart-card/package-lock.json": "daaa5d8d53587115f2fb7127adb51cbfaa9c5d55906e598ab643e8b4b0fc3a6d",
"quickstart-card/package.json": "7683ee1fb095bbf9897941bc4bf4796c488545cc9f712a943870ded1cdf7fccb",
"quickstart-card/src/Card.vue": "792c0528eb22ad3e84db8f023b29b430ea5faf8b1638766176bf24ce05aa90f7",
"quickstart-card/src/Details.vue": "a94eb71ec6ac389f4c1d6e5ea82c546ed1be5e31da410a63563c78e8a233407c",
"quickstart-card/src/WebDialog.vue": "9248328cf1e8d2afd671a44ba6340e7d84ef7f32f101461471f9f1d2920517f4",
"quickstart-card/src/directFrame.js": "648cd8ed2f9f2188aee71475df1ee4f936df73fdc7ce3fa7de03f0ae2c8b2f1a",
"quickstart-card/src/index.js": "48c908c983f14c159bf50c1d2ab3c54824f04bc2ecdacc714691164dea974c75",
"quickstart-card/src/model.js": "0497552a2caadd0f3d1333f359cb6704a9e370e68ce71ed80c2d9090857124e3",
"quickstart-card/src/style.css": "818e49ac458ee245b2c27fd7a7d62bd7e2117e44a85bbb388dddd175b05fce66",
"quickstart-card/src/webStyle.css": "7bc8849ff35cce46a1aec88239905f307eb7ebe655d8d19c9c88d854018526b7",
"quickstart-card/vite.config.js": "7dda71bfe6923df40b4142608d38fa239da9e79e0b30ff3cd6d1747c49f657eb",
"scripts/build-quickstart-card.sh": "345645c1513398221c612f6f1c0da77b3e4c958a86a18ef9382236307a55e3e8",
"scripts/card-provenance.py": "2bbed5b4ad40fe94310bc6b9ba6f4d20fc7ed8ec675800b4ebcb5ed68d01a026"
},
"sourceSha256": "ca7ed2ac012210d4be444c080306e27e77c02eab0a998dda7b5f911f712f4385",
"assets": {
"card.dfb0ce55.js": "ed9555d2ead731e603cce340c950c681d8dcb64f301c52ed5380bf8e7cd62664",
"chunk.1932f6b1.js": "af27ba0c26dff540b8fd4cf07eaa50cca447539f7cc3d7d29f3fb3c44bf0ffef",
"chunk.31ac0177.js": "c9d9ebd0ea447c7cee8743a912f63c744ff426a50eb1c5dc8c8321b86103d4f1"
}
}
@@ -1,5 +1,6 @@
'use strict'; 'use strict';
'require baseclass'; 'require baseclass';
'require rpc';
'require ui'; 'require ui';
/* Shared between the Test page's recent-history block and the full History /* Shared between the Test page's recent-history block and the full History
@@ -164,20 +165,54 @@ return baseclass.extend({
/* One token->label table for the schedule intervals: Settings builds /* One token->label table for the schedule intervals: Settings builds
* its choices from it and the Test page looks the status label up, so * its choices from it and the Test page looks the status label up, so
* the two cannot drift. The init script accepts more shapes than these * the two cannot drift. The init script accepts more shapes than these
* six, so readers must fall back to the raw token. */ * seven, so readers must fall back to the raw token. */
INTERVALS: { INTERVALS: {
'15m': _('Every 15 minutes'), '15m': _('Every 15 minutes'),
'30m': _('Every 30 minutes'), '30m': _('Every 30 minutes'),
'1h': _('Hourly'), '1h': _('Hourly'),
'6h': _('Every 6 hours'), '6h': _('Every 6 hours'),
'12h': _('Every 12 hours'), '12h': _('Every 12 hours'),
'1d': _('Daily') '1d': _('Daily'),
'7d': _('Weekly')
}, },
/* Cron's weekday numbers, Monday first; an array keeps that order. */
DAYS: [
[ '1', _('Monday') ], [ '2', _('Tuesday') ], [ '3', _('Wednesday') ],
[ '4', _('Thursday') ], [ '5', _('Friday') ], [ '6', _('Saturday') ],
[ '0', _('Sunday') ]
],
/* The interval and the weekdays as set; a token it does not know shows as it is. */
scheduleLabel(interval, days) {
const every = this.INTERVALS[interval || '1d'] || interval;
const day = d => (this.DAYS.find(x => x[0] == d) || [ d, d ])[1];
if (!days || days == '*')
return every;
return _('%s on %s', 'schedule interval on weekdays').format(every,
String(days).split(',').map(p => p.split('-').map(day).join('–')).join(', '));
},
/* Each interface's link: the name the backend records its results under. */
callLinks: rpc.declare({
object: 'librespeed',
method: 'links',
expect: { '': {} }
}),
/* Exported alongside the chart: every timestamp a page prints should /* Exported alongside the chart: every timestamp a page prints should
* come through here, or the date-only guard gets lost in a copy. */ * come through here, or the date-only guard gets lost in a copy. */
chartStampFull: chartStampFull, chartStampFull: chartStampFull,
/* By epoch: the backend lists runs as recorded, which is out of order
* for a run recorded before NTP set the clock. */
byTime(entries) {
return (Array.isArray(entries) ? entries.slice() : [])
.sort((a, b) => (a.epoch ?? 0) - (b.epoch ?? 0));
},
/* Plain figures of one series: what is normal, how much it wobbles, and /* Plain figures of one series: what is normal, how much it wobbles, and
* where it stands now. The story sentences are built from these. On * where it stands now. The story sentences are built from these. On
* daily aggregates the extremes come from the _min/_max columns the * daily aggregates the extremes come from the _min/_max columns the
@@ -14,6 +14,17 @@
* second fetch, since the entries are in memory anyway. */ * second fetch, since the entries are in memory anyway. */
const pageSize = 50; const pageSize = 50;
/* Entries without an interface; '?' is outside the UCI name alphabet. */
const UNKNOWN = '?';
function ifaceKey(e) {
return e.interface || UNKNOWN;
}
function ifaceLabel(key) {
return (key == UNKNOWN) ? _('unknown') : key;
}
const callConfig = rpc.declare({ const callConfig = rpc.declare({
object: 'librespeed', object: 'librespeed',
method: 'config', method: 'config',
@@ -36,6 +47,7 @@ return view.extend({
range: 86400, range: 86400,
server: '', server: '',
iface: '', iface: '',
def: null,
page: 0, page: 0,
/* Which entries come back -- and at which resolution -- is the server's /* Which entries come back -- and at which resolution -- is the server's
@@ -54,9 +66,9 @@ return view.extend({
? callHistory(now - 2 * this.range, now - this.range).catch(() => ({})) ? callHistory(now - 2 * this.range, now - this.range).catch(() => ({}))
: Promise.resolve({}) : Promise.resolve({})
]).then(L.bind(function(data) { ]).then(L.bind(function(data) {
this.entries = Array.isArray(data[0].entries) ? data[0].entries : []; this.entries = lscommon.byTime(data[0].entries);
this.resolution = data[0].resolution || 'raw'; this.resolution = data[0].resolution || 'raw';
this.prevEntries = Array.isArray(data[1].entries) ? data[1].entries : []; this.prevEntries = lscommon.byTime(data[1].entries);
this.prevResolution = data[1].resolution || 'raw'; this.prevResolution = data[1].resolution || 'raw';
}, this)); }, this));
}, },
@@ -67,32 +79,50 @@ return view.extend({
speed: lscommon.GROUPS.speed.slice(), speed: lscommon.GROUPS.speed.slice(),
latency: lscommon.GROUPS.latency.slice() latency: lscommon.GROUPS.latency.slice()
}; };
/* The config rides along for one purpose: with history keeping off, /* The config rides along for the default interface, and because
* the empty state must not send the user to run a test that will * with history keeping off the empty state must not send the user
* never produce an entry. */ * to run a test that will never produce an entry. */
return Promise.all([ return Promise.all([
this.fetch(), this.fetch(),
callConfig().then(c => { this.config = c; }, () => {}) callConfig().then(c => { this.config = c; }, () => {}),
]); lscommon.callLinks().catch(() => ({}))
]).then(data => {
const def = this.config && this.config.interface;
this.def = (data[2].interfaces || {})[def] || def;
});
}, },
/* The server/interface filters narrow the fetched range on the client; /* The server/interface filters narrow the fetched range on the client;
* daily aggregates carry neither field, so there the filters offer only * daily aggregates carry no server, so there that filter offers only
* "All" and match everything. */ * "All", which matches everything. */
applyFilters(entries) { applyFilters(entries) {
return (entries || []).filter(e => return (entries || []).filter(e =>
(!this.server || (e.server && e.server.name) == this.server) && (!this.server || (e.server && e.server.name) == this.server) &&
(!this.iface || e.interface == this.iface)); ifaceKey(e) == this.iface);
},
/* The default interface first, then by name, unknown last. */
ifaceKeys(entries) {
const rank = k => (k == this.def) ? 0 : ((k == UNKNOWN) ? 2 : 1),
keys = [];
entries.forEach(e => {
if (keys.indexOf(ifaceKey(e)) < 0)
keys.push(ifaceKey(e));
});
return keys.sort((a, b) => rank(a) - rank(b) || L.naturalCompare(a, b));
}, },
visible() { visible() {
return this.applyFilters(this.entries); return this.applyFilters(this.entries);
}, },
filterSelect(title, values, current, onpick) { filterSelect(title, values, current, onpick, all, label) {
const sel = E('select', { 'class': 'cbi-input-select' }, const sel = E('select', { 'class': 'cbi-input-select' },
[ E('option', { 'value': '' }, [ _('All') ]) ].concat( (all ? [ E('option', { 'value': '' }, [ _('All') ]) ] : []).concat(
values.map(v => E('option', { 'value': v }, [ v ])))); values.map(v => E('option', { 'value': v }, [ label ? label(v) : v ]))));
sel.value = values.indexOf(current) >= 0 ? current : ''; sel.value = values.indexOf(current) >= 0 ? current : '';
sel.addEventListener('change', ui.createHandlerFn(this, function() { sel.addEventListener('change', ui.createHandlerFn(this, function() {
@@ -248,6 +278,10 @@ return view.extend({
this.chartNode.appendChild(E('p', { 'class': 'librespeed-muted' }, this.chartNode.appendChild(E('p', { 'class': 'librespeed-muted' },
[ _('Daily minimum, average and maximum.') ])); [ _('Daily minimum, average and maximum.') ]));
if (this.iface == UNKNOWN)
this.chartNode.appendChild(E('p', { 'class': 'librespeed-muted' },
[ _('These results name no interface: days archived before results were kept per interface, which mix all links.') ]));
/* The sort key carries the same decimal count as the display half: /* The sort key carries the same decimal count as the display half:
* ui.Table stringifies the whole cell and compares digit runs one by * ui.Table stringifies the whole cell and compares digit runs one by
* one, so ragged fractions would put 94.4 above 94.35. */ * one, so ragged fractions would put 94.4 above 94.35. */
@@ -274,7 +308,6 @@ return view.extend({
let rows = entries.slice().reverse().map(e => [ let rows = entries.slice().reverse().map(e => [
[ e.epoch ?? 0, cell(when(e)) ], [ e.epoch ?? 0, cell(when(e)) ],
cell((e.server && e.server.name) || '–'), cell((e.server && e.server.name) || '–'),
cell(e.interface || '–'),
cell(protoCell(e)), cell(protoCell(e)),
[ num(e.download_mbps, 2), cell(fmtNum(e.download_mbps, 2)) ], [ num(e.download_mbps, 2), cell(fmtNum(e.download_mbps, 2)) ],
[ num(e.upload_mbps, 2), cell(fmtNum(e.upload_mbps, 2)) ], [ num(e.upload_mbps, 2), cell(fmtNum(e.upload_mbps, 2)) ],
@@ -351,7 +384,7 @@ return view.extend({
* shows a locale string, and numbers order numerically. The table is * shows a locale string, and numbers order numerically. The table is
* where sorting belongs; the chart above never reorders time. */ * where sorting belongs; the chart above never reorders time. */
this.table = new ui.Table([ this.table = new ui.Table([
_('Time'), _('Server'), _('Interface'), _('Protocol'), _('Time'), _('Server'), _('Protocol'),
_('Download [Mbps]'), _('Upload [Mbps]'), _('Ping [ms]'), _('Jitter [ms]') _('Download [Mbps]'), _('Upload [Mbps]'), _('Ping [ms]'), _('Jitter [ms]')
], { id: 'librespeed-history' }); ], { id: 'librespeed-history' });
this.tableNode = this.table.render(); this.tableNode = this.table.render();
@@ -383,32 +416,30 @@ return view.extend({
ranges.classList.add('librespeed-push'); ranges.classList.add('librespeed-push');
/* Filter choices are whatever the fetched range actually contains. */ /* Filter choices are whatever the fetched range actually contains. */
const servers = [], ifaces = []; const servers = [], ifaces = this.ifaceKeys(this.entries);
this.entries.forEach(e => { this.entries.forEach(e => {
const s = e.server && e.server.name; const s = e.server && e.server.name;
if (s && servers.indexOf(s) < 0) if (s && servers.indexOf(s) < 0)
servers.push(s); servers.push(s);
if (e.interface && ifaces.indexOf(e.interface) < 0)
ifaces.push(e.interface);
}); });
/* The freshly fetched window may no longer contain the chosen /* The freshly fetched window may no longer contain the chosen
* server or interface -- daily aggregates carry neither field at * server or interface -- daily aggregates may carry neither field at
* all. The widget would then quietly repaint as "All" while the * all. The widget would then quietly repaint as "All" while the
* model kept filtering everything out, with no control on screen * model kept filtering everything out, with no control on screen
* able to clear it; reconcile the model here, where the choice * able to clear it; reconcile the model here, where the choice
* lists are built. */ * lists are built. */
if (this.server && servers.indexOf(this.server) < 0) if (this.server && servers.indexOf(this.server) < 0)
this.server = ''; this.server = '';
if (this.iface && ifaces.indexOf(this.iface) < 0) if (ifaces.indexOf(this.iface) < 0)
this.iface = ''; this.iface = ifaces[0];
const filters = E('div', { 'class': 'librespeed-toolbar' }, [ const filters = E('div', { 'class': 'librespeed-toolbar' }, [
this.filterSelect(_('Server'), servers.sort(), this.server, this.filterSelect(_('Server'), servers.sort(), this.server,
function(v) { this.server = v; this.page = 0; this.redraw(); }), function(v) { this.server = v; this.page = 0; this.redraw(); }, true),
this.filterSelect(_('Interface'), ifaces.sort(), this.iface, ifaces.length ? this.filterSelect(_('Interface'), ifaces, this.iface,
function(v) { this.iface = v; this.page = 0; this.redraw(); }) function(v) { this.iface = v; this.page = 0; this.redraw(); }, false, ifaceLabel) : ''
]); ]);
this.controls.innerHTML = ''; this.controls.innerHTML = '';
@@ -2,31 +2,60 @@
'require view'; 'require view';
'require form'; 'require form';
'require rpc'; 'require rpc';
'require tools.widgets as widgets'; 'require uci';
'require librespeed.common as lscommon'; 'require librespeed.common as lscommon';
/* global lscommon */
const callConfig = rpc.declare({ const callConfig = rpc.declare({
object: 'librespeed', object: 'librespeed',
method: 'config', method: 'config',
expect: { '': {} } expect: { '': {} }
}); });
/* The intervals the init script can put in cron; it leaves out any other. */
const INTERVAL_RE = /^(?:(?:[1-9]|[1-5][0-9])m|(?:[1-9]|1[0-9]|2[0-3])h|1d|7d)$/;
return view.extend({ return view.extend({
load() { load() {
return callConfig().catch(() => ({})); return Promise.all([
callConfig().catch(() => ({})),
lscommon.callLinks().catch(() => ({})),
uci.load('librespeed')
]);
}, },
render(config) { render(data) {
const config = data[0],
links = data[1].links || [],
ifmap = data[1].interfaces || {},
linkOf = n => ifmap[n] || n;
let m, s, o; let m, s, o;
/* Links, plus stored names that are not links: a save drops what is not offered. */
const offer = (opt, stored) => {
const label = n => {
if (links.indexOf(ifmap[n]) >= 0)
return _('%s (recorded as %s)').format(n, ifmap[n]);
if (ifmap[n])
return _('%s (no gateway)').format(n);
return Object.keys(ifmap).length ? _('%s (not found)').format(n) : n;
};
links.forEach(n => opt.value(n));
stored.filter((n, i, a) => n && links.indexOf(n) < 0 && a.indexOf(n) == i)
.forEach(n => opt.value(n, label(n)));
};
m = new form.Map('librespeed', _('LibreSpeed – Settings')); m = new form.Map('librespeed', _('LibreSpeed – Settings'));
s = m.section(form.NamedSection, 'main', 'librespeed', _('Measurement')); s = m.section(form.NamedSection, 'main', 'librespeed', _('Measurement'));
o = s.option(widgets.NetworkSelect, 'interface', _('Interface'), o = s.option(form.ListValue, 'interface', _('Interface'),
_('Logical interface the measurement is bound to.')); _('Logical interface measured by default: by the Test page unless another one is chosen there, and by an automatic test that names no interface.'));
o.default = 'wan'; o.default = 'wan';
o.nocreate = true; offer(o, [ uci.get('librespeed', 'main', 'interface') || 'wan' ]);
const mainIface = o;
o = s.option(form.Value, 'server', _('Server'), o = s.option(form.Value, 'server', _('Server'),
_("Numeric server id from the LibreSpeed server list, or 'auto' to pick the closest.")); _("Numeric server id from the LibreSpeed server list, or 'auto' to pick the closest."));
@@ -54,34 +83,97 @@ return view.extend({
o.value('http', _('force HTTP')); o.value('http', _('force HTTP'));
o.default = 'auto'; o.default = 'auto';
s = m.section(form.NamedSection, 'schedule', 'librespeed', _('Scheduled measurements')); /* The help sits above the table, as a phone hides the column headings. */
s = m.section(form.TableSection, 'schedule', _('Scheduled measurements'), [
[ _('Enable'), _('Runs a measurement from cron at the chosen interval. Note that a measurement saturates the connection while it runs.') ],
[ _('Days'), _('Leave empty to run every day. A weekly test runs on one of the chosen days, or on any day when none is chosen; the day is drawn once and kept while it stays among the chosen days.') ],
[ _('Hours'), _('An hour window on the 24-hour clock, such as 2-5 for 02:00–05:59. A daily or weekly measurement runs at a random time inside it, drawn when the schedule is applied; shorter intervals only run within it. Leave empty for any time. A window across midnight is not supported.') ]
].map(h => E('p', {}, [ '%s: %s'.format(h[0], h[1]) ])));
s.anonymous = true;
s.addremove = true;
/* A new row gets the night window of the shipped first row. */
s.handleAdd = function(ev, name) {
const sid = this.map.data.add('librespeed', 'schedule', name);
o = s.option(form.Flag, 'enabled', _('Enable'), this.map.data.set('librespeed', sid, 'hours', '2-5');
_('Runs a measurement from cron at the chosen interval. Note that a measurement saturates the connection while it runs.'));
return this.map.save(null, true);
};
/* The legacy named section first, as the init script reads it first. */
s.cfgsections = function() {
const legacy = (uci.get('librespeed', 'schedule') || {})['.type'] == 'librespeed';
return (legacy ? [ 'schedule' ] : []).concat(
uci.sections('librespeed', 'schedule').map(x => x['.name']));
};
const rows = s.cfgsections();
o = s.option(form.ListValue, 'interface', _('Interface'));
o.optional = true;
o.placeholder = _('Default interface');
offer(o, rows.map(sid => uci.get('librespeed', sid, 'interface')));
/* Only enabled tests reach the crontab, one per link. The legacy row
* without an interface measures the default interface chosen above. */
const measured = (sid, v) => linkOf(v || (sid == 'schedule' ? mainIface.formvalue('main') : ''));
o.validate = function(section_id, value) {
if (!value && section_id != 'schedule')
return _('Choose the interface this test measures.');
if (enabled.formvalue(section_id) != '1')
return true;
const name = measured(section_id, value);
const taken = this.section.cfgsections().some(sid => sid != section_id &&
enabled.formvalue(sid) == '1' && measured(sid, this.formvalue(sid) ?? this.cfgvalue(sid)) == name);
return !taken || _('Another enabled automatic test already measures %s.').format(name);
};
o = s.option(form.Flag, 'enabled', _('Enable'));
const enabled = o;
o = s.option(form.ListValue, 'interval', _('Interval')); o = s.option(form.ListValue, 'interval', _('Interval'));
/* From the shared table, so the Test page's status label and these /* From the shared table, so the Test page's status label and these
* choices cannot drift apart. */ * choices cannot drift apart. */
Object.keys(lscommon.INTERVALS).forEach(k => Object.keys(lscommon.INTERVALS).forEach(k =>
o.value(k, lscommon.INTERVALS[k])); o.value(k, lscommon.INTERVALS[k]));
/* A hand-set interval is offered as it is, or a save would replace it. */
rows.map(sid => uci.get('librespeed', sid, 'interval'))
.filter((v, i, a) => v && !lscommon.INTERVALS[v] && a.indexOf(v) == i)
.forEach(v => o.value(v));
o.default = '1d'; o.default = '1d';
o.depends('enabled', '1'); o.depends('enabled', '1');
o.retain = true;
/* Without a width the table squeezes the column and cuts the labels. */
o.width = '13em';
o.validate = function(section_id, value) {
return INTERVAL_RE.test(value) ||
_('The interval %s is not supported. Use 1-59m, 1-23h, 1d or 7d.').format(value);
};
o = s.option(form.MultiValue, 'days', _('Days'), o = s.option(form.MultiValue, 'days', _('Days'));
_('Leave empty to run every day.')); lscommon.DAYS.forEach(d => o.value(d[0], d[1]));
o.value('1', _('Monday'));
o.value('2', _('Tuesday'));
o.value('3', _('Wednesday'));
o.value('4', _('Thursday'));
o.value('5', _('Friday'));
o.value('6', _('Saturday'));
o.value('0', _('Sunday'));
o.optional = true; o.optional = true;
o.depends('enabled', '1'); o.depends('enabled', '1');
o.retain = true;
/* The init script hands this straight to cron, which wants commas. */ /* The init script hands this straight to cron, which wants commas. */
o.cfgvalue = function(section_id) { o.cfgvalue = function(section_id) {
const v = form.MultiValue.prototype.cfgvalue.apply(this, arguments); const v = form.MultiValue.prototype.cfgvalue.apply(this, arguments);
return (v == null || v == '*') ? [] : String(v).split(','); const on = {};
if (v == null || v == '*')
return [];
/* A hand-set range (1-5) as its days, so an untouched save keeps it. */
String(v).split(',').forEach(p => {
const r = p.match(/^([0-6])(?:-([0-6]))?$/);
if (r)
for (let d = +r[1]; d <= +(r[2] ?? r[1]); d++)
on[d] = true;
});
return lscommon.DAYS.map(d => d[0]).filter(d => on[d]);
}; };
o.write = function(section_id, value) { o.write = function(section_id, value) {
const list = Array.isArray(value) ? value.filter(v => v !== '') : []; const list = Array.isArray(value) ? value.filter(v => v !== '') : [];
@@ -90,11 +182,11 @@ return view.extend({
return this.super('write', [ section_id, list.join(',') ]); return this.super('write', [ section_id, list.join(',') ]);
}; };
o = s.option(form.Value, 'hours', _('Hours'), o = s.option(form.Value, 'hours', _('Hours'));
_('An hour window on the 24-hour clock, such as 2-5 for 02:00–05:59. A daily measurement runs at a random time inside it, drawn when the schedule is applied; shorter intervals only run within it. Leave empty for any time. A window across midnight is not supported.'));
o.placeholder = '2-5'; o.placeholder = '2-5';
o.optional = true; o.optional = true;
o.depends('enabled', '1'); o.depends('enabled', '1');
o.retain = true;
o.validate = function(section_id, value) { o.validate = function(section_id, value) {
if (value == '') if (value == '')
return true; return true;
@@ -138,22 +230,25 @@ return view.extend({
o.depends('enabled', '1'); o.depends('enabled', '1');
return m.render().then(node => { return m.render().then(node => {
const cron = config && config.schedule && config.schedule.cron; const scheds = config.schedules || [];
const box = E('div', { 'style': 'margin-top:1em' }); const box = E('div', { 'style': 'margin-top:1em' });
if (cron) { if (scheds.length) {
/* Epochs computed by the backend in the router's timezone. */ /* Epochs computed by the backend in the router's timezone. */
const runs = (config && config.schedule && config.schedule.next_runs || [])
.map(e => new Date(e * 1000));
box.appendChild(E('h4', {}, [ _('Upcoming measurements') ])); box.appendChild(E('h4', {}, [ _('Upcoming measurements') ]));
box.appendChild(E('table', { 'class': 'table', 'style': 'max-width:24em' }, box.appendChild(E('table', { 'class': 'table', 'style': 'max-width:32em' },
runs.map(d => E('tr', { 'class': 'tr' }, [ scheds.flatMap(sc => (sc.next_runs || []).map(e => {
E('td', { 'class': 'td' }, [ d.toLocaleDateString() ]), const d = new Date(e * 1000);
E('td', { 'class': 'td' }, [ d.toLocaleTimeString() ])
])))); return E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, [ linkOf(sc.interface) ]),
E('td', { 'class': 'td' }, [ d.toLocaleDateString(undefined,
{ weekday: 'short', year: 'numeric', month: 'numeric', day: 'numeric' }) ]),
E('td', { 'class': 'td' }, [ d.toLocaleTimeString() ])
]);
}))));
box.appendChild(E('p', { 'style': 'color:#888' }, [ box.appendChild(E('p', { 'style': 'color:#888' }, [
_('A daily measurement runs at a time drawn when the schedule is applied; saving draws it anew.') _('The time of a daily measurement is drawn anew whenever the schedule is applied. A weekly measurement keeps its drawn day and time while they fit the chosen days and hours.')
])); ]));
} }
else { else {
@@ -12,6 +12,9 @@
const callStart = rpc.declare({ const callStart = rpc.declare({
object: 'librespeed', object: 'librespeed',
method: 'start', method: 'start',
params: [ 'interface' ],
/* A ubus error must not read as a start. */
reject: true,
expect: { '': {} } expect: { '': {} }
}); });
@@ -201,6 +204,7 @@ return view.extend({
button: null, button: null,
lastSeen: null, lastSeen: null,
config: {}, config: {},
ifmap: {},
load() { load() {
return Promise.all([ return Promise.all([
@@ -208,23 +212,27 @@ return view.extend({
callResult().catch(() => ({})), callResult().catch(() => ({})),
callConfig().catch(() => ({})), callConfig().catch(() => ({})),
callHistory(Math.floor(Date.now() / 1000 - recentSeconds), callHistory(Math.floor(Date.now() / 1000 - recentSeconds),
undefined, 0).catch(() => ({})) undefined, 0).catch(() => ({})),
lscommon.callLinks().catch(() => ({}))
]); ]);
}, },
renderRecent(data) { renderRecent(data) {
const entries = Array.isArray(data && data.entries) ? data.entries : []; /* One interface only: an average over WAN and LTE describes neither. */
const all = lscommon.byTime(data && data.entries);
const entries = all.filter(e => e.interface == this.iface);
/* Kept so switching the metric can redraw without refetching. */ /* Kept so switching the metric can redraw without refetching. */
this.recentData = data; this.recentData = data;
this.recentNode.innerHTML = ''; this.recentNode.innerHTML = '';
this.recentSubtitle.textContent = '%s · %s'.format(_('last 24 hours'), this.iface);
this.recentCount.textContent = entries.length this.recentCount.textContent = entries.length
? N_(entries.length, '%d measurement', '%d measurements') ? N_(entries.length, '%d measurement', '%d measurements')
.format(entries.length) : ''; .format(entries.length) : '';
/* The active button names the metric, so the subtitle only carries /* The active button names the metric, so the subtitle only carries
* the window. */ * the window and the interface. */
this.recentSwitch.replaceChildren(...lscommon.switcher(this, this.recentSwitch.replaceChildren(...lscommon.switcher(this,
lscommon.GROUPS.speed.map(k => { lscommon.GROUPS.speed.map(k => {
const m = lscommon.METRICS.find(x => x[0] == k); const m = lscommon.METRICS.find(x => x[0] == k);
@@ -277,6 +285,17 @@ return view.extend({
if (!drew) { if (!drew) {
this.recentNode.appendChild(E('p', { 'class': 'librespeed-muted' }, this.recentNode.appendChild(E('p', { 'class': 'librespeed-muted' },
[ _('No data in the last 24 hours.') ])); [ _('No data in the last 24 hours.') ]));
const others = all.length - entries.length;
if (!entries.length && others > 0)
this.recentNode.appendChild(E('p', { 'class': 'librespeed-muted' }, [
N_(others, '%d measurement of another interface is in the full history.',
'%d measurements of other interfaces are in the full history.').format(others),
' ',
E('a', { 'href': L.url('admin', 'network', 'librespeed', 'history') },
[ _('View full history »') ])
]));
return; return;
} }
@@ -328,19 +347,20 @@ return view.extend({
}, },
handleStart(ev) { handleStart(ev) {
return callStart().then(L.bind(function(res) { /* A raised RPC error carries LuCI's stack trace after its first line. */
if (res && res.error) { const fail = msg => ui.addNotification(null, E('p', [
ui.addNotification(null, E('p', [ _('Could not start the measurement: %s').format(String(msg).split('\n')[0])
_('Could not start the measurement: %s').format(res.error) ]));
]));
return; return callStart(this.iface).then(L.bind(function(res) {
} if (res && res.error)
return fail(res.error);
/* Show the running state immediately rather than waiting up to /* Show the running state immediately rather than waiting up to
* pollInterval for the next status. */ * pollInterval for the next status. */
this.renderStatus({ running: true, started: Date.now() / 1000 }); this.renderStatus({ running: true, started: Date.now() / 1000 });
this.setBusy(true); this.setBusy(true);
}, this)); }, this), err => fail(err.message));
}, },
handleStop(ev) { handleStop(ev) {
@@ -360,13 +380,18 @@ return view.extend({
running ? 'handleStop' : 'handleStart'); running ? 'handleStop' : 'handleStart');
}, },
runContext() { linkOf(name) {
return this.ifmap[name] || name;
},
runContext(status) {
const parts = []; const parts = [];
if (this.config.server && this.config.server != 'auto') if (this.config.server && this.config.server != 'auto')
parts.push(_('server %s').format(this.config.server)); parts.push(_('server %s').format(this.config.server));
if (this.config.interface) /* As the backend names it: a cron run may measure another interface. */
parts.push(this.config.interface); if (status.interface)
parts.push(status.interface);
return parts.join(' · '); return parts.join(' · ');
}, },
@@ -462,7 +487,7 @@ return view.extend({
rows.push(E('div', { 'class': 'librespeed-muted' }, rows.push(E('div', { 'class': 'librespeed-muted' },
[ _('%s elapsed').format(elapsed) ])); [ _('%s elapsed').format(elapsed) ]));
const ctx = this.runContext(); const ctx = this.runContext(status);
if (ctx) if (ctx)
rows.push(E('div', { 'class': 'librespeed-muted', 'style': 'margin-top:.5em' }, [ ctx ])); rows.push(E('div', { 'class': 'librespeed-muted', 'style': 'margin-top:.5em' }, [ ctx ]));
@@ -480,19 +505,21 @@ return view.extend({
status.last_finished ? ' · ' + fmtTime(status.last_finished) : '' status.last_finished ? ' · ' + fmtTime(status.last_finished) : ''
])); ]));
} }
else if (!status.running && status.last_error) {
/* One per interface, kept until a run of it succeeds. */
(status.running ? [] : status.failures || []).forEach(f => {
/* Compact, and above the figures: the failure is news, the last /* Compact, and above the figures: the failure is news, the last
* good result is still the substance of the page. */ * good result is still the substance of the page. */
this.alertNode.appendChild(E('div', { this.alertNode.appendChild(E('div', {}, [ E('div', {
'class': 'alert-message warning', 'class': 'alert-message warning',
'style': 'display:inline-block; text-align:left' 'style': 'display:inline-block; text-align:left'
}, [ }, [
E('strong', {}, [ _('Last measurement failed') ]), E('strong', {}, [ _('Last measurement of %s failed').format(this.linkOf(f.interface)) ]),
E('br'), E('br'),
status.last_error, f.error,
status.last_finished ? ' · ' + fmtTime(status.last_finished) : '' f.finished ? ' · ' + fmtTime(f.finished) : ''
])); ]) ]));
} });
}, },
renderResult(result) { renderResult(result) {
@@ -586,9 +613,12 @@ return view.extend({
const status = data[0] || {}, const status = data[0] || {},
result = data[1] || {}, result = data[1] || {},
config = data[2] || {}, config = data[2] || {},
recent = data[3] || {}; recent = data[3] || {},
links = data[4] || {};
this.config = config; this.config = config;
this.ifmap = links.interfaces || {};
this.iface = this.linkOf(config.interface || 'wan');
this.alertNode = E('div', {}); this.alertNode = E('div', {});
this.statusNode = E('div', {}); this.statusNode = E('div', {});
this.resultHeading = E('div', { 'class': 'librespeed-muted', 'style': 'margin-top:.35em' }); this.resultHeading = E('div', { 'class': 'librespeed-muted', 'style': 'margin-top:.35em' });
@@ -600,8 +630,7 @@ return view.extend({
'class': 'librespeed-visually-hidden' 'class': 'librespeed-visually-hidden'
}); });
this.recentCount = E('span', { 'class': 'librespeed-muted' }); this.recentCount = E('span', { 'class': 'librespeed-muted' });
this.recentSubtitle = E('div', { 'class': 'librespeed-muted' }, this.recentSubtitle = E('div', { 'class': 'librespeed-muted' });
[ _('last 24 hours') ]);
/* Built once and refilled: ui.Table gives sortable headers, the same /* Built once and refilled: ui.Table gives sortable headers, the same
* as the History page's table. */ * as the History page's table. */
this.recentTable = new ui.Table([ this.recentTable = new ui.Table([
@@ -618,6 +647,28 @@ return view.extend({
this.button = E('button', { 'class': 'cbi-button cbi-button-action' }, this.button = E('button', { 'class': 'cbi-button cbi-button-action' },
[ _('Start test') ]); [ _('Start test') ]);
/* The backend's links, or the default without any; the choice lasts
* for this page only. A default that is not a link is not chosen. */
const ifaces = (links.links || []).slice();
let note = '';
if (!ifaces.length)
ifaces.push(this.iface);
else if (ifaces.indexOf(this.iface) < 0) {
note = _('The default interface %s is not available.').format(config.interface || 'wan');
this.iface = ifaces[0];
}
const ifaceSelect = E('select', {
'class': 'cbi-input-select',
'change': ev => {
this.iface = ev.target.value;
this.renderRecent(this.recentData);
}
}, ifaces.map(n => E('option', { 'value': n }, [ n ])));
ifaceSelect.value = this.iface;
this.lastSeen = status.last_finished; this.lastSeen = status.last_finished;
this.renderStatus(status); this.renderStatus(status);
@@ -668,20 +719,17 @@ return view.extend({
/* Computed by the backend in the router's timezone; the browser may /* Computed by the backend in the router's timezone; the browser may
* well sit in another one, so it only formats the epoch. */ * well sit in another one, so it only formats the epoch. */
const sched = config.schedule || {}; const schedRows = (config.schedules || []).map(sc => {
const next = sched.next_runs || []; const every = lscommon.scheduleLabel(sc.interval, sc.days),
/* Strict, matching history.js: the backend derives this from the next = (sc.next_runs || [])[0];
* crontab and emits a real boolean, never UCI's '0'/'1'. */
const schedRows = [ [ _('Enabled'), sched.enabled === true ? _('Yes') : _('No') ] ];
if (sched.enabled === true) { return [ this.linkOf(sc.interface), next
/* The shared table translates the six tokens the UI offers; the ? '%s · %s'.format(every, new Date(next * 1000).toLocaleString())
* init script accepts more, so the raw token is the fallback. */ : every ];
schedRows.push([ _('Interval'), });
lscommon.INTERVALS[sched.interval || '1d'] || sched.interval ]);
if (next.length) if (!schedRows.length)
schedRows.push([ _('Next run'), new Date(next[0] * 1000).toLocaleString() ]); schedRows.push([ _('Enabled'), _('No') ]);
}
/* The main card carries the result; the aside carries what the next /* The main card carries the result; the aside carries what the next
* run will do. Plain sections and tables, so every theme renders it. */ * run will do. Plain sections and tables, so every theme renders it. */
@@ -689,7 +737,6 @@ return view.extend({
E('div', { 'class': 'cbi-section', 'style': 'margin:0 0 1em 0' }, [ E('div', { 'class': 'cbi-section', 'style': 'margin:0 0 1em 0' }, [
E('h3', [ _('Test configuration') ]), E('h3', [ _('Test configuration') ]),
kv([ kv([
[ _('Interface'), config.interface || 'wan' ],
[ _('Server'), (config.server == 'auto' || !config.server) [ _('Server'), (config.server == 'auto' || !config.server)
? _('automatic (nearest)') : config.server ], ? _('automatic (nearest)') : config.server ],
[ _('Protocol'), [ _('Protocol'),
@@ -715,7 +762,17 @@ return view.extend({
this.statusNode, this.statusNode,
this.resultHeading, this.resultHeading,
this.resultNode, this.resultNode,
E('div', { 'style': 'margin-top:1em' }, [ this.button ]) E('div', {
'class': 'librespeed-toolbar',
'style': 'justify-content:center; margin-top:1em'
}, [
E('label', {}, [
E('span', { 'class': 'librespeed-muted' }, [ _('Interface') ]),
' ', ifaceSelect
]),
this.button
]),
note ? E('p', { 'class': 'librespeed-muted', 'style': 'margin:.5em 0 0' }, [ note ]) : ''
]); ]);
const recentSection = E('div', { 'class': 'cbi-section', 'style': 'margin:1.5em 0 0 0' }, [ const recentSection = E('div', { 'class': 'cbi-section', 'style': 'margin:1.5em 0 0 0' }, [
+249 -191
View File
@@ -1,168 +1,199 @@
msgid "" msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8" msgstr "Content-Type: text/plain; charset=UTF-8"
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:315 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:348
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:223 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:231
msgid "%d measurement" msgid "%d measurement"
msgid_plural "%d measurements" msgid_plural "%d measurements"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:463 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:293
msgid "%d measurement of another interface is in the full history."
msgid_plural "%d measurements of other interfaces are in the full history."
msgstr[0] ""
msgstr[1] ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:41
msgid "%s (no gateway)"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:42
msgid "%s (not found)"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:39
msgid "%s (recorded as %s)"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:488
msgid "%s elapsed" msgid "%s elapsed"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:123 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:194
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:135 msgctxt "schedule interval on weekdays"
msgid "%s on %s"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:215
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:227
msgid "1 year" msgid "1 year"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:30 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:31
msgid "1y" msgid "1y"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:136 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:228
msgid "2 years" msgid "2 years"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:27 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:28
msgid "24h" msgid "24h"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:121 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:213
msgid "30 days" msgid "30 days"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:29 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:30
msgid "30d" msgid "30d"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:120 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:212
msgid "7 days" msgid "7 days"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:28 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:29
msgid "7d" msgid "7d"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:122 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:214
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:134 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:226
msgid "90 days" msgid "90 days"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:156 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:32
msgid "" #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:124
"A daily measurement runs at a time drawn when the schedule is applied; "
"saving draws it anew."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:31
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:94
msgid "All" msgid "All"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:94 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:90
msgid "" msgid ""
"An hour window on the 24-hour clock, such as 2-5 for 02:00–05:59. A daily " "An hour window on the 24-hour clock, such as 2-5 for 02:00–05:59. A daily or "
"measurement runs at a random time inside it, drawn when the schedule is " "weekly measurement runs at a random time inside it, drawn when the schedule "
"applied; shorter intervals only run within it. Leave empty for any time. A " "is applied; shorter intervals only run within it. Leave empty for any time. "
"window across midnight is not supported." "A window across midnight is not supported."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:127 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:129
msgid "Another enabled automatic test already measures %s."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:219
msgid "Archive path" msgid "Archive path"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:133 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:225
msgid "Archive retention" msgid "Archive retention"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:562 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:120
msgid "Choose the interface this test measures."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:589
msgid "Completed" msgid "Completed"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:128 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:220
msgid "" msgid ""
"Completed days are reduced to daily minimum, average and maximum and " "Completed days are reduced to daily minimum, average and maximum and "
"appended here once a day, so measurements since the last flush may be lost " "appended here once a day, so measurements since the last flush may be lost "
"after an unexpected power loss. Leave empty to keep no persistent history." "after an unexpected power loss. Leave empty to keep no persistent history."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:389 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:414
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:426 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:451
msgid "Connecting to the test server…" msgid "Connecting to the test server…"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:334 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:352
msgid "Could not start the measurement: %s" msgid "Could not start the measurement: %s"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:174 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:175
msgid "Daily" msgid "Daily"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:249 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:279
msgid "Daily minimum, average and maximum." msgid "Daily minimum, average and maximum."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:70 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:89
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:154
msgid "Days" msgid "Days"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:252 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:260
msgid "Declining — the last measurement is %d%% below the 24-hour average." msgid "Declining — the last measurement is %d%% below the 24-hour average."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:11 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:113
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:92 msgid "Default interface"
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:532 msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:12
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:95
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:559
msgid "Download" msgid "Download"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:388
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:638
msgid "Download [Mbps]" msgid "Download [Mbps]"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:59 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:88
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:132
msgid "Enable" msgid "Enable"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:732
msgid "Enabled" msgid "Enabled"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:702 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:749
msgid "" msgid ""
"Encrypted transfers, which on hardware without AES acceleration may bound " "Encrypted transfers, which on hardware without AES acceleration may bound "
"the result." "the result."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:173 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:174
msgid "Every 12 hours" msgid "Every 12 hours"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:169 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:170
msgid "Every 15 minutes" msgid "Every 15 minutes"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:170 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:171
msgid "Every 30 minutes" msgid "Every 30 minutes"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:172 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:173
msgid "Every 6 hours" msgid "Every 6 hours"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:443 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:474
msgid "Export CSV" msgid "Export CSV"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:446 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:477
msgid "Export JSON" msgid "Export JSON"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:76 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:182
msgid "Friday" msgid "Friday"
msgstr "" msgstr ""
@@ -170,263 +201,264 @@ msgstr ""
msgid "Grant access to LibreSpeed measurements" msgid "Grant access to LibreSpeed measurements"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:697 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:744
msgid "HTTP (forced)" msgid "HTTP (forced)"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:696 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:743
msgid "HTTPS (forced)" msgid "HTTPS (forced)"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:159 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:189
msgid "Hide this series" msgid "Hide this series"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:109 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:201
#: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:25 #: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:25
msgid "History" msgid "History"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:215 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:245
msgid "History keeping is switched off, so measurements are not recorded." msgid "History keeping is switched off, so measurements are not recorded."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:115 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:207
msgid "History stored in /tmp is lost when the router reboots." msgid "History stored in /tmp is lost when the router reboots."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:171 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:172
msgid "Hourly" msgid "Hourly"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:93 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:90
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:185
msgid "Hours" msgid "Hours"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:441
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:410 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:54
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:26 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:111
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:550 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:577
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:692 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:770
msgid "Interface" msgid "Interface"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:62 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:135
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:680
msgid "Interval" msgid "Interval"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:14 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:15
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:540 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:567
msgid "Jitter" msgid "Jitter"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:388
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:638
msgid "Jitter [ms]" msgid "Jitter [ms]"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:111 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:203
msgid "Keep history" msgid "Keep history"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:490 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:517
msgid "Last measurement failed" msgid "Last measurement of %s failed"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:382 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:407
msgid "Last successful measurement" msgid "Last successful measurement"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:369 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:402
msgid "Latency" msgid "Latency"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:71 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:89
msgid "Leave empty to run every day." msgid ""
"Leave empty to run every day. A weekly test runs on one of the chosen days, "
"or on any day when none is chosen; the day is drawn once and kept while it "
"stays among the chosen days."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:738 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:795
#: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:3 #: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:3
msgid "LibreSpeed" msgid "LibreSpeed"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:455 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:486
msgid "LibreSpeed – History" msgid "LibreSpeed – History"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:22 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:50
msgid "LibreSpeed – Settings" msgid "LibreSpeed – Settings"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:27 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:55
msgid "Logical interface the measurement is bound to." msgid ""
"Logical interface measured by default: by the Test page unless another one "
"is chosen there, and by an automatic test that names no interface."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:24 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:52
msgid "Measurement" msgid "Measurement"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:438 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:469
msgid "Measurements" msgid "Measurements"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:741 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:798
msgid "Measures the internet connection from this router." msgid "Measures the internet connection from this router."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:236 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:244
msgid "Metric" msgid "Metric"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:72 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:181
msgid "Monday" msgid "Monday"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:37 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:66
msgid "Must be a server id or 'auto'" msgid "Must be a server id or 'auto'"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:47 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:76
msgid "Must be an http(s) URL" msgid "Must be an http(s) URL"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:329 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:362
msgid "Next" msgid "Next"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:683 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:732
msgid "Next run"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675
msgid "No" msgid "No"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:246 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:276
msgid "No data for the selected metric." msgid "No data for the selected metric."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:279 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:287
msgid "No data in the last 24 hours." msgid "No data in the last 24 hours."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:507 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:534
msgid "No measurement yet." msgid "No measurement yet."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:218 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:248
msgid "No measurements match the current filters." msgid "No measurements match the current filters."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:430 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:461
msgid "No measurements yet" msgid "No measurements yet"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:161 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:256
msgid "" msgid ""
"No schedule is active. Enable it above and apply to draw the measurement " "No schedule is active. Enable it above and apply to draw the measurement "
"time." "time."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:32 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:61
msgid "" msgid ""
"Numeric server id from the LibreSpeed server list, or 'auto' to pick the " "Numeric server id from the LibreSpeed server list, or 'auto' to pick the "
"closest." "closest."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:51 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:80
msgid "" msgid ""
"On routers without AES acceleration, TLS itself can bound the result — " "On routers without AES acceleration, TLS itself can bound the result — "
"forcing plain HTTP then measures the line rather than the cipher." "forcing plain HTTP then measures the line rather than the cipher."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:223 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:253
msgid "Open settings" msgid "Open settings"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:324 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:357
msgid "Page %d of %d" msgid "Page %d of %d"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:114 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:206
msgid "Path" msgid "Path"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:13 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:14
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:91 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:94
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:539 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:566
msgid "Ping" msgid "Ping"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:388
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:638
msgid "Ping [ms]" msgid "Ping [ms]"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:322 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355
msgid "Previous" msgid "Previous"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:387
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:50 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:79
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:559 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:586
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:695 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:742
msgid "Protocol" msgid "Protocol"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:381 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:414
msgid "Range" msgid "Range"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:726 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:783
msgid "Recent history" msgid "Recent history"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:119 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:211
msgid "Retention" msgid "Retention"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:739 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:796
msgid "Router speed test" msgid "Router speed test"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:217 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:247
msgid "Run a speed test to start building your connection history." msgid "Run a speed test to start building your connection history."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:60 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:88
msgid "" msgid ""
"Runs a measurement from cron at the chosen interval. Note that a measurement " "Runs a measurement from cron at the chosen interval. Note that a measurement "
"saturates the connection while it runs." "saturates the connection while it runs."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:77 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:182
msgid "Saturday" msgid "Saturday"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:707 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:754
msgid "Schedule status" msgid "Schedule status"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:57 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:87
msgid "Scheduled measurements" msgid "Scheduled measurements"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:370 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:403
msgid "Series" msgid "Series"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:387
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:408 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:439
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:31 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:60
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:548 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:575
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:608 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:637
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:693 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:740
msgid "Server" msgid "Server"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:40 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:69
msgid "Server list URL" msgid "Server list URL"
msgstr "" msgstr ""
@@ -434,34 +466,34 @@ msgstr ""
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:159 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:189
msgid "Show this series" msgid "Show this series"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:369 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:402
msgid "Speed" msgid "Speed"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:189 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:219
msgid "Stable over the selected period." msgid "Stable over the selected period."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:258 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:266
msgid "Stable — averaged %d Mbps, ranging from %d to %d Mbps." msgid "Stable — averaged %d Mbps, ranging from %d to %d Mbps."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:223 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:253
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:424 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:455
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:356 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:376
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:619 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:648
msgid "Start test" msgid "Start test"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:356 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:376
msgid "Stop test" msgid "Stop test"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:78 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:183
msgid "Sunday" msgid "Sunday"
msgstr "" msgstr ""
@@ -469,32 +501,53 @@ msgstr ""
msgid "Test" msgid "Test"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:690 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:738
msgid "Test configuration" msgid "Test configuration"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:479 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:658
msgid "The default interface %s is not available."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:151
msgid "The interval %s is not supported. Use 1-59m, 1-23h, 1d or 7d."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:504
msgid "The last measurement was stopped." msgid "The last measurement was stopped."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:105 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:251
msgid ""
"The time of a daily measurement is drawn anew whenever the schedule is "
"applied. A weekly measurement keeps its drawn day and time while they fit "
"the chosen days and hours."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:197
msgid "The window must not cross midnight" msgid "The window must not cross midnight"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:75 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:283
msgid ""
"These results name no interface: days archived before results were kept per "
"interface, which mix all links."
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:182
msgid "Thursday" msgid "Thursday"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:387
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:608 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:637
msgid "Time" msgid "Time"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:73 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:181
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:41 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:70
msgid "" msgid ""
"URL of a LibreSpeed server list in JSON, from a self-hosted deployment: " "URL of a LibreSpeed server list in JSON, from a self-hosted deployment: "
"either a static file such as https://example.org/servers.json or a generator " "either a static file such as https://example.org/servers.json or a generator "
@@ -502,121 +555,126 @@ msgid ""
"official list." "official list."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:700 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:747
msgid "Unencrypted transfers, so the line is measured rather than the cipher." msgid "Unencrypted transfers, so the line is measured rather than the cipher."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:149 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:238
msgid "Upcoming measurements" msgid "Upcoming measurements"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:12 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:13
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:93 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:96
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:533 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:560
msgid "Upload" msgid "Upload"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:388
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:638
msgid "Upload [Mbps]" msgid "Upload [Mbps]"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:103 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:195
msgid "Use an hour (0-23) or a range like 2-5" msgid "Use an hour (0-23) or a range like 2-5"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:255 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:263
msgid "Variable — ranged from %d to %d Mbps." msgid "Variable — ranged from %d to %d Mbps."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:326 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:297
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:345
msgid "View full history »" msgid "View full history »"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:581 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:608
msgid "View result" msgid "View result"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:74 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:181
msgid "Wednesday" msgid "Wednesday"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:703 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:176
msgid "Weekly"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:750
msgid "Whichever scheme the server list provides." msgid "Whichever scheme the server list provides."
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:741
msgid "Yes"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:694
msgid "automatic (nearest)" msgid "automatic (nearest)"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:294 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:313
msgid "average" msgid "average"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:300 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:335
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:371 #: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:406
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:168 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:198
msgid "avg" msgid "avg"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:295 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:314
msgid "best" msgid "best"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:293 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:312
msgid "current" msgid "current"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:209
msgid "declining" msgid "declining"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:557 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:584
msgid "encrypted (HTTPS)" msgid "encrypted (HTTPS)"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:54 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:83
msgid "force HTTP" msgid "force HTTP"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:53 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:82
msgid "force HTTPS" msgid "force HTTPS"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:209
msgid "highly variable" msgid "highly variable"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:604 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:229
msgid "last 24 hours" msgid "last 24 hours"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:557 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:584
msgid "plain HTTP" msgid "plain HTTP"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:367 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:391
msgid "server %s" msgid "server %s"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:52 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:81
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:698 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:745
msgid "server default" msgid "server default"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:209
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:186 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:216
msgid "stable" msgid "stable"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:134 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:25
msgid "unknown"
msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:164
msgid "vs previous period" msgid "vs previous period"
msgstr "" msgstr ""
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:296 #: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:315
msgid "worst" msgid "worst"
msgstr "" msgstr ""
@@ -7,24 +7,12 @@
"status", "status",
"result", "result",
"history", "history",
"config" "config",
], "links"
"network.interface": [
"dump"
],
"network": [
"get_proto_handlers"
],
"luci-rpc": [
"getBoardJSON",
"getNetworkDevices",
"getWirelessDevices"
] ]
}, },
"uci": [ "uci": [
"librespeed", "librespeed"
"network",
"wireless"
] ]
}, },
"write": { "write": {
+23 -8
View File
@@ -7,8 +7,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-linkeasefull-embed PKG_NAME:=luci-app-linkeasefull-embed
PKG_VERSION:=1.2.0-r1 PKG_VERSION:=1.2.0-r3
PKG_RELEASE:=4 PKG_RELEASE:=5
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0 PKG_USE_MIPS16:=0
@@ -28,14 +28,29 @@ define Package/$(PKG_NAME)/description
Register OpenWrt LuCI as a LinkEaseFull desktop module and provide embedded-mode assets. Register OpenWrt LuCI as a LinkEaseFull desktop module and provide embedded-mode assets.
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
# Compatibility entry for desktops which only scan the old directory.
root="$${IPKG_INSTROOT:-}"
legacy="$${root}/usr/share/linkeasefull/desktop-apps.d/15-openwrt-luci.json"
if [ ! -e "$${legacy}" ] && [ ! -L "$${legacy}" ]; then
mkdir -p "$${legacy%/*}"
ln -s /usr/share/linkeasefull/openwrt-luci/openwrt-luci.json "$${legacy}" || exit $$?
fi
exit 0
endef
define Package/$(PKG_NAME)/prerm define Package/$(PKG_NAME)/prerm
#!/bin/sh #!/bin/sh
set -e set -e
root="$${IPKG_INSTROOT:-}" root="$${IPKG_INSTROOT:-}"
registration="$${root}/usr/share/linkeasefull/desktop-apps.d/15-openwrt-luci.json" for directory in /usr/share/linkease/apps.d /usr/share/linkeasefull/desktop-apps.d; do
if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json" ]; then registration="$${root}$${directory}/15-openwrt-luci.json"
rm -f "$${registration}" if [ "$$(readlink "$${registration}" 2>/dev/null)" = "/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json" ]; then
fi rm -f "$${registration}"
fi
done
rmdir "$${root}/usr/share/linkeasefull/desktop-apps.d" 2>/dev/null || true
exit 0 exit 0
endef endef
@@ -46,13 +61,13 @@ define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/share/linkeasefull/openwrt-luci $(1)/usr/share/linkeasefull/desktop-apps.d $(INSTALL_DIR) $(1)/usr/share/linkeasefull/openwrt-luci $(1)/usr/share/linkease/apps.d
$(INSTALL_DIR) $(1)/www/luci-static/linkeasefull-embed $(INSTALL_DIR) $(1)/www/luci-static/linkeasefull-embed
$(INSTALL_DATA) ./files/openwrt-luci/openwrt-luci.json $(1)/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json $(INSTALL_DATA) ./files/openwrt-luci/openwrt-luci.json $(1)/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json
$(INSTALL_DATA) ./files/openwrt-luci/openwrt.svg $(1)/usr/share/linkeasefull/openwrt-luci/openwrt.svg $(INSTALL_DATA) ./files/openwrt-luci/openwrt.svg $(1)/usr/share/linkeasefull/openwrt-luci/openwrt.svg
$(INSTALL_DATA) ./files/www/embed.css $(1)/www/luci-static/linkeasefull-embed/embed.css $(INSTALL_DATA) ./files/www/embed.css $(1)/www/luci-static/linkeasefull-embed/embed.css
$(INSTALL_DATA) ./files/www/embed-prelude.js $(1)/www/luci-static/linkeasefull-embed/embed-prelude.js $(INSTALL_DATA) ./files/www/embed-prelude.js $(1)/www/luci-static/linkeasefull-embed/embed-prelude.js
ln -sf /usr/share/linkeasefull/openwrt-luci/openwrt-luci.json $(1)/usr/share/linkeasefull/desktop-apps.d/15-openwrt-luci.json ln -sf /usr/share/linkeasefull/openwrt-luci/openwrt-luci.json $(1)/usr/share/linkease/apps.d/15-openwrt-luci.json
endef endef
$(eval $(call BuildPackage,$(PKG_NAME))) $(eval $(call BuildPackage,$(PKG_NAME)))
+1 -1
View File
@@ -7,7 +7,7 @@ separate from the independently installable `linkeasefull` runtime package.
This package installs: This package installs:
- `/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json` - `/usr/share/linkeasefull/openwrt-luci/openwrt-luci.json`
- `/usr/share/linkeasefull/desktop-apps.d/15-openwrt-luci.json` - `/usr/share/linkease/apps.d/15-openwrt-luci.json`
- `/www/luci-static/linkeasefull-embed/embed-prelude.js` - `/www/luci-static/linkeasefull-embed/embed-prelude.js`
- `/www/luci-static/linkeasefull-embed/embed.css` - `/www/luci-static/linkeasefull-embed/embed.css`
@@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-10 03:40+0200\n" "POT-Creation-Date: 2009-06-10 03:40+0200\n"
"PO-Revision-Date: 2026-05-03 18:07+0000\n" "PO-Revision-Date: 2026-11-06 09:18+0000\n"
"Last-Translator: sllk <sillhack@hotmail.fr>\n" "Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: French <https://hosted.weblate.org/projects/openwrt/" "Language-Team: French <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationspackage-manager/fr/>\n" "luciapplicationspackage-manager/fr/>\n"
"Language: fr\n" "Language: fr\n"
@@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.17.1\n" "X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008
@@ -287,7 +287,7 @@ msgstr "Remise à zéro"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1157 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1157
msgid "SHA256" msgid "SHA256"
msgstr "SHA-256" msgstr "SHA256"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1019 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1019
msgid "Save" msgid "Save"
@@ -1,8 +1,9 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2026-10-13 21:56+0000\n" "PO-Revision-Date: 2026-11-04 16:54+0000\n"
"Last-Translator: Pavel Borecki <pavelbo@users.noreply.hosted.weblate.org>\n" "Last-Translator: Kövecses József <kovecses@users.noreply.hosted.weblate.org>"
"\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationspackage-manager/hu/>\n" "luciapplicationspackage-manager/hu/>\n"
"Language: hu\n" "Language: hu\n"
@@ -10,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.11.dev0\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008
@@ -233,7 +234,7 @@ msgstr "Nincs telepítve"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1268 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1268
msgid "OK" msgid "OK"
msgstr "Rendben" msgstr "OK"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1344 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1344
msgid "Package name" msgid "Package name"
@@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-10 03:41+0200\n" "POT-Creation-Date: 2009-06-10 03:41+0200\n"
"PO-Revision-Date: 2026-09-29 12:10+0000\n" "PO-Revision-Date: 2026-11-01 06:11+0000\n"
"Last-Translator: Pavel Borecki <pavel.borecki@gmail.com>\n" "Last-Translator: LucasMZ <git@lucasmz.dev>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"openwrt/luciapplicationspackage-manager/pt_BR/>\n" "openwrt/luciapplicationspackage-manager/pt_BR/>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
@@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 2026.10.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008
@@ -142,7 +142,7 @@ msgstr "Executando o gerenciador de pacotes"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1257 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1257
msgid "Filter" msgid "Filter"
msgstr "Filtrar" msgstr "Filtro"
#: applications/luci-app-package-manager/root/usr/share/rpcd/acl.d/luci-app-package-manager.json:3 #: applications/luci-app-package-manager/root/usr/share/rpcd/acl.d/luci-app-package-manager.json:3
msgid "Grant access to package management" msgid "Grant access to package management"
@@ -1,8 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2026-05-15 10:43+0000\n" "PO-Revision-Date: 2026-10-20 09:40+0000\n"
"Last-Translator: 為什麼不加空格 <c++23@users.noreply.hosted.weblate.org>\n" "Last-Translator: TCP <tcp@users.noreply.hosted.weblate.org>\n"
"Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/" "Language-Team: Chinese (Traditional Han script) <https://hosted.weblate.org/"
"projects/openwrt/luciapplicationspackage-manager/zh_Hant/>\n" "projects/openwrt/luciapplicationspackage-manager/zh_Hant/>\n"
"Language: zh_Hant\n" "Language: zh_Hant\n"
@@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.5.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:943
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1008
@@ -37,7 +37,7 @@ msgstr "允許覆寫衝突套件檔案"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1057 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1057
msgid "Automatically remove unused dependencies" msgid "Automatically remove unused dependencies"
msgstr "自動刪除未使用依賴項" msgstr "自動移除未使用依賴項"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1328 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1328
msgid "Available" msgid "Available"
@@ -243,15 +243,15 @@ msgstr "確定安裝 <em>%h</em>?"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1071 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1071
msgid "Remove" msgid "Remove"
msgstr "刪除" msgstr "移除"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1047 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:1047
msgid "Remove package <em>%h</em>" msgid "Remove package <em>%h</em>"
msgstr "刪除套件 <em>%h</em>" msgstr "移除套件 <em>%h</em>"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:337 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:337
msgid "Remove…" msgid "Remove…"
msgstr "刪除…" msgstr "移除…"
#: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:822 #: applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js:822
msgid "Require approx. %1024mB size for %d package(s) to install." msgid "Require approx. %1024mB size for %d package(s) to install."
File diff suppressed because it is too large. Load diff
@@ -9,21 +9,19 @@
--qos-hd: var(--background-color-low, rgba(128, 128, 128, .06)); --qos-hd: var(--background-color-low, rgba(128, 128, 128, .06));
--qos-r: 4px; --qos-r: 4px;
--qos-gap: .75em; --qos-gap: .75em;
--qos-pad: .45em 1em; /* The table cell padding; every box and row uses it, so all tabs line up. */
--qos-pad: .45em .75em;
} }
/* The service bar sits outside any section, so it gets its own box. Flex /* The service bar is the theme's own .cbi-page-actions, sized and drawn as
items ignore float, so the theme's page-actions floats cannot reorder the the quick settings Save & Apply bar above it. Flex items ignore float, so the
buttons and they stay in declared order whatever their colour class. */ theme's page-actions floats cannot reorder the buttons and they stay in
declared order whatever their colour class. */
#qos-svc-btns { #qos-svc-btns {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-end; justify-content: flex-end;
gap: .4em; gap: .4em;
margin: 0 0 var(--qos-gap);
padding: var(--qos-pad);
border: 1px solid var(--qos-bd);
border-radius: var(--qos-r);
} }
#qos-svc-btns::after { #qos-svc-btns::after {
@@ -46,7 +44,7 @@
} }
#qos-app .table .td { #qos-app .table .td {
padding: .45em .75em; padding: var(--qos-pad);
vertical-align: middle; vertical-align: middle;
border-top-color: var(--qos-ln); border-top-color: var(--qos-ln);
} }
@@ -101,12 +99,6 @@
padding: 0; padding: 0;
} }
/* The fold box sits just clear of its heading; the theme's h3 line-height
would otherwise double its depth. */
#qos-app .qa > details.cbi-section {
padding: .4em .75em;
}
#qos-app .qos-box > h3 { #qos-app .qos-box > h3 {
margin: 0 0 var(--qos-gap); margin: 0 0 var(--qos-gap);
} }
@@ -162,6 +154,16 @@
padding: .15em .3em; padding: .15em .3em;
} }
/* The Dynamic Entries list is a table, not a form row: full cell padding. */
#qos-app .qa #qos-dyn .th,
#qos-app .qa #qos-dyn .td {
padding: var(--qos-pad);
}
#qos-app .qa .cbi-section-descr {
margin: 0 0 .4em;
}
#qos-app .qa .th { #qos-app .qa .th {
font-size: .85em; font-size: .85em;
overflow: hidden; overflow: hidden;
@@ -197,7 +199,7 @@
} }
#qos-app .qa details:not(.cbi-section) .td { #qos-app .qa details:not(.cbi-section) .td {
padding: .2em .5em; padding: var(--qos-pad);
border-top: 1px solid var(--qos-ln); border-top: 1px solid var(--qos-ln);
} }
@@ -286,7 +288,8 @@
} }
/* A header table above a boxed body; bars and figures are updated in place. */ /* A header table above a boxed body; bars and figures are updated in place. */
#qos-cn .qbox { #qos-cn .qbox,
#qos-dyn .qbox {
overflow: hidden; overflow: hidden;
border: 1px solid var(--qos-bd); border: 1px solid var(--qos-bd);
border-radius: var(--qos-r); border-radius: var(--qos-r);
@@ -296,19 +299,23 @@
margin-top: var(--qos-gap); margin-top: var(--qos-gap);
} }
#qos-cn .qhead { #qos-cn .qhead,
#qos-dyn .qhead {
background: var(--qos-hd); background: var(--qos-hd);
border-bottom: 1px solid var(--qos-ln); border-bottom: 1px solid var(--qos-ln);
} }
#qos-cn .qhead .th, #qos-cn .qhead .th,
#qos-cn .qbox .td { #qos-cn .qbox .td,
#qos-dyn .qhead .th,
#qos-dyn .qbox .td {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
#qos-cn .qbox .tr:not(.table-titles):hover .td { #qos-cn .qbox .tr:not(.table-titles):hover .td,
#qos-dyn .qbox .tr:not(.table-titles):hover .td {
background: var(--qos-hd); background: var(--qos-hd);
} }
@@ -319,7 +326,8 @@
border-radius: var(--qos-r); border-radius: var(--qos-r);
} }
#qos-cn .qn { #qos-cn .qn,
#qos-dyn .qn {
width: 1%; width: 1%;
text-align: right; text-align: right;
white-space: nowrap; white-space: nowrap;
@@ -330,50 +338,229 @@
font-weight: 600; font-weight: 600;
} }
#qos-cn-map-box { /* The measure sits above the sections, at the right, as a plain select. */
#qos-cn-measure {
display: flex;
justify-content: flex-end;
align-items: center;
gap: .5em;
}
#qos-cn-measure select {
width: auto;
}
/* Traffic by CAKE Tin: a box per direction, side by side while they fit. The
banner holds the direction over the donut and the column titles over the
table; in a narrow box both wrap, so the titles stay above the table and the
donut drops below it. */
#qos-cn .qos-tins {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 26em), 1fr));
gap: var(--qos-gap);
}
#qos-cn .qos-tins .qbox {
min-width: 0;
}
#qos-cn .qos-tins .qbox + .qbox {
margin-top: 0;
}
#qos-cn .qos-tin-head,
#qos-cn .qos-tin-body {
display: flex;
flex-wrap: wrap;
align-items: center;
}
#qos-cn .qos-tin-head {
column-gap: var(--qos-gap);
}
/* As wide as the donut and its margin, so the titles sit over their columns. */
#qos-cn .qos-tin-head > div {
flex: none;
box-sizing: border-box;
width: calc(9.5em + var(--qos-gap));
padding: var(--qos-pad);
padding-right: 0;
}
#qos-cn .qos-tin-body {
flex-wrap: wrap-reverse;
justify-content: center;
}
#qos-cn .qos-tin-head .table,
#qos-cn .qos-tin-body .table {
flex: 1 1 18em;
margin: 0;
}
/* Arcs are stroked circles over a ring that shows where a tin has none. */
#qos-cn .qos-donut {
position: relative;
flex: none;
width: 9.5em;
height: 9.5em;
margin: var(--qos-gap);
}
#qos-cn .qos-donut svg {
display: block;
width: 100%;
height: 100%;
fill: none;
stroke-width: 15;
}
#qos-cn .qos-donut .qos-ring {
stroke: var(--qos-ln);
}
#qos-cn .qos-donut div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: .9em;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
/* Traffic by Class under one mode: tin rows are shaded as the header is. Class
rows sit under the tin name, by the cell padding plus a swatch and its margin,
with their codepoints muted. The bars' column takes what the names and figures
leave. */
#qos-cn .qos-bar {
width: 100%;
min-width: 4em;
}
#qos-cn .qbox .qos-grp .td {
background: var(--qos-hd);
}
/* Footstrap pins a table's titles under its top bar while the page scrolls.
In this clipped box they would pin to the box and cover the first rows. */
#qos-cn .qos-cls .th {
position: static;
}
#qos-cn .qos-cls .qos-in > .td:first-child {
padding-left: 1.85em;
}
#qos-cn .qos-mk {
opacity: .75;
}
#qos-cn .qos-sw {
display: inline-block;
width: .7em;
height: .7em;
margin-right: .4em;
border-radius: 2px;
}
#qos-cn .qos-cn-info {
margin: var(--qos-gap) 0 0;
font-size: 90%;
}
#qos-cn-map-box,
#qos-dyn-box {
height: 24rem; height: 24rem;
min-height: 6rem; min-height: 6rem;
overflow-y: scroll; overflow-y: scroll;
resize: vertical; resize: vertical;
} }
/* Quick settings: one inner box per tab, rows split by the same line as the /* A handful of dynamic entries is usual, so the box fits its rows up to the same height. */
tables, and the control then its hint on one line so every hint starts in #qos-dyn-box {
the same column. */ height: auto;
min-height: 0;
max-height: 24rem;
overflow-y: auto;
}
/* Quick settings: unboxed, like the Service table above it, with its rows laid
out as that table's: the same cell padding, a 33% label column in the theme's
normal weight and a line above every row. The control then its hint on one
line, so every hint starts in the same column. */
/* Clear of the Service table above, which ends without a bar of its own. */
#qos-qs-sect {
--qos-ctl: 2.4em;
margin-top: 2em;
}
/* Every row is as deep as one holding an input box, checkbox rows included, and
the box fits its rows, with no blank space under the last one. */
#qos-app .qs-box { #qos-app .qs-box {
min-width: 0; min-width: 0;
min-height: 13em; padding: 0;
padding: .3em 1.5em;
border: 1px solid var(--qos-bd);
border-radius: var(--qos-r);
} }
/* The theme wraps .cbi-value; a row here never wraps on a wide screen, and the
field takes what the label leaves (basis 0), not its content's width, so a
long hint cannot push the field onto a line of its own. */
#qos-qs-sect .cbi-value { #qos-qs-sect .cbi-value {
align-items: flex-start; flex-wrap: nowrap;
align-items: center;
margin: 0; margin: 0;
padding: .25em 0; padding: 0;
}
#qos-qs-sect .cbi-value + .cbi-value {
border-top: 1px solid var(--qos-ln); border-top: 1px solid var(--qos-ln);
} }
/* No line above a tab's first row: the tab bar already draws one there. */
#qos-qs-sect .qs-box > .cbi-value:first-child {
border-top: 0;
}
#qos-qs-sect .cbi-value label.cbi-value-title { #qos-qs-sect .cbi-value label.cbi-value-title {
flex: 0 0 16em; flex: 0 0 33%;
padding-top: 0; box-sizing: border-box;
line-height: 30px; padding: var(--qos-pad);
font-weight: 600; text-align: left;
font-weight: normal;
} }
#qos-qs-sect .cbi-value-field { #qos-qs-sect .cbi-value-field {
display: grid; display: grid;
grid-template-columns: minmax(0, 18em) minmax(0, 1fr); grid-template-columns: minmax(0, 28em) minmax(0, 1fr);
align-items: center; align-items: center;
gap: .3em 1.5em; gap: .3em 1.5em;
flex: 1 1 auto; flex: 1 1 0;
margin-left: 1.5em; box-sizing: border-box;
min-height: calc(var(--qos-ctl) + .9em);
margin: 0;
padding: var(--qos-pad);
min-width: 0; min-width: 0;
line-height: 30px; }
/* The tab panes share one grid cell, so the box is as deep as the tallest tab
and switching tabs never moves the page; a shorter tab leaves a gap under its
last row. A hidden pane keeps its size but cannot be seen, clicked or focused. */
#qos-qs-sect .qs-panes {
display: grid;
}
#qos-qs-sect .qs-panes > [data-tab] {
grid-area: 1 / 1;
height: auto;
max-height: none;
overflow: visible;
}
#qos-qs-sect .qs-panes > [data-tab]:not([data-tab-active="true"]) {
visibility: hidden;
} }
#qos-qs-sect .cbi-value-description { #qos-qs-sect .cbi-value-description {
@@ -398,6 +585,7 @@
#qos-qs-sect .cbi-value-field input[type=text], #qos-qs-sect .cbi-value-field input[type=text],
#qos-qs-sect .cbi-value-field input[type=number], #qos-qs-sect .cbi-value-field input[type=number],
#qos-qs-sect .cbi-value-field select { #qos-qs-sect .cbi-value-field select {
height: var(--qos-ctl);
max-width: 100%; max-width: 100%;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -424,10 +612,6 @@
width: 18em; width: 18em;
} }
#qos-qs-sect .qs-wide .cbi-value-field {
grid-template-columns: minmax(0, 28em) minmax(0, 1fr);
}
#qos-qs-sect [data-q$=opts] { #qos-qs-sect [data-q$=opts] {
width: 100%; width: 100%;
} }
@@ -439,15 +623,28 @@
} }
#qos-qs-sect .cbi-value label.cbi-value-title { #qos-qs-sect .cbi-value label.cbi-value-title {
line-height: 1.5; padding-bottom: 0;
} }
#qos-qs-sect .cbi-value-field { #qos-qs-sect .cbi-value-field {
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
margin-left: 0;
} }
#qos-qs-sect .cbi-value-field > * { #qos-qs-sect .cbi-value-field > * {
grid-column: 1; grid-column: 1;
} }
/* Traffic by Class leaves its bars out and lets a codepoint, or a class name
too long for the line, wrap, so the figures keep their width. */
#qos-cn .qos-bar {
display: none;
}
#qos-cn .qos-cls .td:first-child {
white-space: normal;
}
#qos-cn .qos-cls code {
overflow-wrap: anywhere;
}
} }
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: MIT
'use strict';
'require baseclass';
'require fs';
'require rpc';
'require uci';
// Status > Overview card: the Service rows of the app's Overview tab, with the
// shaped rates. Three ubus calls a tick and the qosify config, which uci.load()
// reads once per page, so nothing forks. index.js stops drawing a card whose
// load() rejects, so each call settles to null, shown as unknown.
var callServiceList=rpc.declare({object:'service',method:'list',params:['name'],expect:{'':{}},reject:true});
// skip_running_check keeps rc.list from forking `qosify running`.
var callRcList=rpc.declare({object:'rc',method:'list',params:['name','skip_running_check'],expect:{'':{}},reject:true});
var callQosifyStatus=rpc.declare({object:'qosify',method:'status',expect:{'':{}},reject:true});
// Bootstrap and OpenWrt 2020 have no .label.danger; the app's own rule from
// qosify.css. Footstrap drops the row lines of a two-cell table on this page:
// a rule outside its layers draws them, and :where() keeps it under any theme's
// .table .td, so bootstrap and its phone layout keep their own lines.
var STYLE='.qos-ov .label.danger{background-color:var(--error-color-high,#e8210d);color:var(--on-error-color,#fff)}'+
':where(.qos-ov .tr+.tr)>.td{border-top:1px solid var(--border-color-medium,rgba(128,128,128,.35))}';
function nul(){return null;}
function tx(v){return typeof v==='string'?[v]:v;}
function badge(kind,t){return E('span',{'class':'label '+kind},tx(t));}
function unk(){return badge('warning',_('Unknown'));}
function kvRow(k,v){return E('tr',{'class':'tr'},[E('td',{'class':'td left','width':'33%'},tx(k)),E('td',{'class':'td left'},tx(v))]);}
function isRunning(r){try{var i=r.qosify.instances;for(var k in i)if(i[k].running)return true;}catch(e){}return false;}
function runPid(r){try{var i=r.qosify.instances;for(var k in i)if(i[k].running&&i[k].pid)return i[k].pid;}catch(e){}return 0;}
// The status keys are option name; qosify.init sends no disabled section
// (config_get_bool) and falls back to bandwidth for an unset direction. A
// shaped direction without one runs CAKE unlimited.
function ifSect(type,name){
return uci.sections('qosify',type).filter(function(s){return s.name===name&&!/^(1|on|true|yes|enabled)$/.test(s.disabled);})[0]||null;
}
function rate(s,on,k){return !on?_('no'):!s?_('yes'):s['bandwidth_'+k]||s.bandwidth||_('unlimited');}
return baseclass.extend({
title:_('qosify'),
load:function(){
var self=this;
return Promise.all([
callServiceList('qosify').catch(nul),
callRcList('qosify',true).catch(nul),
callQosifyStatus().catch(nul),
uci.load('qosify').catch(nul)
]).then(function(d){return self.uptime(d[0]).then(function(u){d.push(u);return d;});});
},
// As on the Overview tab: service list carries the pid but no start time, so
// starttime (field 22 of /proc/<pid>/stat, USER_HZ ticks since boot) is set
// against /proc/uptime, once per pid; later ticks add performance.now().
uptime:function(r){
var self=this,pid=runPid(r);
if(!pid){self._up=null;return Promise.resolve(null);}
if(self._up&&self._up.pid===pid)return Promise.resolve(self._up.up+(performance.now()-self._up.t)/1000);
return Promise.all([fs.read('/proc/'+pid+'/stat'),fs.read('/proc/uptime')]).then(function(d){
var st=String(d[0]),f=st.slice(st.lastIndexOf(')')+2).split(' '),up=parseFloat(d[1])-f[19]/100;
if(!(up>=0))return null;
self._up={pid:pid,up:up,t:performance.now()};
return up;
}).catch(nul);
},
// The Overview tab's rows and wording, each interface with its rates in place
// of yes. The qosify object goes with the daemon, so an unanswered status
// call only reads unknown while it runs.
render:function(d){
var run=d[0]!==null?isRunning(d[0]):null,rc=d[1]&&d[1].qosify,st=d[2]||(run===false?{}:null),n=0,ifs=[];
if(st)['interfaces','devices'].forEach(function(g){
for(var k in st[g]){
var e=st[g][k]||{},s=d[3]!==null?ifSect(g==='devices'?'device':'interface',k):null;
if(e.active)n++;
ifs.push(kvRow((g==='devices'?_('device %s'):_('interface %s')).format(k),[badge(e.active?'success':'danger',e.active?_('active'):_('inactive')),' ',
_('device: %s, ingress: %s, egress: %s').format(e.ifname||'-',rate(s,e.ingress,'down'),rate(s,e.egress,'up'))]));
}
});
return E([E('style',{},[STYLE]),E('table',{'class':'table qos-ov'},[
kvRow(_('Status'),run==null?unk():run&&!st?badge('warning',_('Running — Shaping Unknown')):run&&n?badge('success',_('Running & Shaping')):
run?badge('warning',_('Running — Not Shaping')):badge('danger',_('Not Running'))),
kvRow(_('Uptime'),d[4]!=null?'%t'.format(Math.floor(d[4])):'-'),
kvRow(_('Autostart'),d[1]===null?unk():rc&&rc.enabled?badge('success',_('Enabled')):badge('danger',_('Disabled')))
].concat(ifs))]);
}
});
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -4,8 +4,8 @@
# Remove qosify qdiscs and ifb devices left behind after qosify exits. # Remove qosify qdiscs and ifb devices left behind after qosify exits.
# #
# A clean stop only does part of this: interface_clear_qdisc() removes the root # A clean stop only does part of this: interface_clear_qdisc() removes the root
# qdisc, the bpf filters and the ifb device but not clsact, and main() never # qdisc, the bpf filters and the ifb device but not clsact, and before 16c95b0
# calls qosify_dns_stop(), so ifb-dns stays up. A crash, a SIGKILL or a respawn # main() never called qosify_dns_stop(), so ifb-dns stays up. A crash, a SIGKILL or a respawn
# loop leaves the rest too. This script deliberately only touches the devices of # loop leaves the rest too. This script deliberately only touches the devices of
# enabled qosify sections, the ifb names qosify derives from them and qosify's # enabled qosify sections, the ifb names qosify derives from them and qosify's
# own ifb-dns -- never a qdisc or ifb qosify did not create. # own ifb-dns -- never a qdisc or ifb qosify did not create.
@@ -32,11 +32,12 @@ exec 9>"$LOCK"
command -v flock >/dev/null && { flock -n 9 || exit 0; } command -v flock >/dev/null && { flock -n 9 || exit 0; }
# Mirrors interface_ifb_name() in qosify: "ifb-<dev>" while strlen(dev) + 4 is # Mirrors interface_ifb_name() in qosify: "ifb-<dev>" while strlen(dev) + 4 is
# below IFNAMSIZ. Longer names take a different branch upstream which we do not # below IFNAMSIZ, else "ifb-" + the first two and last nine characters of dev
# try to reproduce here. # (21cc618). Older builds read before the name for long devices, so their ifb
# cannot be derived and simply is not found here.
ifb_name() { ifb_name() {
[ "${#1}" -lt 12 ] || return 1 [ "${#1}" -lt 12 ] && echo "ifb-$1" ||
echo "ifb-$1" echo "ifb-$(printf %.2s "$1")${1#"${1%?????????}"}"
} }
qosify_filter() { qosify_filter() {
@@ -44,7 +45,8 @@ qosify_filter() {
} }
# qosify's filters sit at QOSIFY_PRIO_BASE (0x110 = 272): its bpf classifier on # qosify's filters sit at QOSIFY_PRIO_BASE (0x110 = 272): its bpf classifier on
# egress, and on ingress the classifier plus the DNS and ifb redirects up to 277. # egress, and on ingress the classifier plus the DNS and ifb redirects up to 277
# (interface_clear_qdisc() deletes the same six; aa3aa6b uses 272-274 of them).
# A clean exit removes them and the root qdisc, so they only survive a crash, and # A clean exit removes them and the root qdisc, so they only survive a crash, and
# then the root cake is qosify's too. Another shaper's root qdisc, and a clsact # then the root cake is qosify's too. Another shaper's root qdisc, and a clsact
# carrying anyone else's filters, are left alone. # carrying anyone else's filters, are left alone.
@@ -130,7 +132,7 @@ fi
for dev in $DEVS; do clear_dev "$dev"; done for dev in $DEVS; do clear_dev "$dev"; done
# ifb-dns is qosify's fixed DNS ifb, not derived from any section, and a stop # ifb-dns is qosify's fixed DNS ifb, not derived from any section, and a stop
# leaves it up under the kernel's default fq_codel. Deleting its root qdisc only # before 16c95b0 leaves it up under the kernel's default fq_codel. Deleting its root qdisc only
# re-attaches the default, so drop the device -- only once qosify has exited. # re-attaches the default, so drop the device -- only once qosify has exited.
pidof qosify >/dev/null || ip link del ifb-dns 2>/dev/null pidof qosify >/dev/null || ip link del ifb-dns 2>/dev/null
@@ -37,6 +37,7 @@ config interface wan
option nat 1 option nat 1
option host_isolate 1 option host_isolate 1
option autorate_ingress 0 option autorate_ingress 0
option multiqueue 0
option ingress_options "" option ingress_options ""
option egress_options "" option egress_options ""
option options "" option options ""
@@ -6,21 +6,24 @@
"qosify": [ "status", "get_stats", "dump" ], "qosify": [ "status", "get_stats", "dump" ],
"rc": [ "list" ], "rc": [ "list" ],
"service": [ "list" ], "service": [ "list" ],
"file": [ "read", "stat" ] "network.interface": [ "status" ],
"file": [ "read", "stat", "list" ]
}, },
"uci": [ "qosify" ], "uci": [ "qosify" ],
"file": { "file": {
"/etc/config/qosify": [ "read", "list" ], "/etc/config/qosify": [ "read", "list" ],
"/etc/qosify/00-defaults.conf": [ "read", "list" ], "/etc/qosify/00-defaults.conf": [ "read", "list" ],
"/etc/init.d/qosify": [ "read" ],
"/usr/share/qosify-luci/qosify": [ "read" ], "/usr/share/qosify-luci/qosify": [ "read" ],
"/usr/share/qosify-luci/00-defaults.conf": [ "read" ], "/usr/share/qosify-luci/00-defaults.conf": [ "read" ],
"/proc/uptime": [ "read" ], "/proc/uptime": [ "read" ],
"/proc/[0-9]*/stat": [ "read" ] "/proc/[0-9]*/stat": [ "read" ],
"/sys/class/net/*/queues": [ "list" ]
} }
}, },
"write": { "write": {
"ubus": { "ubus": {
"qosify": [ "reload", "check_devices" ], "qosify": [ "reload", "check_devices", "add", "remove" ],
"rc": [ "init" ], "rc": [ "init" ],
"uci": [ "revert" ], "uci": [ "revert" ],
"file": [ "write", "exec" ] "file": [ "write", "exec" ]
+4 -4
View File
@@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-26 17:57+0200\n" "POT-Creation-Date: 2009-05-26 17:57+0200\n"
"PO-Revision-Date: 2026-09-08 12:39+0000\n" "PO-Revision-Date: 2026-11-04 16:54+0000\n"
"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" "Last-Translator: Dirk Brenken <dibdot@users.noreply.hosted.weblate.org>\n"
"Language-Team: German <https://hosted.weblate.org/projects/openwrt/" "Language-Team: German <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssamba4/de/>\n" "luciapplicationssamba4/de/>\n"
"Language: de\n" "Language: de\n"
@@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.9.1\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -129,7 +129,7 @@ msgstr "Besitzer Erben"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:34 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:34
msgid "Interface" msgid "Interface"
msgstr "Interface" msgstr "Schnittstelle"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35
msgid "Listen only on the given interface or, if unspecified, on lan" msgid "Listen only on the given interface or, if unspecified, on lan"
+8 -6
View File
@@ -1,8 +1,9 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2026-03-08 17:30+0000\n" "PO-Revision-Date: 2026-11-05 07:53+0000\n"
"Last-Translator: hmzs <hmzs@1szer1.hu>\n" "Last-Translator: Kövecses József <kovecses@users.noreply.hosted.weblate.org>"
"\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssamba4/hu/>\n" "luciapplicationssamba4/hu/>\n"
"Language: hu\n" "Language: hu\n"
@@ -10,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.17-dev\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -126,12 +127,13 @@ msgstr "Tulajdonos öröklése"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:34 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:34
msgid "Interface" msgid "Interface"
msgstr "Csatoló" msgstr "Interfész"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35
msgid "Listen only on the given interface or, if unspecified, on lan" msgid "Listen only on the given interface or, if unspecified, on lan"
msgstr "" msgstr ""
"Figyelés csak a megadott csatolón, vagy a helyi hálózaton, ha nincs megadva" "Figyelés csak a megadott interfészen, vagy a helyi hálózaton, ha nincs "
"megadva"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98
msgid "Name" msgid "Name"
@@ -152,7 +154,7 @@ msgstr ""
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:99 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:99
msgid "Path" msgid "Path"
msgstr "Útvonal" msgstr "Elérési út"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:94 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:94
msgid "" msgid ""
+4 -4
View File
@@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-03-22 15:23+0100\n" "POT-Creation-Date: 2010-03-22 15:23+0100\n"
"PO-Revision-Date: 2026-02-10 18:10+0000\n" "PO-Revision-Date: 2026-10-30 23:22+0000\n"
"Last-Translator: Hyeonjeong Lee <h9101654@gmail.com>\n" "Last-Translator: Hyeonjeong Lee <hayden@users.noreply.hosted.weblate.org>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Korean <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssamba4/ko/>\n" "luciapplicationssamba4/ko/>\n"
"Language: ko\n" "Language: ko\n"
@@ -12,7 +12,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.16-dev\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -130,7 +130,7 @@ msgstr "인터페이스"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35
msgid "Listen only on the given interface or, if unspecified, on lan" msgid "Listen only on the given interface or, if unspecified, on lan"
msgstr "지정된 인터페이스에서만 수신 대기하며, 미지정 시 lan에서 응답합니다" msgstr "지정 시 해당 인터페이스에서만, 미지정 시 lan에서 수신 대기합니다"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98
msgid "Name" msgid "Name"
+4 -4
View File
@@ -1,8 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2025-01-27 15:34+0000\n" "PO-Revision-Date: 2026-11-04 21:08+0000\n"
"Last-Translator: Piotr Kołtun <pkoltungm@gmail.com>\n" "Last-Translator: Matthaiks <kityn@users.noreply.hosted.weblate.org>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Polish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssamba4/pl/>\n" "luciapplicationssamba4/pl/>\n"
"Language: pl\n" "Language: pl\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n" "|| n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.10-dev\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -109,7 +109,7 @@ msgstr "Wymuś synchroniczne I/O"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:31 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:31
msgid "General Settings" msgid "General Settings"
msgstr "Ustawienia główne" msgstr "Ustawienia ogólne"
#: applications/luci-app-samba4/root/usr/share/rpcd/acl.d/luci-app-samba4.json:3 #: applications/luci-app-samba4/root/usr/share/rpcd/acl.d/luci-app-samba4.json:3
msgid "Grant access to LuCI app samba4" msgid "Grant access to LuCI app samba4"
+20 -17
View File
@@ -3,8 +3,9 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-16 06:59+0200\n" "POT-Creation-Date: 2009-08-16 06:59+0200\n"
"PO-Revision-Date: 2023-06-20 13:51+0000\n" "PO-Revision-Date: 2026-11-01 06:11+0000\n"
"Last-Translator: Mashiro <michio.haiyaku@gmail.com>\n" "Last-Translator: Lê Hoàng Tiến <tienvn6222@users.noreply.hosted.weblate.org>"
"\n"
"Language-Team: Vietnamese <https://hosted.weblate.org/projects/openwrt/" "Language-Team: Vietnamese <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssamba4/vi/>\n" "luciapplicationssamba4/vi/>\n"
"Language: vi\n" "Language: vi\n"
@@ -12,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.18.1\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -40,7 +41,7 @@ msgstr "Chia sẻ Apple Time-machine"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:104 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:104
msgid "Browse-able" msgid "Browse-able"
msgstr "Cho phép duyệt (Browse-able)" msgstr "Có thể duyệt"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:136 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:136
msgid "Create mask" msgid "Create mask"
@@ -76,7 +77,7 @@ msgstr "Chỉnh sửa mẫu được sử dụng để tạo cấu hình samba."
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:57 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:57
msgid "Enable extra Tuning" msgid "Enable extra Tuning"
msgstr "Bật tinh chỉnh bổ sung (Extra Tuning)" msgstr "Bật tinh chỉnh bổ sung"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:64 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:64
msgid "Enable macOS compatible shares" msgid "Enable macOS compatible shares"
@@ -93,20 +94,22 @@ msgstr ""
"máy khách ghi vào cùng một tệp, cùng lúc!" "máy khách ghi vào cùng một tệp, cùng lúc!"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:65 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:65
#, fuzzy
msgid "" msgid ""
"Enables Apple's AAPL extension globally and adds macOS compatibility options " "Enables Apple's AAPL extension globally and adds macOS compatibility options "
"to all shares." "to all shares."
msgstr "" msgstr ""
"Kích hoạt phần mở rộng AAPL của Apple toàn cầu và thêm các tùy chọn tương " "Kích hoạt phần mở rộng AAPL của Apple cho toàn hệ thống và thêm các tùy chọn "
"thích macOS cho tất cả các chia sẻ." "tương thích macOS cho tất cả các chia sẻ."
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:115 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:115
#, fuzzy
msgid "Force Root" msgid "Force Root"
msgstr "Bắt buộc Root" msgstr "Bắt buộc Root"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:61 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:61
msgid "Force synchronous I/O" msgid "Force synchronous I/O"
msgstr "Bắt buộc I/O đồng bộ" msgstr "Bắt buộc dùng đồng bộ I/O"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:31 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:31
msgid "General Settings" msgid "General Settings"
@@ -131,8 +134,8 @@ msgstr "Giao diện"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:35
msgid "Listen only on the given interface or, if unspecified, on lan" msgid "Listen only on the given interface or, if unspecified, on lan"
msgstr "" msgstr ""
"Chỉ lắng nghe trên giao diện đã chỉ định hoặc, nếu không được chỉ định, trên " "Chỉ lắng nghe trên giao diện đã chỉ định hoặc, nếu không được chỉ định, chỉ "
"LAN" "lắng nghe trên LAN"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:98
msgid "Name" msgid "Name"
@@ -148,8 +151,8 @@ msgid ""
"On lower-end devices may increase speeds, by forcing synchronous I/O instead " "On lower-end devices may increase speeds, by forcing synchronous I/O instead "
"of the default asynchronous." "of the default asynchronous."
msgstr "" msgstr ""
"Trên các thiết bị cấu hình thấp hơn, việc bắt buộc I/O đồng bộ thay vì mặc " "Việc bắt buộc I/O đồng bộ thay vì mặc định là bất đồng bộ có thể tăng tốc độ "
"định là bất đồng bộ có thể tăng tốc độ." "trên các thiết bị cấu hình thấp hơn."
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:99 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:99
msgid "Path" msgid "Path"
@@ -161,7 +164,7 @@ msgid ""
"mounted device." "mounted device."
msgstr "" msgstr ""
"Vui lòng thêm các thư mục để chia sẻ. Mỗi thư mục tương ứng với một thư mục " "Vui lòng thêm các thư mục để chia sẻ. Mỗi thư mục tương ứng với một thư mục "
"trên một thiết bị đã được gắn kết (mount)." "trên một thiết bị lưu trữ đã được gắn kết (mounted device)."
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:109 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:109
msgid "Read-only" msgid "Read-only"
@@ -178,13 +181,13 @@ msgid ""
"('|') should not be changed. They get their values from the 'General " "('|') should not be changed. They get their values from the 'General "
"Settings' tab." "Settings' tab."
msgstr "" msgstr ""
"Đây là nội dung của tệp '/etc/samba/smb.conf.template' mà cấu hình samba của " "Cấu hình samba của bạn sẽ được tạo ra từ nội dung của tệp '/etc/samba/"
"bạn sẽ được tạo ra từ đó. Các giá trị được bao quanh bởi dấu | không nên " "smb.conf.template'. Các giá trị được bao quanh bởi dấu ('|') không nên được "
"được thay đổi. Chúng lấy giá trị của chúng từ tab 'Cài đặt chung'." "thay đổi. Chúng lấy giá trị từ tab 'Cài đặt chung'."
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:153 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:153
msgid "Time-machine size in GB" msgid "Time-machine size in GB"
msgstr "Kích thước của Time-machine bằng GB" msgstr "Kích thước của Time-machine đo bằng GB"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:148 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:148
msgid "Vfs objects" msgid "Vfs objects"
+4 -5
View File
@@ -6,9 +6,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-10 03:40+0200\n" "POT-Creation-Date: 2009-06-10 03:40+0200\n"
"PO-Revision-Date: 2026-08-31 06:44+0000\n" "PO-Revision-Date: 2026-10-27 15:07+0000\n"
"Last-Translator: Hosted Weblate user 54392 " "Last-Translator: nKsyn <nksyn@users.noreply.hosted.weblate.org>\n"
"<hamburger2048@users.noreply.hosted.weblate.org>\n"
"Language-Team: Chinese (Simplified Han script) <https://hosted.weblate.org/" "Language-Team: Chinese (Simplified Han script) <https://hosted.weblate.org/"
"projects/openwrt/luciapplicationssamba4/zh_Hans/>\n" "projects/openwrt/luciapplicationssamba4/zh_Hans/>\n"
"Language: zh_Hans\n" "Language: zh_Hans\n"
@@ -16,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.9.dev0\n" "X-Generator: Weblate 2026.11.dev0\n"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:120
msgid "Allow guests" msgid "Allow guests"
@@ -30,7 +29,7 @@ msgstr "允许旧(不安全)的协议/身份验证"
msgid "" msgid ""
"Allow legacy smb(v1)/Lanman connections, needed for older devices without " "Allow legacy smb(v1)/Lanman connections, needed for older devices without "
"smb(v2.1/3) support." "smb(v2.1/3) support."
msgstr "允许不支持smb(v2.1/3)的旧设备使用旧的smb(v1)/Lanman连接。" msgstr "允许不支持smb(v2.1/3)的老设备使用过时的smb(v1)/Lanman连接。"
#: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:117 #: applications/luci-app-samba4/htdocs/luci-static/resources/view/samba4.js:117
msgid "Allowed users" msgid "Allowed users"
+1 -1
View File
@@ -9,7 +9,7 @@ LUCI_PKGARCH:=all
PKG_LICENSE:=Apache-2.0 PKG_LICENSE:=Apache-2.0
PKG_VERSION:=1.0 PKG_VERSION:=1.0
PKG_RELEASE:=5 PKG_RELEASE:=6
PKG_MAINTAINER:=Meng Zhuo <mengzhuo@iscas.ac.cn> PKG_MAINTAINER:=Meng Zhuo <mengzhuo@iscas.ac.cn>
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
+5 -5
View File
@@ -3,12 +3,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Language: de\n" "Language: de\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" "Last-Translator: Dirk Brenken <dibdot@users.noreply.hosted.weblate.org>\n"
"Language-Team: German <https://hosted.weblate.org/projects/openwrt/" "Language-Team: German <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssfp-info/de/>\n" "luciapplicationssfp-info/de/>\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"PO-Revision-Date: 2026-09-08 12:39+0000\n" "PO-Revision-Date: 2026-11-04 16:54+0000\n"
"X-Generator: Weblate 2026.9.1\n" "X-Generator: Weblate 2026.11.1.dev0\n"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:68 #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:68
msgid "Bias Current" msgid "Bias Current"
@@ -24,7 +24,7 @@ msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:61 #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:61
msgid "Interface" msgid "Interface"
msgstr "Interface" msgstr "Schnittstelle"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:106 #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:106
msgid "No SFP/QSFP modules detected." msgid "No SFP/QSFP modules detected."
@@ -100,7 +100,7 @@ msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:63 #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:63
msgid "Type" msgid "Type"
msgstr "" msgstr "Typ"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:62 #: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:62
msgid "Vendor" msgid "Vendor"
+119
View File
@@ -0,0 +1,119 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Language: fr\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: French <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssfp-info/fr/>\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"PO-Revision-Date: 2026-11-06 10:11+0000\n"
"X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:68
msgid "Bias Current"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:65
msgid "Date Code"
msgstr ""
#: applications/luci-app-sfp-info/root/usr/share/rpcd/acl.d/luci-app-sfp-info.json:3
msgid "Grant ubus access to SFP Info"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:61
msgid "Interface"
msgstr "Interface"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:106
msgid "No SFP/QSFP modules detected."
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:205
msgid "Normal"
msgstr "Normal"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:64
msgid "Part Number"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:70
msgid "RX Power"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:182
msgid "RX power high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:183
msgid "RX power low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:46
msgid "Range"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:78
msgid "SFP / QSFP Transceiver Information"
msgstr ""
#: applications/luci-app-sfp-info/root/usr/share/luci/menu.d/luci-app-sfp-info.json:3
msgid "SFP Info"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:71
msgid "Status"
msgstr "État"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:69
msgid "TX Power"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:178
msgid "TX bias high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:179
msgid "TX bias low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:180
msgid "TX power high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:181
msgid "TX power low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:66
msgid "Temperature"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:174
msgid "Temperature high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:175
msgid "Temperature low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:63
msgid "Type"
msgstr "Type"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:62
msgid "Vendor"
msgstr "Vendeur"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:67
msgid "Voltage"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:176
msgid "Voltage high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:177
msgid "Voltage low"
msgstr ""
+119
View File
@@ -0,0 +1,119 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Language: hu\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Martin Olmer <izflek@users.noreply.hosted.weblate.org>\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationssfp-info/hu/>\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"PO-Revision-Date: 2026-11-05 09:36+0000\n"
"X-Generator: Weblate 2026.11.2.dev0\n"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:68
msgid "Bias Current"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:65
msgid "Date Code"
msgstr ""
#: applications/luci-app-sfp-info/root/usr/share/rpcd/acl.d/luci-app-sfp-info.json:3
msgid "Grant ubus access to SFP Info"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:61
msgid "Interface"
msgstr "Interfész"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:106
msgid "No SFP/QSFP modules detected."
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:205
msgid "Normal"
msgstr "Normál"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:64
msgid "Part Number"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:70
msgid "RX Power"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:182
msgid "RX power high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:183
msgid "RX power low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:46
msgid "Range"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:78
msgid "SFP / QSFP Transceiver Information"
msgstr ""
#: applications/luci-app-sfp-info/root/usr/share/luci/menu.d/luci-app-sfp-info.json:3
msgid "SFP Info"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:71
msgid "Status"
msgstr "Állapot"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:69
msgid "TX Power"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:178
msgid "TX bias high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:179
msgid "TX bias low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:180
msgid "TX power high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:181
msgid "TX power low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:66
msgid "Temperature"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:174
msgid "Temperature high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:175
msgid "Temperature low"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:63
msgid "Type"
msgstr "Típus"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:62
msgid "Vendor"
msgstr "Gyártó"
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:67
msgid "Voltage"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:176
msgid "Voltage high"
msgstr ""
#: applications/luci-app-sfp-info/htdocs/luci-static/resources/view/sfp-info/main.js:177
msgid "Voltage low"
msgstr ""
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff. Show more