diff --git a/6in4/Makefile b/6in4/Makefile new file mode 100755 index 000000000..d0f2ad30c --- /dev/null +++ b/6in4/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (C) 2010-2015 OpenWrt.org +# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# - Added gateway setting +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=6in4 +PKG_VERSION:=270 +PKG_RELEASE:=2 +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/6in4 + SECTION:=net + CATEGORY:=Network + DEPENDS:=@IPV6 +kmod-sit +uclient-fetch + TITLE:=IPv6-in-IPv4 configuration support + MAINTAINER:=Jo-Philipp Wich + PKGARCH:=all +endef + +define Package/6in4/description +Provides support for 6in4 tunnels in /etc/config/network. +Refer to http://wiki.openwrt.org/doc/uci/network for +configuration details. +endef + +define Build/Compile +endef + +define Build/Configure +endef + +define Package/6in4/install + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/6in4.sh $(1)/lib/netifd/proto/6in4.sh +endef + +$(eval $(call BuildPackage,6in4)) diff --git a/6in4/files/6in4.sh b/6in4/files/6in4.sh new file mode 100755 index 000000000..cf17c86d8 --- /dev/null +++ b/6in4/files/6in4.sh @@ -0,0 +1,149 @@ +#!/bin/sh +# 6in4.sh - IPv6-in-IPv4 tunnel backend +# Copyright (c) 2010-2015 OpenWrt.org + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . /lib/functions/network.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_6in4_update() { + sh -c ' + timeout=5 + + (while [ $((timeout--)) -gt 0 ]; do + sleep 1 + kill -0 $$ || exit 0 + done; kill -9 $$) 2>/dev/null & + + exec "$@" + ' "$1" "$@" +} + +proto_6in4_add_prefix() { + append "$3" "$1" +} + +proto_6in4_setup() { + local cfg="$1" + local iface="$2" + local link="6in4-$cfg" + + local mtu ttl tos ipaddr peeraddr ip6addr ip6prefix ip6prefixes tunlink tunnelid username password updatekey gateway + json_get_vars mtu ttl tos ipaddr peeraddr ip6addr tunlink tunnelid username password updatekey gateway + json_for_each_item proto_6in4_add_prefix ip6prefix ip6prefixes + + [ -z "$peeraddr" ] && { + proto_notify_error "$cfg" "MISSING_ADDRESS" + proto_block_restart "$cfg" + return + } + + [ -n "$tunlink" ] && ( proto_add_host_dependency "$cfg" "$peeraddr" "$tunlink" ) + + [ -z "$ipaddr" ] && { + local wanif="$tunlink" + if [ -z "$wanif" ] && ! network_find_wan wanif; then + proto_notify_error "$cfg" "NO_WAN_LINK" + return + fi + + if ! network_get_ipaddr ipaddr "$wanif"; then + proto_notify_error "$cfg" "NO_WAN_LINK" + return + fi + } + + proto_init_update "$link" 1 + + [ -n "$ip6addr" ] && { + local local6="${ip6addr%%/*}" + local mask6="${ip6addr##*/}" + [[ "$local6" = "$mask6" ]] && mask6= + proto_add_ipv6_address "$local6" "$mask6" + proto_add_ipv6_route "::" 0 "" "" "" "$local6/$mask6" + } + + [ -n "$gateway" ] && { + proto_add_ipv6_route "::" 0 "$gateway" + } + + for ip6prefix in $ip6prefixes; do + proto_add_ipv6_prefix "$ip6prefix" + proto_add_ipv6_route "::" 0 "" "" "" "$ip6prefix" + done + + proto_add_tunnel + json_add_string mode sit + json_add_int mtu "${mtu:-1280}" + json_add_int ttl "${ttl:-64}" + [ -n "$tos" ] && json_add_string tos "$tos" + json_add_string local "$ipaddr" + json_add_string remote "$peeraddr" + [ -n "$tunlink" ] && json_add_string link "$tunlink" + proto_close_tunnel + + proto_send_update "$cfg" + + [ -n "$tunnelid" -a -n "$username" -a \( -n "$password" -o -n "$updatekey" \) ] && { + [ -n "$updatekey" ] && password="$updatekey" + + local http="http" + local urlget="uclient-fetch" + local urlget_opts="-qO-" + local ca_path="${SSL_CERT_DIR:-/etc/ssl/certs}" + + [ -f /lib/libustream-ssl.so ] && http=https + [ "$http" = "https" -a -z "$(find $ca_path -name "*.0" 2>/dev/null)" ] && { + urlget_opts="$urlget_opts --no-check-certificate" + } + + local url="$http://ipv4.tunnelbroker.net/nic/update?hostname=$tunnelid" + local try=0 + local max=3 + + ( + set -o pipefail + while [ $((++try)) -le $max ]; do + if proto_6in4_update $urlget $urlget_opts --user="$username" --password="$password" "$url" 2>&1 | \ + sed -e 's,^Killed$,timeout,' -e "s,^,update $try/$max: ," | \ + logger -t "$link"; + then + logger -t "$link" "updated" + return 0 + fi + sleep 5 + done + logger -t "$link" "update failed" + ) + } +} + +proto_6in4_teardown() { + local cfg="$1" +} + +proto_6in4_init_config() { + no_device=1 + available=1 + + proto_config_add_string "ipaddr" + proto_config_add_string "ip6addr" + proto_config_add_array "ip6prefix" + proto_config_add_string "peeraddr" + proto_config_add_string "tunlink" + proto_config_add_string "tunnelid" + proto_config_add_string "username" + proto_config_add_string "password" + proto_config_add_string "updatekey" + proto_config_add_string "gateway" + proto_config_add_int "mtu" + proto_config_add_int "ttl" + proto_config_add_string "tos" +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol 6in4 +} diff --git a/aquantia/Makefile b/aquantia/Makefile new file mode 100755 index 000000000..f99bb0c90 --- /dev/null +++ b/aquantia/Makefile @@ -0,0 +1,41 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=kmod-aquantia +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/phy-aquantia + SUBMENU:=Network Devices + TITLE:=aQuantia device support + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core +kmod-libphy + KCONFIG:=CONFIG_AQUANTIA_PHY + HIDDEN:=1 + FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia.ko + AUTOLOAD:=$(call AutoProbe,aquantia) +endef + +define KernelPackage/phy-aquantia/description + Kernel modules for aQuantia Ethernet adapters. +endef + +define KernelPackage/atlantic + SUBMENU:=Network Devices + TITLE:=aQuantia AQtion(tm) Support + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 @KERNEL_5_4 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-phy-aquantia + KCONFIG:=CONFIG_AQTION + FILES:=$(LINUX_DIR)/drivers/net/ethernet/aquantia/atlantic/atlantic.ko + AUTOLOAD:=$(call AutoProbe,atlantic) +endef + +define KernelPackage/atlantic/description + Kernel modules for the aQuantia AQtion(tm) Ethernet card +endef + +define Build/Compile +endef + +$(eval $(call KernelPackage,phy-aquantia)) +$(eval $(call KernelPackage,atlantic)) \ No newline at end of file diff --git a/bcm27xx-eeprom/Makefile b/bcm27xx-eeprom/Makefile new file mode 100755 index 000000000..b114ee11a --- /dev/null +++ b/bcm27xx-eeprom/Makefile @@ -0,0 +1,59 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=bcm27xx-eeprom +PKG_VERSION:=v2022.04.26-138a1 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)? +PKG_HASH:=7c54839e68f226c5853fb63c8a1539b729d84b2e6bac311a51766c601d10a413 + +PKG_LICENSE:=BSD-3-Clause Custom +PKG_LICENSE_FILES:=LICENSE + +PKG_MAINTAINER:=Álvaro Fernández Rojas + +include $(INCLUDE_DIR)/package.mk + +TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS) +TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS) + +define Package/bcm27xx-eeprom + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=bcm27xx-userland +blkid +coreutils +coreutils-od +pciutils +python3-light + TITLE:=BCM27xx EEPROM tools +endef + +define Package/bcm27xx-eeprom/description + BCM27xx EEPROM tools. +endef + +define Build/Compile + true +endef + +define Package/bcm27xx-eeprom/conffiles +/etc/bcm27xx-eeprom.conf +endef + +define Package/bcm27xx-eeprom/install + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) $(PKG_BUILD_DIR)/rpi-eeprom-update-default $(1)/etc/bcm27xx-eeprom.conf + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-config $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-digest $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-update $(1)/usr/bin + + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader + $(CP) $(PKG_BUILD_DIR)/firmware/release-notes.md $(1)/lib/firmware/raspberrypi/bootloader + + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/critical + $(CP) $(PKG_BUILD_DIR)/firmware/critical/ $(1)/lib/firmware/raspberrypi/bootloader/ + + $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/stable + $(CP) $(PKG_BUILD_DIR)/firmware/stable/ $(1)/lib/firmware/raspberrypi/bootloader/ +endef + +$(eval $(call BuildPackage,bcm27xx-eeprom)) diff --git a/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch new file mode 100755 index 000000000..7fc10a8a5 --- /dev/null +++ b/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch @@ -0,0 +1,45 @@ +From da37f7b051fe6833e25e78184cc9217dd4379187 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Mon, 23 Mar 2020 10:10:55 +0100 +Subject: [PATCH] rpi-eeprom-update: OpenWrt defaults +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-update | 6 +++--- + rpi-eeprom-update-default | 5 +++-- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- a/rpi-eeprom-update ++++ b/rpi-eeprom-update +@@ -24,12 +24,12 @@ else + fi + + # Selects the release sub-directory +-FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default} ++FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-stable} + FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}} +-FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup} ++FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-${FIRMWARE_ROOT}/backup} + ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1} + RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin} + BOOTFS=${BOOTFS:-/boot} + CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0} + RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}" + +--- a/rpi-eeprom-update-default ++++ b/rpi-eeprom-update-default +@@ -1,8 +1,9 @@ + + FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader +-FIRMWARE_RELEASE_STATUS="critical" ++FIRMWARE_RELEASE_STATUS="stable" + FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}" +-FIRMWARE_BACKUP_DIR="/var/lib/raspberrypi/bootloader/backup" ++FIRMWARE_BACKUP_DIR="${FIRMWARE_ROOT}/backup" + BOOTFS=/boot + USE_FLASHROM=0 + EEPROM_CONFIG_HOOK= ++VCMAILBOX=/usr/bin/vcmailbox diff --git a/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch new file mode 100755 index 000000000..f24a9c3f1 --- /dev/null +++ b/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch @@ -0,0 +1,26 @@ +From 6674d49dea0104031b3f54df4c7a356dc4307bb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 25 Mar 2020 20:58:35 +0100 +Subject: [PATCH] rpi-eeprom-update: change default include path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-update | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/rpi-eeprom-update ++++ b/rpi-eeprom-update +@@ -6,8 +6,8 @@ set -e + + script_dir=$(cd "$(dirname "$0")" && pwd) + +-if [ -f /etc/default/rpi-eeprom-update ]; then +- . /etc/default/rpi-eeprom-update ++if [ -f /etc/bcm27xx-eeprom.conf ]; then ++ . /etc/bcm27xx-eeprom.conf + fi + + LOCAL_MODE=0 diff --git a/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch new file mode 100755 index 000000000..5872f12da --- /dev/null +++ b/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch @@ -0,0 +1,33 @@ +From 8376ac74390af0ad736c88615e128b82a75eebc0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Fri, 19 Feb 2021 10:54:23 +0100 +Subject: [PATCH] rpi-eeprom-update: chmod silent (-f) is not supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + rpi-eeprom-update | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/rpi-eeprom-update ++++ b/rpi-eeprom-update +@@ -200,7 +200,7 @@ applyRecoveryUpdate() + || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" + + # For NFS mounts ensure that the files are readable to the TFTP user +- chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ ++ chmod go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ + || die "Failed to set permissions on eeprom update files" + fi + +@@ -211,7 +211,7 @@ applyRecoveryUpdate() + || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" + + # For NFS mounts ensure that the files are readable to the TFTP user +- chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ ++ chmod go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ + || die "Failed to set permissions on eeprom update files" + fi + diff --git a/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch b/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch new file mode 100755 index 000000000..6feb7602c --- /dev/null +++ b/bcm27xx-eeprom/patches/0005-rpi-eeprom-config-change-default-text-editor.patch @@ -0,0 +1,22 @@ +--- a/rpi-eeprom-config ++++ b/rpi-eeprom-config +@@ -166,8 +166,8 @@ def edit_config(eeprom=None): + """ + Implements something like 'git commit' for editing EEPROM configs. + """ +- # Default to nano if $EDITOR is not defined. +- editor = 'nano' ++ # Default to vi if $EDITOR is not defined. ++ editor = 'vi' + if 'EDITOR' in os.environ: + editor = os.environ['EDITOR'] + +@@ -428,7 +428,7 @@ Operating modes: + + To cancel the pending update run 'sudo rpi-eeprom-update -r' + +- The default text editor is nano and may be overridden by setting the 'EDITOR' ++ The default text editor is vi and may be overridden by setting the 'EDITOR' + environment variable and passing '-E' to 'sudo' to preserve the environment. + + 6. Signing the bootloader config file. diff --git a/cryptodev-linux/Makefile b/cryptodev-linux/Makefile new file mode 100755 index 000000000..0c1f63a60 --- /dev/null +++ b/cryptodev-linux/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id$ + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=cryptodev-linux +PKG_VERSION:=1.12 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://codeload.github.com/$(PKG_NAME)/$(PKG_NAME)/tar.gz/$(PKG_NAME)-$(PKG_VERSION)? +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_HASH:=f51c2254749233b1b1d7ec9445158bd709f124f88e1c650fe2faac83c3a81938 +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_MAINTAINER:=Ansuel Smith + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/cryptodev + SUBMENU:=Cryptographic API modules + TITLE:=Driver for cryptographic acceleration + URL:=http://cryptodev-linux.org/ + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + DEPENDS:=+kmod-crypto-authenc +kmod-crypto-hash + FILES:=$(PKG_BUILD_DIR)/cryptodev.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,50,cryptodev) + MODPARAMS.cryptodev:=cryptodev_verbosity=-1 +endef + +define KernelPackage/cryptodev/description + This is a driver for that allows to use the Linux kernel supported + hardware ciphers by user-space applications. +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(KERNEL_MAKE_FLAGS) \ + KERNEL_DIR="$(LINUX_DIR)" +endef + +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR)/usr/include/crypto + $(CP) $(PKG_BUILD_DIR)/crypto/cryptodev.h $(STAGING_DIR)/usr/include/crypto/ +endef + +$(eval $(call KernelPackage,cryptodev)) diff --git a/fullconenat/Makefile b/fullconenat/Makefile new file mode 100755 index 000000000..d49155c7e --- /dev/null +++ b/fullconenat/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (C) 2022 Chion Tang +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=fullconenat +PKG_RELEASE:=9 + +PKG_SOURCE_DATE:=2022-02-13 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/llccd/netfilter-full-cone-nat.git +PKG_SOURCE_VERSION:=108a36cbdca17e68c9e6e7fd5e26156a88f738e8 +PKG_MIRROR_HASH:=00d749235271dee194dcd23c22e6e85207ea90192a62a110b2af0b4e4de1971f + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Chion Tang + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define Package/iptables-mod-fullconenat + SUBMENU:=Firewall + SECTION:=net + CATEGORY:=Network + TITLE:=FULLCONENAT iptables extension + DEPENDS:=+iptables +kmod-ipt-fullconenat +endef + +define Package/iptables-mod-fullconenat/install + $(INSTALL_DIR) $(1)/usr/lib/iptables + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libipt_FULLCONENAT.so $(1)/usr/lib/iptables +endef + +define KernelPackage/ipt-fullconenat + SUBMENU:=Netfilter Extensions + TITLE:=FULLCONENAT netfilter module + DEPENDS:=+kmod-nf-ipt +kmod-nf-nat + KCONFIG:= \ + CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y + FILES:=$(PKG_BUILD_DIR)/xt_FULLCONENAT.ko +endef + +include $(INCLUDE_DIR)/kernel-defaults.mk + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(BUILDFLAGS)" \ + modules + $(call Build/Compile/Default) +endef + +$(eval $(call KernelPackage,ipt-fullconenat)) +$(eval $(call BuildPackage,iptables-mod-fullconenat)) diff --git a/fullconenat/patches/001-fix-init-Repeat-definition.patch b/fullconenat/patches/001-fix-init-Repeat-definition.patch new file mode 100755 index 000000000..67c9332c8 --- /dev/null +++ b/fullconenat/patches/001-fix-init-Repeat-definition.patch @@ -0,0 +1,20 @@ +--- a/libip6t_FULLCONENAT.c ++++ b/libip6t_FULLCONENAT.c +@@ -214,6 +214,7 @@ static struct xtables_target fullconenat_tg_reg = { + .x6_options = FULLCONENAT_opts, + }; + ++#define _init __attribute__((constructor)) _INIT + void _init(void) + { + xtables_register_target(&fullconenat_tg_reg); +--- a/libipt_FULLCONENAT.c ++++ b/libipt_FULLCONENAT.c +@@ -235,6 +235,7 @@ static struct xtables_target fullconenat_tg_reg = { + .x6_options = FULLCONENAT_opts, + }; + ++#define _init __attribute__((constructor)) _INIT + void _init(void) + { + xtables_register_target(&fullconenat_tg_reg); diff --git a/fullconenat/patches/001-linux-6.1-support.patch b/fullconenat/patches/001-linux-6.1-support.patch new file mode 100755 index 000000000..41721fb5c --- /dev/null +++ b/fullconenat/patches/001-linux-6.1-support.patch @@ -0,0 +1,26 @@ +--- a/xt_FULLCONENAT.c ++++ b/xt_FULLCONENAT.c +@@ -325,7 +325,11 @@ + /* for now we do the same thing for both --random and --random-fully */ + + /* select a random starting point */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ start = (uint16_t)(get_random_u32() % (u32)range_size); ++#else + start = (uint16_t)(prandom_u32() % (u32)range_size); ++#endif + } else { + + if ((original_port >= min && original_port <= min + range_size - 1) +@@ -995,7 +999,11 @@ + /* for now we do the same thing for both --random and --random-fully */ + + /* select a random starting point */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++ start = (uint16_t)(get_random_u32() % (u32)range_size); ++#else + start = (uint16_t)(prandom_u32() % (u32)range_size); ++#endif + } else { + + if ((original_port >= min && original_port <= min + range_size - 1) diff --git a/fullconenat/src/Makefile b/fullconenat/src/Makefile new file mode 100755 index 000000000..b2f88db33 --- /dev/null +++ b/fullconenat/src/Makefile @@ -0,0 +1,6 @@ +libipt_FULLCONENAT.so: libipt_FULLCONENAT.o + $(CC) -shared -lxtables -o $@ $^; +libipt_FULLCONENAT.o: libipt_FULLCONENAT.c + $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; + +obj-m += xt_FULLCONENAT.o diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 1047d5b6b..1f5ecffcc 100755 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -37,7 +37,8 @@ PKG_CPE_ID:=cpe:/a:golang:go PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_DIR:=$(BUILD_DIR)/go-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 +#PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 PKG_GO_PREFIX:=/usr PKG_GO_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR) diff --git a/https-dns-proxy/Makefile b/https-dns-proxy/Makefile old mode 100644 new mode 100755 index ce7d70eeb..abfb4be7a --- a/https-dns-proxy/Makefile +++ b/https-dns-proxy/Makefile @@ -1,14 +1,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=https-dns-proxy -PKG_VERSION:=2023-05-25 -PKG_RELEASE:=2 +PKG_VERSION:=2021-11-22 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy/ -PKG_SOURCE_DATE:=$(PKG_VERSION) -PKG_SOURCE_VERSION:=d03e11572562f008f68df217a7378628f1bb7b79 -PKG_MIRROR_HASH:=5af3683c48bc9e493ca2761a6f7ee756431692a695d6008f61b8b92431036dca +PKG_SOURCE_DATE:=2021-11-22 +PKG_SOURCE_VERSION:=9336fd6272d67e8bb6e304fa54f3139a3d26f08f +PKG_MIRROR_HASH:=60b1ddabaf1db3a9ee19f3294a1df714364d580cef5e3c2161363c371a557456 PKG_MAINTAINER:=Stan Grishin PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE @@ -16,20 +16,20 @@ PKG_LICENSE_FILES:=LICENSE include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/cmake.mk -CMAKE_OPTIONS += -DCLANG_TIDY_EXE= -DGIT_VERSION=$(PKG_VERSION)-$(PKG_RELEASE) +CMAKE_OPTIONS += -DCLANG_TIDY_EXE= define Package/https-dns-proxy SECTION:=net CATEGORY:=Network TITLE:=DNS Over HTTPS Proxy URL:=https://docs.openwrt.melmac.net/https-dns-proxy/ - DEPENDS:=+libcares +libcurl +libev +ca-bundle +jsonfilter + DEPENDS:=+libcares +libcurl +libev +ca-bundle CONFLICTS:=https_dns_proxy endef define Package/https-dns-proxy/description -Light-weight DNS-over-HTTPS, non-caching translation proxy for the RFC 8484 DoH standard. -It receives regular (UDP) DNS requests and resolves them via DoH resolver. +https-dns-proxy is a light-weight DNS<-->HTTPS, non-caching translation proxy for the RFC 8484 DoH standard. +It receives regular (UDP) DNS requests and issues them via DoH. Please see https://docs.openwrt.melmac.net/https-dns-proxy/ for more information. endef @@ -40,14 +40,12 @@ endef define Package/https-dns-proxy/install $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DIR) ${1}/etc/config $(INSTALL_DIR) $(1)/etc/hotplug.d/iface - $(INSTALL_DIR) $(1)/etc/uci-defaults/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/https_dns_proxy $(1)/usr/sbin/https-dns-proxy $(INSTALL_BIN) ./files/https-dns-proxy.init $(1)/etc/init.d/https-dns-proxy - $(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/https-dns-proxy + $(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/https-dns-proxy $(INSTALL_CONF) ./files/https-dns-proxy.config $(1)/etc/config/https-dns-proxy - $(INSTALL_BIN) ./files/https-dns-proxy.defaults $(1)/etc/uci-defaults/50-https-dns-proxy-migrate-options.sh endef $(eval $(call BuildPackage,https-dns-proxy)) diff --git a/https-dns-proxy/files/README.md b/https-dns-proxy/files/README.md old mode 100644 new mode 100755 diff --git a/https-dns-proxy/files/https-dns-proxy.config b/https-dns-proxy/files/https-dns-proxy.config old mode 100644 new mode 100755 index 39b807b45..f08e03ca9 --- a/https-dns-proxy/files/https-dns-proxy.config +++ b/https-dns-proxy/files/https-dns-proxy.config @@ -1,7 +1,5 @@ config main 'config' - option canary_domains_icloud '1' - option canary_domains_mozilla '1' - option dnsmasq_config_update '*' + option update_dnsmasq_config '*' option force_dns '1' list force_dns_port '53' list force_dns_port '853' @@ -13,13 +11,12 @@ config main 'config' # list force_dns_port '4434' # list force_dns_port '5443' # list force_dns_port '8443' - option procd_trigger_wan6 '0' config https-dns-proxy option bootstrap_dns '1.1.1.1,1.0.0.1' option resolver_url 'https://cloudflare-dns.com/dns-query' option listen_addr '127.0.0.1' - option listen_port '5053' + option listen_port '5054' option user 'nobody' option group 'nogroup' @@ -27,6 +24,6 @@ config https-dns-proxy option bootstrap_dns '8.8.8.8,8.8.4.4' option resolver_url 'https://dns.google/dns-query' option listen_addr '127.0.0.1' - option listen_port '5054' + option listen_port '5053' option user 'nobody' option group 'nogroup' diff --git a/https-dns-proxy/files/https-dns-proxy.defaults b/https-dns-proxy/files/https-dns-proxy.defaults deleted file mode 100644 index 8321ea99b..000000000 --- a/https-dns-proxy/files/https-dns-proxy.defaults +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - sed -i "s|update_dnsmasq_config|dnsmasq_config_update|" "/etc/config/https-dns-proxy" - sed -i "s|wan6_trigger|procd_trigger_wan6|" "/etc/config/https-dns-proxy" diff --git a/https-dns-proxy/files/https-dns-proxy.hotplug.iface b/https-dns-proxy/files/https-dns-proxy.hotplug.iface old mode 100644 new mode 100755 diff --git a/https-dns-proxy/files/https-dns-proxy.init b/https-dns-proxy/files/https-dns-proxy.init index d63dad9c5..ef0ffc7d2 100755 --- a/https-dns-proxy/files/https-dns-proxy.init +++ b/https-dns-proxy/files/https-dns-proxy.init @@ -1,9 +1,10 @@ #!/bin/sh /etc/rc.common -# Copyright 2019-2022 Stan Grishin (stangri@melmac.ca) -# shellcheck disable=SC1091,SC3043,SC3060 +# Copyright 2019-2020 Stan Grishin (stangri@melmac.net) +# shellcheck disable=SC2039,SC3043,SC3060 +PKG_VERSION='dev-test' # shellcheck disable=SC2034 -START=95 +START=80 # shellcheck disable=SC2034 USE_PROCD=1 @@ -14,60 +15,8 @@ else EXTRA_COMMANDS='version' fi -readonly PKG_VERSION='dev-test' -readonly packageName='https-dns-proxy' -readonly serviceName="$packageName $PKG_VERSION" -readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m' -readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m' readonly PROG=/usr/sbin/https-dns-proxy -readonly BOOTSTRAP_CF='1.1.1.1,1.0.0.1,2606:4700:4700::1111,2606:4700:4700::1001' -readonly BOOTSTRAP_GOOGLE='8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844' -readonly DEFAULT_BOOTSTRAP="${BOOTSTRAP_CF},${BOOTSTRAP_GOOGLE}" -readonly canaryDomainsMozilla='use-application-dns.net' -readonly canaryDomainsiCloud='mask.icloud.com mask-h2.icloud.com' - -str_contains() { [ -n "$1" ] &&[ -n "$2" ] && [ "${1//$2}" != "$1" ]; } -is_mac_address() { expr "$1" : '[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]$' >/dev/null; } -is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; } -is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; } -output() { - local msg memmsg logmsg - local sharedMemoryOutput="/dev/shm/$packageName-output" - [ -t 1 ] && printf "%b" "$@" - msg="${1//$serviceName /service }"; - if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then - [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")" - logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')" - logger -t "$packageName" "$(printf "%b" "$logmsg")" - rm -f "$sharedMemoryOutput" - else - printf "%b" "$msg" >> "$sharedMemoryOutput" - fi -} -output_ok() { output "$_OK_"; } -output_okn() { output "${_OK_}\\n"; } -output_fail() { output "$_FAIL_"; } -output_failn() { output "${_FAIL_}\\n"; } -uci_add_list_if_new() { - local PACKAGE="$1" - local CONFIG="$2" - local OPTION="$3" - local VALUE="$4" - local i - [ -n "$PACKAGE" ] && [ -n "$CONFIG" ] && [ -n "$OPTION" ] && [ -n "$VALUE" ] || return 1 - for i in $(uci_get "$PACKAGE" "$CONFIG" "$OPTION"); do - [ "$i" = "$VALUE" ] && return 0 - done - uci_add_list "$PACKAGE" "$CONFIG" "$OPTION" "$VALUE" -} -uci_changes() { - local PACKAGE="$1" - local CONFIG="$2" - local OPTION="$3" - /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} changes "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}" -} - -dnsmasq_restart() { [ -x /etc/init.d/dnsmasq ] || return 0; /etc/init.d/dnsmasq restart >/dev/null 2>&1; } +dnsmasqConfig=''; forceDNS=''; forceDNSPorts=''; version() { echo "$PKG_VERSION"; } @@ -77,10 +26,11 @@ append_bool() { local section="$1" local option="$2" local value="$3" - local default="${4:-0}" + local default="$4" local _loctmp + [ -z "$default" ] && default="0" config_get_bool _loctmp "$section" "$option" "$default" - [ "$_loctmp" -ne 0 ] && xappend "$value" + [ "$_loctmp" != "0" ] && xappend "$value" } append_parm() { @@ -90,280 +40,180 @@ append_parm() { local default="$4" local _loctmp config_get _loctmp "$section" "$option" "$default" - [ -n "$_loctmp" ] && xappend "$switch $_loctmp" -} - -append_counter() { - local section="$1" - local option="$2" - local switch="$3" - local default="${4:-0}" - local _loctmp i - config_get _loctmp "$section" "$option" "$default" -# shellcheck disable=SC2086,SC2154 - for i in $(seq 1 $_loctmp); do - xappend '-v' - done -} - -append_bootstrap() { - local section="$1" - local option="$2" - local switch="$3" - local default="$4" - local _old_ifs="$IFS" - local _loctmp _newtmp i - config_get _loctmp "$section" "$option" "$default" [ -z "$_loctmp" ] && return 0 - IFS=" ," - for i in $_loctmp; do - if { [ "$ipv6_resolvers_only" -eq 0 ] && is_ipv4 "$i"; } || \ - { [ "$ipv6_resolvers_only" -ne 0 ] && is_ipv6 "$i"; }; then - [ -z "$_newtmp" ] && _newtmp="$i" || _newtmp="${_newtmp},${i}" - fi - done - IFS="$_old_ifs" - [ -n "$_newtmp" ] && xappend "$switch $_newtmp" - [ "$ipv6_resolvers_only" -eq 0 ] && xappend '-4' -} - -boot() { - ubus -t 30 wait_for network.interface 2>/dev/null - rc_procd start_service 'on_boot' + xappend "$switch $_loctmp" } start_instance() { - local cfg="$1" param listen_addr listen_port ipv6_resolvers_only p url iface - - config_get url "$cfg" 'resolver_url' - config_get_bool ipv6_resolvers_only "$cfg" 'use_ipv6_resolvers_only' '0' + local cfg="$1" param listen_addr listen_port i append_parm "$cfg" 'resolver_url' '-r' + append_parm "$cfg" 'polling_interval' '-i' append_parm "$cfg" 'listen_addr' '-a' '127.0.0.1' - append_parm "$cfg" 'listen_port' '-p' "$port" + append_parm "$cfg" 'listen_port' '-p' "$p" append_parm "$cfg" 'dscp_codepoint' '-c' - append_bootstrap "$cfg" 'bootstrap_dns' '-b' "$DEFAULT_BOOTSTRAP" + append_parm "$cfg" 'bootstrap_dns' '-b' append_parm "$cfg" 'user' '-u' 'nobody' append_parm "$cfg" 'group' '-g' 'nogroup' - append_parm "$cfg" 'ca_certs_file' '-C' - append_parm "$cfg" 'polling_interval' '-i' append_parm "$cfg" 'proxy_server' '-t' append_parm "$cfg" 'logfile' '-l' append_bool "$cfg" 'use_http1' '-x' - append_counter "$cfg" 'verbosity' '-v' '0' + config_get_bool ipv6_resolvers_only "$cfg" 'use_ipv6_resolvers_only' '0' + config_get verbosity "$cfg" 'verbosity' '0' + +# shellcheck disable=SC2086,SC2154 + for i in $(seq 1 $verbosity); do + xappend '-v' + done +# shellcheck disable=SC2154 + if [ "$ipv6_resolvers_only" = 0 ]; then + xappend '-4' + fi procd_open_instance # shellcheck disable=SC2086 - procd_set_param command $PROG $param + procd_set_param command ${PROG} ${param} procd_set_param stderr 1 procd_set_param stdout 1 procd_set_param respawn - procd_open_data - json_add_object mdns - procd_add_mdns_service "$packageName" 'udp' "$port" "DNS over HTTPS proxy" - json_close_object - json_add_string url "$url" - if [ "$force_dns" -ne 0 ]; then - json_add_array firewall - for iface in $procd_fw_src_interfaces; do - for p in $force_dns_port; do - if netstat -tuln | grep 'LISTEN' | grep ":${p}" >/dev/null 2>&1 || [ "$p" = '53' ]; then - json_add_object '' - json_add_string type redirect - json_add_string target DNAT - json_add_string src "$iface" - json_add_string proto 'tcp udp' - json_add_string src_dport "$p" - json_add_string dest_port "$p" - json_add_string family any - json_add_boolean reflection 0 - json_close_object - else - json_add_object '' - json_add_string type rule - json_add_string src "$iface" - json_add_string dest '*' - json_add_string proto 'tcp udp' - json_add_string dest_port "$p" - json_add_string target REJECT - json_close_object - fi - done - done - json_close_array - fi - procd_close_data procd_close_instance - if [ "$?" ]; then - config_get listen_addr "$cfg" 'listen_addr' '127.0.0.1' - config_get listen_port "$cfg" 'listen_port' "$port" - if [ "$dnsmasq_config_update" = '*' ]; then - config_load 'dhcp' - config_foreach dnsmasq_doh_server 'dnsmasq' 'add' "${listen_addr}" "${listen_port}" - elif [ -n "$dnsmasq_config_update" ]; then - for i in $dnsmasq_config_update; do - if [ -n "$(uci_get 'dhcp' "@dnsmasq[$i]")" ]; then - dnsmasq_doh_server "@dnsmasq[$i]" 'add' "${listen_addr}" "${listen_port}" - elif [ -n "$(uci_get 'dhcp' "$i")" ]; then - dnsmasq_doh_server "${i}" 'add' "${listen_addr}" "${listen_port}" - fi - done - fi - output_ok - port="$((port+1))" - force_dns=0 - else - output_fail + config_get listen_addr "$cfg" 'listen_addr' '127.0.0.1' + config_get listen_port "$cfg" 'listen_port' "$p" + + if [ "$dnsmasqConfig" = "*" ]; then + config_load 'dhcp' + config_foreach dnsmasq_add_doh_server 'dnsmasq' "${listen_addr}" "${listen_port}" + elif [ -n "$dnsmasqConfig" ]; then + for i in $dnsmasqConfig; do + dnsmasq_add_doh_server "@dnsmasq[${i}]" "${listen_addr}" "${listen_port}" + done fi + p="$((p+1))" } -start_service() { - local canaryDomains canary_domains_icloud canary_domains_mozilla - local dnsmasq_config_update force_dns force_dns_port - local procd_fw_src_interfaces +is_force_dns_active() { iptables-save 2>/dev/null | grep -q -w -- '--dport 53'; } - local port=5053 - output "Starting $serviceName " - config_load "$packageName" - config_get_bool canary_domains_icloud 'config' 'canary_domains_icloud' '1' - config_get_bool canary_domains_mozilla 'config' 'canary_domains_mozilla' '1' - config_get_bool force_dns 'config' 'force_dns' '1' - config_get dnsmasq_config_update 'config' 'dnsmasq_config_update' '*' - config_get force_dns_port 'config' 'force_dns_port' '53 853' - config_get procd_fw_src_interfaces 'config' 'procd_fw_src_interfaces' 'lan' - if [ "$canary_domains_icloud" -ne 0 ]; then - canaryDomains="${canaryDomains:+$canaryDomains }${canaryDomainsiCloud}" - fi - if [ "$canary_domains_mozilla" -ne 0 ]; then - canaryDomains="${canaryDomains:+$canaryDomains }${canaryDomainsMozilla}" - fi +start_service() { + local p=5053 c + config_load 'https-dns-proxy' + config_get dnsmasqConfig 'config' 'update_dnsmasq_config' '*' + config_get_bool forceDNS 'config' 'force_dns' '1' + config_get forceDNSPorts 'config' 'force_dns_port' '53 853' dhcp_backup 'create' - config_load "$packageName" - config_foreach start_instance "$packageName" - if [ -n "$(uci_changes dhcp)" ]; then - uci_commit 'dhcp' - dnsmasq_restart + config_load 'https-dns-proxy' + config_foreach start_instance 'https-dns-proxy' + if [ "$forceDNS" -ne 0 ]; then + procd_open_instance 'main' + procd_set_param command /bin/true + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_open_data + json_add_array firewall + for c in $forceDNSPorts; do + if netstat -tuln | grep 'LISTEN' | grep ":${c}" >/dev/null 2>&1 || [ "$c" = "53" ]; then + json_add_object "" + json_add_string type redirect + json_add_string target DNAT + json_add_string src lan + json_add_string proto "tcp udp" + json_add_string src_dport "$c" + json_add_string dest_port "$c" + json_add_boolean reflection 0 + json_close_object + else + json_add_object "" + json_add_string type rule + json_add_string src lan + json_add_string dest "*" + json_add_string proto "tcp udp" + json_add_string dest_port "$c" + json_add_string target REJECT + json_close_object + fi + done + json_close_array + procd_close_data + procd_close_instance + fi + if [ -n "$(uci -q changes dhcp)" ]; then + uci -q commit dhcp + [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq restart >/dev/null 2>&1 fi - output "\\n" } stop_service() { - local canaryDomains canary_domains_icloud canary_domains_mozilla - local dnsmasq_config_update - local s=0 - output "Stopping $serviceName " - config_load "$packageName" - config_get dnsmasq_config_update 'config' 'dnsmasq_config_update' '*' - config_get_bool canary_domains_icloud 'config' 'canary_domains_icloud' '1' - config_get_bool canary_domains_mozilla 'config' 'canary_domains_mozilla' '1' - if [ "$canary_domains_icloud" -ne 0 ]; then - canaryDomains="${canaryDomains:+$canaryDomains }${canaryDomainsiCloud}" - fi - if [ "$canary_domains_mozilla" -ne 0 ]; then - canaryDomains="${canaryDomains:+$canaryDomains }${canaryDomainsMozilla}" - fi + config_load 'https-dns-proxy' + config_get dnsmasqConfig 'config' 'update_dnsmasq_config' '*' dhcp_backup 'restore' - if [ -n "$(uci_changes dhcp)" ]; then - uci_commit 'dhcp' - dnsmasq_restart || s=1 + if [ -n "$(uci -q changes dhcp)" ]; then + uci -q commit dhcp + [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq restart >/dev/null 2>&1 fi -# shellcheck disable=SC2015 - [ "$s" -eq 0 ] && output_okn || output_failn } -# shellcheck disable=SC1091 service_triggers() { - local wan wan6 i - local procd_trigger_wan6 - config_load "$packageName" - config_get_bool procd_trigger_wan6 'config' 'procd_trigger_wan6' '0' - . /lib/functions/network.sh - network_flush_cache - network_find_wan wan - wan="${wan:-wan}" - if [ "$procd_trigger_wan6" -ne 0 ]; then - network_find_wan6 wan6 - wan6="${wan6:-wan6}" - fi - for i in "$wan" "$wan6"; do - [ -n "$i" ] && procd_add_interface_trigger "interface.*" "$i" "/etc/init.d/${packageName}" restart - done - procd_add_config_trigger "config.change" "$packageName" "/etc/init.d/${packageName}" reload + procd_add_config_trigger "config.change" "https-dns-proxy" /etc/init.d/https-dns-proxy reload } service_started() { procd_set_config_changed firewall; } service_stopped() { procd_set_config_changed firewall; } -restart() { procd_send_signal "$packageName"; rc_procd start_service; } -dnsmasq_doh_server() { - local cfg="$1" param="$2" address="${3:-127.0.0.1}" port="$4" i - case "$param" in - add) - if [ "$force_dns" -ne 0 ]; then - for i in $canaryDomains; do - uci_add_list_if_new 'dhcp' "$cfg" 'server' "/${i}/" - done - fi - case $address in - 0.0.0.0|::ffff:0.0.0.0) address='127.0.0.1';; - ::) address='::1';; - esac - uci_add_list_if_new 'dhcp' "$cfg" 'server' "${address}#${port}" - ;; - remove) - eval "$(ubus call service list "{ 'verbose': true, 'name': '$packageName' }" | jsonfilter -F '# ' -e 'TUPLES=@[*].instances[*].command[4,6]')" - for i in $TUPLES; do - uci_remove_list 'dhcp' "$cfg" 'server' "$i" - done - for i in $canaryDomains; do - uci_remove_list 'dhcp' "$cfg" 'server' "/${i}/" - done - ;; +dnsmasq_add_doh_server() { + local cfg="$1" address="$2" port="$3" + case $address in + 0.0.0.0|::ffff:0.0.0.0) address='127.0.0.1';; + ::) address='::1';; esac + uci -q del_list "dhcp.${cfg}.server=${address}#${port}" + uci -q add_list "dhcp.${cfg}.server=${address}#${port}" } dnsmasq_create_server_backup() { - local cfg="$1" i - [ -n "$(uci_get 'dhcp' "$cfg")" ] || return 1 - if [ -z "$(uci_get 'dhcp' "$cfg" 'doh_backup_noresolv')" ]; then - if [ -z "$(uci_get 'dhcp' "$cfg" 'noresolv')" ]; then - uci_set 'dhcp' "$cfg" 'doh_backup_noresolv' '-1' - else - uci_set 'dhcp' "$cfg" 'doh_backup_noresolv' "$(uci_get 'dhcp' "$cfg" noresolv)" + local cfg="$1" + local i + uci -q get "dhcp.${cfg}" >/dev/null || return 1 + if ! uci -q get "dhcp.${cfg}.doh_backup_noresolv" >/dev/null; then + if [ -z "$(uci -q get "dhcp.${cfg}.noresolv")" ]; then + uci -q set "dhcp.${cfg}.noresolv=1" + uci -q set "dhcp.${cfg}.doh_backup_noresolv=-1" + elif [ "$(uci -q get "dhcp.${cfg}.noresolv")" != "1" ]; then + uci -q set "dhcp.${cfg}.noresolv=1" + uci -q set "dhcp.${cfg}.doh_backup_noresolv=0" fi - uci_set 'dhcp' "$cfg" 'noresolv' 1 fi - if [ -z "$(uci_get 'dhcp' "$cfg" 'doh_backup_server')" ]; then - if [ -z "$(uci_get 'dhcp' "$cfg" 'server')" ]; then - uci_add_list 'dhcp' "$cfg" 'doh_backup_server' "" + if ! uci -q get "dhcp.${cfg}.doh_backup_server" >/dev/null; then + if [ -z "$(uci -q get "dhcp.${cfg}.server")" ]; then + uci -q add_list "dhcp.${cfg}.doh_backup_server=" fi - for i in $(uci_get 'dhcp' "$cfg" 'server'); do - uci_add_list 'dhcp' "$cfg" 'doh_backup_server' "$i" + for i in $(uci -q get "dhcp.${cfg}.server"); do + uci -q add_list "dhcp.${cfg}.doh_backup_server=$i" if [ "$i" = "$(echo "$i" | tr -d /\#)" ]; then - uci_remove_list 'dhcp' "$cfg" 'server' "$i" + uci -q del_list "dhcp.${cfg}.server=$i" fi done + uci -q del_list "dhcp.${cfg}.server=127.0.0.1#5353" fi return 0 } dnsmasq_restore_server_backup() { - local cfg="$1" i - [ -n "$(uci_get 'dhcp' "$cfg")" ] || return 0 - if [ -n "$(uci_get 'dhcp' "$cfg" 'doh_backup_noresolv')" ]; then - if [ "$(uci_get 'dhcp' "$cfg" 'doh_backup_noresolv')" = "-1" ]; then - uci_remove 'dhcp' "$cfg" 'noresolv' - else - uci_set 'dhcp' "$cfg" 'noresolv' "$(uci_get 'dhcp' "$cfg" 'doh_backup_noresolv')" + local cfg="$1" + local i + uci -q get "dhcp.${cfg}" >/dev/null || return 0 + if uci -q get "dhcp.${cfg}.doh_backup_noresolv" >/dev/null; then + if [ "$(uci -q get "dhcp.${cfg}.doh_backup_noresolv")" = "0" ]; then + uci -q set "dhcp.${cfg}.noresolv=0" + else + uci -q del "dhcp.${cfg}.noresolv" fi - uci_remove 'dhcp' "$cfg" 'doh_backup_noresolv' + uci -q del "dhcp.${cfg}.doh_backup_noresolv" fi - if uci_get 'dhcp' "$cfg" 'doh_backup_server' >/dev/null 2>&1; then - dnsmasq_doh_server "$cfg" 'remove' - for i in $(uci_get 'dhcp' "$cfg" 'doh_backup_server'); do - uci_add_list_if_new 'dhcp' "$cfg" 'server' "$i" + if uci -q get "dhcp.${cfg}.doh_backup_server" >/dev/null; then + uci -q del "dhcp.${cfg}.server" + for i in $(uci -q get "dhcp.${cfg}.doh_backup_server"); do + uci -q add_list "dhcp.${cfg}.server=$i" done - uci_remove 'dhcp' "$cfg" 'doh_backup_server' + uci -q del "dhcp.${cfg}.doh_backup_server" fi } @@ -372,15 +222,12 @@ dhcp_backup() { config_load 'dhcp' case "$1" in create) - if [ "$dnsmasq_config_update" = "*" ]; then + if [ "$dnsmasqConfig" = "*" ]; then config_foreach dnsmasq_create_server_backup 'dnsmasq' - elif [ -n "$dnsmasq_config_update" ]; then - for i in $dnsmasq_config_update; do - if [ -n "$(uci_get 'dhcp' "@dnsmasq[$i]")" ]; then - dnsmasq_create_server_backup "@dnsmasq[$i]" - elif [ -n "$(uci_get 'dhcp' "$i")" ]; then + elif [ -n "$dnsmasqConfig" ]; then + for i in $dnsmasqConfig; do + dnsmasq_create_server_backup "@dnsmasq[${i}]" || \ dnsmasq_create_server_backup "$i" - fi done fi ;; diff --git a/https-dns-proxy/patches/010-cmakelists-remove-cflags.patch b/https-dns-proxy/patches/010-fix-cmakelists.patch old mode 100644 new mode 100755 similarity index 56% rename from https-dns-proxy/patches/010-cmakelists-remove-cflags.patch rename to https-dns-proxy/patches/010-fix-cmakelists.patch index cd60c6dc0..106142579 --- a/https-dns-proxy/patches/010-cmakelists-remove-cflags.patch +++ b/https-dns-proxy/patches/010-fix-cmakelists.patch @@ -1,13 +1,13 @@ --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -25,9 +25,9 @@ if (NOT CMAKE_INSTALL_BINDIR) - set(CMAKE_INSTALL_BINDIR bin) +@@ -21,9 +21,9 @@ if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE}' as none was specified.") endif() --set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") +-set(CMAKE_C_FLAGS "-Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") -set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG") -set(CMAKE_C_FLAGS_RELEASE "-O2") -+#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") ++#set(CMAKE_C_FLAGS "-Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") +#set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG") +#set(CMAKE_C_FLAGS_RELEASE "-O2") diff --git a/https-dns-proxy/patches/020-src-options.c-add-version.patch b/https-dns-proxy/patches/020-src-options.c-add-version.patch deleted file mode 100644 index 8bb2d9361..000000000 --- a/https-dns-proxy/patches/020-src-options.c-add-version.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/options.c -+++ b/src/options.c -@@ -22,7 +22,7 @@ const char * options_sw_version() { - #ifdef SW_VERSION - return SW_VERSION; - #else -- return "2023.01.01-atLeast"; // update date sometimes, like 1-2 times a year -+ return "2023-05-25-1"; // update date sometimes, like 1-2 times a year - #endif - } - diff --git a/https-dns-proxy/test.sh b/https-dns-proxy/test.sh old mode 100644 new mode 100755 index 443b747a0..45469ed96 --- a/https-dns-proxy/test.sh +++ b/https-dns-proxy/test.sh @@ -1,3 +1,3 @@ #!/bin/sh -/etc/init.d/"$1" version 2>&1 | grep "$2" && "$1" -V 2>&1 | grep "$2" +/etc/init.d/"$1" version 2>&1 | grep "$2" diff --git a/ipcalc/Makefile b/ipcalc/Makefile old mode 100644 new mode 100755 diff --git a/iproute2/Makefile b/iproute2/Makefile old mode 100644 new mode 100755 index 101ca6732..302d57bf8 --- a/iproute2/Makefile +++ b/iproute2/Makefile @@ -8,19 +8,17 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.3.0 +PKG_VERSION:=6.2.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=dfb2a98db96e7a653cffc6693335a1a466e29a34b6ac528be48f35e1d2766732 +PKG_HASH:=4d72730200ec5b2aabaa1a2f20553c6748292f065d9a154c7d5e22559df9fd62 PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 PKG_CPE_ID:=cpe:/a:iproute2_project:iproute2 -PKG_BUILD_FLAGS:=gc-sections lto - include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/nls.mk @@ -173,7 +171,8 @@ define Build/Configure > $(PKG_BUILD_DIR)/include/SNAPSHOT.h endef -TARGET_LDFLAGS += -Wl,--as-needed +TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto +TARGET_LDFLAGS += -Wl,--gc-sections -Wl,--as-needed TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny MAKE_FLAGS += \ diff --git a/iproute2/patches/100-configure.patch b/iproute2/patches/100-configure.patch old mode 100644 new mode 100755 index 2d4fb7b9b..0c19b2086 --- a/iproute2/patches/100-configure.patch +++ b/iproute2/patches/100-configure.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -36,7 +36,8 @@ int main(int argc, char **argv) { +@@ -34,7 +34,8 @@ int main(int argc, char **argv) { } EOF diff --git a/iproute2/patches/110-darwin_fixes.patch b/iproute2/patches/110-darwin_fixes.patch old mode 100644 new mode 100755 index 06ae59f8b..1f3eb101e --- a/iproute2/patches/110-darwin_fixes.patch +++ b/iproute2/patches/110-darwin_fixes.patch @@ -1,6 +1,6 @@ --- a/netem/maketable.c +++ b/netem/maketable.c -@@ -11,7 +11,9 @@ +@@ -10,7 +10,9 @@ #include #include #include @@ -12,7 +12,7 @@ #include --- a/netem/normal.c +++ b/netem/normal.c -@@ -9,8 +9,12 @@ +@@ -8,8 +8,12 @@ #include #include @@ -27,7 +27,7 @@ #define TABLEFACTOR NETEM_DIST_SCALE --- a/netem/pareto.c +++ b/netem/pareto.c -@@ -8,8 +8,12 @@ +@@ -7,8 +7,12 @@ #include #include @@ -42,7 +42,7 @@ #define TABLESIZE 16384 --- a/netem/paretonormal.c +++ b/netem/paretonormal.c -@@ -15,10 +15,13 @@ +@@ -14,10 +14,13 @@ #include #include #include diff --git a/iproute2/patches/115-add-config-xtlibdir.patch b/iproute2/patches/115-add-config-xtlibdir.patch old mode 100644 new mode 100755 index 03df7809f..8702d5fd2 --- a/iproute2/patches/115-add-config-xtlibdir.patch +++ b/iproute2/patches/115-add-config-xtlibdir.patch @@ -1,6 +1,6 @@ --- a/tc/Makefile +++ b/tc/Makefile -@@ -127,6 +127,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR +@@ -128,6 +128,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR ifneq ($(IPT_LIB_DIR),) CFLAGS += -DIPT_LIB_DIR=\"$(IPT_LIB_DIR)\" endif diff --git a/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch b/iproute2/patches/120-no_arpd_ifstat_rtacct_lnstat.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/140-allow_pfifo_fast.patch b/iproute2/patches/140-allow_pfifo_fast.patch old mode 100644 new mode 100755 index 8f5a7d352..13de48f41 --- a/iproute2/patches/140-allow_pfifo_fast.patch +++ b/iproute2/patches/140-allow_pfifo_fast.patch @@ -1,6 +1,6 @@ --- a/tc/q_fifo.c +++ b/tc/q_fifo.c -@@ -90,5 +90,6 @@ struct qdisc_util pfifo_head_drop_qdisc_ +@@ -95,5 +95,6 @@ struct qdisc_util pfifo_head_drop_qdisc_ struct qdisc_util pfifo_fast_qdisc_util = { .id = "pfifo_fast", diff --git a/iproute2/patches/140-keep_libmnl_optional.patch b/iproute2/patches/140-keep_libmnl_optional.patch old mode 100644 new mode 100755 index a8cdd103b..ff7e9ca4e --- a/iproute2/patches/140-keep_libmnl_optional.patch +++ b/iproute2/patches/140-keep_libmnl_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -411,7 +411,7 @@ check_tirpc() +@@ -387,7 +387,7 @@ check_selinux() check_mnl() { diff --git a/iproute2/patches/145-keep_libelf_optional.patch b/iproute2/patches/145-keep_libelf_optional.patch old mode 100644 new mode 100755 index 0c5c3f59e..079ca0512 --- a/iproute2/patches/145-keep_libelf_optional.patch +++ b/iproute2/patches/145-keep_libelf_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -266,7 +266,7 @@ EOF +@@ -255,7 +255,7 @@ EOF check_elf() { diff --git a/iproute2/patches/150-keep_libcap_optional.patch b/iproute2/patches/150-keep_libcap_optional.patch old mode 100644 new mode 100755 index 4cce2c3ca..68e162416 --- a/iproute2/patches/150-keep_libcap_optional.patch +++ b/iproute2/patches/150-keep_libcap_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -469,7 +469,7 @@ EOF +@@ -445,7 +445,7 @@ EOF check_cap() { diff --git a/iproute2/patches/155-keep_tirpc_optional.patch b/iproute2/patches/155-keep_tirpc_optional.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/160-libnetlink-pic.patch b/iproute2/patches/160-libnetlink-pic.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/170-ip_tiny.patch b/iproute2/patches/170-ip_tiny.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/175-reduce-dynamic-syms.patch b/iproute2/patches/175-reduce-dynamic-syms.patch old mode 100644 new mode 100755 index d0914848d..c3892e5a0 --- a/iproute2/patches/175-reduce-dynamic-syms.patch +++ b/iproute2/patches/175-reduce-dynamic-syms.patch @@ -1,6 +1,6 @@ --- a/tc/Makefile +++ b/tc/Makefile -@@ -113,7 +113,7 @@ LDLIBS += -L. -lm +@@ -114,7 +114,7 @@ LDLIBS += -L. -lm ifeq ($(SHARED_LIBS),y) LDLIBS += -ldl @@ -9,7 +9,7 @@ endif TCLIB := tc_core.o -@@ -143,7 +143,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc +@@ -144,7 +144,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc all: tc $(TCSO) tc: $(TCOBJ) $(LIBNETLINK) libtc.a @@ -18,7 +18,7 @@ libtc.a: $(TCLIB) $(QUIET_AR)$(AR) rcs $@ $^ -@@ -165,6 +165,7 @@ install: all +@@ -166,6 +166,7 @@ install: all clean: rm -f $(TCOBJ) $(TCLIB) libtc.a tc *.so emp_ematch.tab.h; \ rm -f emp_ematch.tab.* @@ -26,7 +26,7 @@ q_atm.so: q_atm.c $(QUIET_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -shared -fpic -o q_atm.so q_atm.c -latm -@@ -204,4 +205,16 @@ static-syms.h: $(wildcard *.c) +@@ -205,4 +206,16 @@ static-syms.h: $(wildcard *.c) sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \ done > $@ diff --git a/iproute2/patches/180-drop_FAILED_POLICY.patch b/iproute2/patches/180-drop_FAILED_POLICY.patch old mode 100644 new mode 100755 index 9ce7dd9a1..07d5230a6 --- a/iproute2/patches/180-drop_FAILED_POLICY.patch +++ b/iproute2/patches/180-drop_FAILED_POLICY.patch @@ -11,7 +11,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY --- a/ip/rtm_map.c +++ b/ip/rtm_map.c -@@ -49,6 +49,8 @@ char *rtnl_rtntype_n2a(int id, char *buf +@@ -54,6 +54,8 @@ char *rtnl_rtntype_n2a(int id, char *buf return "nat"; case RTN_XRESOLVE: return "xresolve"; @@ -20,7 +20,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY default: snprintf(buf, len, "%d", id); return buf; -@@ -84,6 +86,8 @@ int rtnl_rtntype_a2n(int *id, char *arg) +@@ -89,6 +91,8 @@ int rtnl_rtntype_a2n(int *id, char *arg) res = RTN_UNICAST; else if (strcmp(arg, "throw") == 0) res = RTN_THROW; @@ -31,7 +31,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY if (!end || end == arg || *end || res > 255) --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h -@@ -265,6 +265,7 @@ enum { +@@ -256,6 +256,7 @@ enum { RTN_THROW, /* Not in this table */ RTN_NAT, /* Translate this address */ RTN_XRESOLVE, /* Use external resolver */ diff --git a/iproute2/patches/190-fix-nls-rpath-link.patch b/iproute2/patches/190-fix-nls-rpath-link.patch old mode 100644 new mode 100755 index c7fceb2e2..92d02b9a4 --- a/iproute2/patches/190-fix-nls-rpath-link.patch +++ b/iproute2/patches/190-fix-nls-rpath-link.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -290,7 +290,7 @@ int main(int argc, char **argv) { +@@ -279,7 +279,7 @@ int main(int argc, char **argv) { } EOF @@ -9,7 +9,7 @@ local ret=$? rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test -@@ -308,7 +308,7 @@ int main(int argc, char **argv) { +@@ -297,7 +297,7 @@ int main(int argc, char **argv) { } EOF diff --git a/iproute2/patches/195-build_variant_ip_tc.patch b/iproute2/patches/195-build_variant_ip_tc.patch old mode 100644 new mode 100755 diff --git a/iproute2/patches/200-drop_libbsd_dependency.patch b/iproute2/patches/200-drop_libbsd_dependency.patch old mode 100644 new mode 100755 index d1948860e..12a1ccfa3 --- a/iproute2/patches/200-drop_libbsd_dependency.patch +++ b/iproute2/patches/200-drop_libbsd_dependency.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -455,14 +455,8 @@ EOF +@@ -431,14 +431,8 @@ EOF if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then echo "no" else diff --git a/iproute2/patches/300-selinux-configurable.patch b/iproute2/patches/300-selinux-configurable.patch old mode 100644 new mode 100755 index 817abf7d1..b7e61fd3b --- a/iproute2/patches/300-selinux-configurable.patch +++ b/iproute2/patches/300-selinux-configurable.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -385,7 +385,7 @@ check_libbpf() +@@ -374,7 +374,7 @@ check_libbpf() check_selinux() # SELinux is a compile time option in the ss utility { diff --git a/lcd4linux/Config.in b/lcd4linux/Config.in new file mode 100755 index 000000000..1410f2b85 --- /dev/null +++ b/lcd4linux/Config.in @@ -0,0 +1,490 @@ +if PACKAGE_lcd4linux-custom + +config LCD4LINUX_CUSTOM_NEEDS_libdbus + bool + +#config LCD4LINUX_CUSTOM_NEEDS_libftdi +# bool + +config LCD4LINUX_CUSTOM_NEEDS_libgd + bool + +config LCD4LINUX_CUSTOM_NEEDS_libiconv + bool + +config LCD4LINUX_CUSTOM_NEEDS_libjpeg + bool + +config LCD4LINUX_CUSTOM_NEEDS_libmpdclient + bool + +config LCD4LINUX_CUSTOM_NEEDS_libmysqlclient + bool + +config LCD4LINUX_CUSTOM_NEEDS_libncurses + bool + +config LCD4LINUX_CUSTOM_NEEDS_libnmeap + bool + +config LCD4LINUX_CUSTOM_NEEDS_libsqlite3 + bool + +config LCD4LINUX_CUSTOM_NEEDS_libusb + bool + +#config LCD4LINUX_CUSTOM_NEEDS_libX11 +# bool + +config LCD4LINUX_CUSTOM_NEEDS_ppp + bool + +config LCD4LINUX_CUSTOM_NEEDS_python + bool + + +comment "Drivers ---" + +config LCD4LINUX_CUSTOM_DRIVER_ASTUSB + bool + prompt "ASTUSB" + +config LCD4LINUX_CUSTOM_DRIVER_BeckmannEgle + bool + prompt "BeckmannEgle" + +config LCD4LINUX_CUSTOM_DRIVER_BWCT + bool + prompt "BWCT" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_CrystalFontz + bool + prompt "CrystalFontz" + +config LCD4LINUX_CUSTOM_DRIVER_Curses + bool + prompt "Curses" + select LCD4LINUX_CUSTOM_NEEDS_libncurses + +config LCD4LINUX_CUSTOM_DRIVER_Cwlinux + bool + prompt "Cwlinux" + +config LCD4LINUX_CUSTOM_DRIVER_D4D + bool + prompt "D4D" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_dpf + bool + prompt "dpf" + select LCD4LINUX_CUSTOM_NEEDS_libusb + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_EA232graphic + bool + prompt "EA232graphic" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_EFN + bool + prompt "EFN" + +config LCD4LINUX_CUSTOM_DRIVER_FutabaVFD + bool + prompt "FutabaVFD" + +config LCD4LINUX_CUSTOM_DRIVER_FW8888 + bool + prompt "FW8888" + +config LCD4LINUX_CUSTOM_DRIVER_G15 + bool + prompt "G15" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_GLCD2USB + bool + prompt "GLCD2USB" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_HD44780 + bool + prompt "HD44780" + depends on BROKEN + +config LCD4LINUX_CUSTOM_DRIVER_HD44780-I2C + bool + prompt "HD44780-I2C" + depends on BROKEN + +config LCD4LINUX_CUSTOM_DRIVER_IRLCD + bool + prompt "IRLCD" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_LCD2USB + bool + prompt "LCD2USB" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_LCDLinux + bool + prompt "LCDLinux" + depends on BROKEN + +config LCD4LINUX_CUSTOM_DRIVER_LCDTerm + bool + prompt "LCDTerm" + +config LCD4LINUX_CUSTOM_DRIVER_LEDMatrix + bool + prompt "LEDMatrix" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_LPH7508 + bool + prompt "LPH7508" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_LUIse + bool + prompt "LUIse" + select LCD4LINUX_CUSTOM_NEEDS_libgd + #select LCD4LINUX_CUSTOM_NEEDS_libluise + depends on BROKEN + +config LCD4LINUX_CUSTOM_DRIVER_LW_ABP + bool + prompt "LW_ABP" + +config LCD4LINUX_CUSTOM_DRIVER_M50530 + bool + prompt "M50530" + +config LCD4LINUX_CUSTOM_DRIVER_MatrixOrbital + bool + prompt "MatrixOrbital" + +config LCD4LINUX_CUSTOM_DRIVER_MatrixOrbitalGX + bool + prompt "MatrixOrbitalGX" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_mdm166a + bool + prompt "mdm166a" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_MilfordInstruments + bool + prompt "MilfordInstruments" + +config LCD4LINUX_CUSTOM_DRIVER_Newhaven + bool + prompt "Newhaven" + +config LCD4LINUX_CUSTOM_DRIVER_Noritake + bool + prompt "Noritake" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_NULL + bool + prompt "NULL" + default y + +config LCD4LINUX_CUSTOM_DRIVER_Pertelian + bool + prompt "Pertelian" + +config LCD4LINUX_CUSTOM_DRIVER_PHAnderson + bool + prompt "PHAnderson" + +config LCD4LINUX_CUSTOM_DRIVER_PICGraphic + bool + prompt "PICGraphic" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_picoLCD + bool + prompt "picoLCD" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_picoLCDGraphic + bool + prompt "picoLCDGraphic" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_PNG + bool + prompt "PNG" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_PPM + bool + prompt "PPM" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_RouterBoard + bool + prompt "RouterBoard" + depends on TARGET_rb532 + +config LCD4LINUX_CUSTOM_DRIVER_SamsungSPF + bool + prompt "SamsungSPF" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libjpeg + +config LCD4LINUX_CUSTOM_DRIVER_serdisplib + bool + prompt "serdisplib" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_serdisplib + +config LCD4LINUX_CUSTOM_DRIVER_ShuttleVFD + bool + prompt "ShuttleVFD" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_SimpleLCD + bool + prompt "SimpleLCD" + +config LCD4LINUX_CUSTOM_DRIVER_st2205 + bool + prompt "st2205" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_st2205tool + +config LCD4LINUX_CUSTOM_DRIVER_T6963 + bool + prompt "T6963" + select LCD4LINUX_CUSTOM_NEEDS_libgd + +config LCD4LINUX_CUSTOM_DRIVER_TeakLCM + bool + prompt "TeakLCM" + +config LCD4LINUX_CUSTOM_DRIVER_TEW673GRU + bool + select LCD4LINUX_CUSTOM_NEEDS_libgd + depends on TARGET_ar71xx + default TARGET_ar71xx + +config LCD4LINUX_CUSTOM_DRIVER_Trefon + bool + prompt "Trefon" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +#config LCD4LINUX_CUSTOM_DRIVER_ULA200 +# bool +# prompt "ULA200" +# select LCD4LINUX_CUSTOM_NEEDS_libftdi +# select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_USBHUB + bool + prompt "USBHUB" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_USBLCD + bool + prompt "USBLCD" + select LCD4LINUX_CUSTOM_NEEDS_libusb + +config LCD4LINUX_CUSTOM_DRIVER_VNC + bool + prompt "VNC" + select LCD4LINUX_CUSTOM_NEEDS_libgd + select LCD4LINUX_CUSTOM_NEEDS_libvncserver + +config LCD4LINUX_CUSTOM_DRIVER_WincorNixdorf + bool + prompt "WincorNixdorf" + +#config LCD4LINUX_CUSTOM_DRIVER_X11 +# bool +# prompt "X11" +# select LCD4LINUX_CUSTOM_NEEDS_libgd +# select LCD4LINUX_CUSTOM_NEEDS_libX11 + + +comment "Plugins ---" + +config LCD4LINUX_CUSTOM_PLUGIN_apm + bool + prompt "apm" + +config LCD4LINUX_CUSTOM_PLUGIN_asterisk + bool + prompt "asterisk" + +config LCD4LINUX_CUSTOM_PLUGIN_button_exec + bool + prompt "button_exec" + +config LCD4LINUX_CUSTOM_PLUGIN_cpuinfo + bool + prompt "cpuinfo" + default y + +config LCD4LINUX_CUSTOM_PLUGIN_dbus + bool + prompt "dbus" + select LCD4LINUX_CUSTOM_NEEDS_libdbus + +config LCD4LINUX_CUSTOM_PLUGIN_diskstats + bool + prompt "diskstats" + +config LCD4LINUX_CUSTOM_PLUGIN_dvb + bool + prompt "dvb" + +config LCD4LINUX_CUSTOM_PLUGIN_event + bool + prompt "event" + +config LCD4LINUX_CUSTOM_PLUGIN_exec + bool + prompt "exec" + +config LCD4LINUX_CUSTOM_PLUGIN_fifo + bool + prompt "fifo" + +config LCD4LINUX_CUSTOM_PLUGIN_file + bool + prompt "file" + +config LCD4LINUX_CUSTOM_PLUGIN_gps + bool + prompt "gps" + select LCD4LINUX_CUSTOM_NEEDS_libnmeap + +config LCD4LINUX_CUSTOM_PLUGIN_hddtemp + bool + prompt "hddtemp" + +config LCD4LINUX_CUSTOM_PLUGIN_huawei + bool + prompt "huawei" + +config LCD4LINUX_CUSTOM_PLUGIN_i2c_sensors + bool + prompt "i2c_sensors" + +config LCD4LINUX_CUSTOM_PLUGIN_iconv + bool + prompt "iconv" + select LCD4LINUX_CUSTOM_NEEDS_libiconv + +config LCD4LINUX_CUSTOM_PLUGIN_imon + bool + prompt "imon" + +config LCD4LINUX_CUSTOM_PLUGIN_isdn + bool + prompt "isdn" + +config LCD4LINUX_CUSTOM_PLUGIN_kvv + bool + prompt "kvv" + +config LCD4LINUX_CUSTOM_PLUGIN_loadavg + bool + prompt "loadavg" + default y + +config LCD4LINUX_CUSTOM_PLUGIN_meminfo + bool + prompt "meminfo" + default y + +config LCD4LINUX_CUSTOM_PLUGIN_mpd + bool + prompt "mpd" + select LCD4LINUX_CUSTOM_NEEDS_libmpdclient + +config LCD4LINUX_CUSTOM_PLUGIN_mpris_dbus + bool + prompt "mpris_dbus" + select LCD4LINUX_CUSTOM_NEEDS_libdbus + +config LCD4LINUX_CUSTOM_PLUGIN_mysql + bool + prompt "mysql" + select LCD4LINUX_CUSTOM_NEEDS_libmysqlclient + +config LCD4LINUX_CUSTOM_PLUGIN_netdev + bool + prompt "netdev" + +config LCD4LINUX_CUSTOM_PLUGIN_netinfo + bool + prompt "netinfo" + +config LCD4LINUX_CUSTOM_PLUGIN_pop3 + bool + prompt "pop3" + +config LCD4LINUX_CUSTOM_PLUGIN_ppp + bool + prompt "ppp" + select LCD4LINUX_CUSTOM_NEEDS_ppp + +config LCD4LINUX_CUSTOM_PLUGIN_proc_stat + bool + prompt "proc_stat" + default y + +#config LCD4LINUX_CUSTOM_PLUGIN_python +# bool +# prompt "python" +# select LCD4LINUX_CUSTOM_NEEDS_python + +config LCD4LINUX_CUSTOM_PLUGIN_qnaplog + bool + prompt "qnaplog" + select LCD4LINUX_CUSTOM_NEEDS_libsqlite3 + +config LCD4LINUX_CUSTOM_PLUGIN_seti + bool + prompt "seti" + +config LCD4LINUX_CUSTOM_PLUGIN_statfs + bool + prompt "statfs" + +config LCD4LINUX_CUSTOM_PLUGIN_uname + bool + prompt "uname" + +config LCD4LINUX_CUSTOM_PLUGIN_uptime + bool + prompt "uptime" + default y + +config LCD4LINUX_CUSTOM_PLUGIN_w1retap + bool + prompt "w1retap" + +config LCD4LINUX_CUSTOM_PLUGIN_wireless + bool + prompt "wireless" + depends on BROKEN + +config LCD4LINUX_CUSTOM_PLUGIN_xmms + bool + prompt "xmms" + +endif diff --git a/lcd4linux/Makefile b/lcd4linux/Makefile new file mode 100755 index 000000000..3271b359f --- /dev/null +++ b/lcd4linux/Makefile @@ -0,0 +1,306 @@ +# +# Copyright (C) 2007-2015 OpenWrt.org +# Copyright (C) 2019 Ycarus (Yannick Chabanois) +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lcd4linux +PKG_REV:=f13470faf00e52d1458f2a88d498716240edc272 +PKG_VERSION:=r$(PKG_REV) +PKG_RELEASE:=4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +#PKG_SOURCE_URL:=https://ssl.bulix.org/svn/lcd4linux/trunk/ +PKG_SOURCE_URL:=https://github.com/redblue-pkt/lcd4linux.git +#PKG_SOURCE_SUBDIR:=lcd4linux-$(PKG_VERSION) +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_SOURCE_PROTO:=git + +LCD4LINUX_DRIVERS:= \ + ASTUSB \ + BeckmannEgle \ + BWCT \ + CrystalFontz \ + Curses \ + Cwlinux \ + D4D \ + DPF \ + EA232graphic \ + EFN \ + FutabaVFD \ + FW8888 \ + GLCD2USB \ + IRLCD \ + $(if $(CONFIG_BROKEN),HD44780) \ + $(if $(CONFIG_BROKEN),HD44780-I2C) \ + LCD2USB \ + $(if $(CONFIG_BROKEN),LCDLinux) \ + LCDTerm \ + LEDMatrix \ + LPH7508 \ + $(if $(CONFIG_BROKEN),LUIse) \ + LW_ABP \ + M50530 \ + MatrixOrbital \ + MatrixOrbitalGX \ + MilfordInstruments \ + Newhaven \ + Noritake \ + NULL \ + Pertelian \ + PHAnderson \ + PICGraphic \ + picoLCD \ + picoLCDGraphic \ + PNG \ + PPM \ + $(if $(CONFIG_TARGET_rb532),RouterBoard) \ + $(if $(CONFIG_BROKEN),SamsungSPF) \ + ShuttleVFD \ + SimpleLCD \ + st2205 \ + T6963 \ + TeakLCM \ + $(if $(CONFIG_TARGET_ar71xx),TEW673GRU) \ + Trefon \ + USBHUB \ + USBLCD \ + VNC \ + WincorNixdorf \ + serdisplib \ +# G15 \ +# ULA200 \ +# X11 \ + +LCD4LINUX_PLUGINS:= \ + apm \ + asterisk \ + button_exec \ + cpuinfo \ + dbus \ + diskstats \ + dvb \ + event \ + exec \ + fifo \ + file \ + gps \ + hddtemp \ + huawei \ + i2c_sensors \ + iconv \ + imon \ + isdn \ + kvv \ + loadavg \ + netdev \ + netinfo \ + meminfo \ + mpris_dbus \ + netdev \ + pop3 \ + ppp \ + proc_stat \ + qnaplog \ + seti \ + statfs \ + uname \ + uptime \ + w1retap \ + $(if $(CONFIG_BROKEN),wireless) \ + xmms \ +# mpd \ +# mysql \ +# python \ + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_BUILD_DEPENDS:= \ +# ppp \ +# libftdi \ +# libX11 \ +# python \ + +PKG_CONFIG_DEPENDS:= \ + $(patsubst %,CONFIG_LCD4LINUX_CUSTOM_DRIVER_%,$(LCD4LINUX_DRIVERS)) \ + $(patsubst %,CONFIG_LCD4LINUX_CUSTOM_PLUGIN_%,$(LCD4LINUX_PLUGINS)) \ + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/lcd4linux/Default + SECTION:=utils + CATEGORY:=Utilities + PKG_MAINTAINER:=Jonathan McCrohan + TITLE:=LCD display utility + URL:=http://lcd4linux.bulix.org/ +endef + +define Package/lcd4linux/Default/description + LCD4Linux is a small program that grabs information from the kernel and + some subsystems and displays it on an external liquid crystal display. +endef + + +define Package/lcd4linux-custom +$(call Package/lcd4linux/Default) + DEPENDS:= \ + +LCD4LINUX_CUSTOM_NEEDS_libdbus:libdbus \ + +LCD4LINUX_CUSTOM_NEEDS_libgd:libgd \ + $(if $(ICONV_FULL),+LCD4LINUX_CUSTOM_NEEDS_libiconv:libiconv-full) \ + +LCD4LINUX_CUSTOM_NEEDS_libjpeg:libjpeg \ + +LCD4LINUX_CUSTOM_NEEDS_libncurses:libncurses \ + +LCD4LINUX_CUSTOM_NEEDS_libsqlite3:libsqlite3 \ + +LCD4LINUX_CUSTOM_NEEDS_libusb:libusb-compat \ +# +LCD4LINUX_CUSTOM_NEEDS_libmpdclient:libmpdclient \ +# +LCD4LINUX_CUSTOM_NEEDS_libmysqlclient:libmysqlclient \ +# +LCD4LINUX_CUSTOM_NEEDS_libftdi:libftdi \ +# +LCD4LINUX_CUSTOM_NEEDS_libX11:libX11 \ +# +LCD4LINUX_CUSTOM_NEEDS_python:python + MENU:=1 + PROVIDES:=lcd4linux + VARIANT=custom +endef + +define Package/lcd4linux-custom/config + source "$(SOURCE)/Config.in" +endef + +define Package/lcd4linux-custom/description +$(call Package/lcd4linux/Default/description) + . + This package contains a customized version of LCD4Linux. +endef + + +define Package/lcd4linux-full +$(call Package/lcd4linux/Default) + DEPENDS:= \ + +libdbus \ + +libgd \ + $(if $(ICONV_FULL),+libiconv-full) \ + +libncurses \ + +libsqlite3 \ + +libusb-compat \ + +serdisplib +# +libmpdclient \ +# +libmysqlclient \ +# +libftdi \ +# +libX11 \ +# +python + PROVIDES:=lcd4linux + VARIANT=full +endef + +define Package/lcd4linux-full/description +$(call Package/lcd4linux/Default/description) + . + This package contains a version of LCD4Linux built with all supported + drivers and plugins. +endef + + +CONFIGURE_ARGS+= \ + --disable-rpath \ + +EXTRA_LDFLAGS+= -Wl,-rpath-link,$(STAGING_DIR)/usr/lib + +ifeq ($(BUILD_VARIANT),custom) + + LCD4LINUX_CUSTOM_DRIVERS:= $(strip $(foreach c, $(LCD4LINUX_DRIVERS), \ + $(if $(CONFIG_LCD4LINUX_CUSTOM_DRIVER_$(c)),$(c),) \ + )) + ifeq ($(LCD4LINUX_CUSTOM_DRIVERS),) + LCD4LINUX_CUSTOM_DRIVERS:=Sample + endif + + LCD4LINUX_CUSTOM_PLUGINS:= $(strip $(foreach c, $(LCD4LINUX_PLUGINS), \ + $(if $(CONFIG_LCD4LINUX_CUSTOM_PLUGIN_$(c)),$(c)) \ + )) + ifeq ($(LCD4LINUX_CUSTOM_PLUGINS),) + LCD4LINUX_CUSTOM_PLUGINS:=sample + endif + + CONFIGURE_ARGS+= \ + --with-drivers="$(LCD4LINUX_CUSTOM_DRIVERS)" \ + --with-plugins="$(LCD4LINUX_CUSTOM_PLUGINS)" \ + + ifneq ($(CONFIG_LCD4LINUX_CUSTOM_NEEDS_libiconv),) + CONFIGURE_ARGS+= --with-libiconv-prefix="$(ICONV_PREFIX)" + else + CONFIGURE_ARGS+= --without-libiconv-prefix + endif + + ifneq ($(CONFIG_LCD4LINUX_CUSTOM_NEEDS_libmysqlclient),) + EXTRA_LDFLAGS+= -L$(STAGING_DIR)/usr/lib/mysql + endif + +# ifneq ($(CONFIG_LCD4LINUX_CUSTOM_NEEDS_python),) +# CONFIGURE_ARGS+= --with-python +# else + CONFIGURE_ARGS+= --without-python +# endif + +# ifneq ($(CONFIG_LCD4LINUX_CUSTOM_NEEDS_libX11),) +# CONFIGURE_ARGS+= --with-x +# else + CONFIGURE_ARGS+= --without-x +# endif + +endif + +ifeq ($(BUILD_VARIANT),full) + + LCD4LINUX_FULL_DRIVERS:= $(strip $(foreach c, $(LCD4LINUX_DRIVERS), \ + $(c) \ + )) + + LCD4LINUX_FULL_PLUGINS:= $(strip $(foreach c, $(LCD4LINUX_PLUGINS), \ + $(c) \ + )) + + CONFIGURE_ARGS+= \ + --with-drivers="$(LCD4LINUX_FULL_DRIVERS)" \ + --with-plugins="$(LCD4LINUX_FULL_PLUGINS)" \ + --with-libiconv-prefix="$(ICONV_PREFIX)" \ + --without-python \ + --without-x \ + + EXTRA_LDFLAGS+= -L$(STAGING_DIR)/usr/lib/mysql + +endif + + +define Package/lcd4linux/conffiles +/etc/lcd4linux.conf +endef + +define Package/lcd4linux/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_INSTALL_DIR)/usr/bin/lcd4linux $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) $(PKG_BUILD_DIR)/lcd4linux.conf.sample $(1)/etc/lcd4linux.conf + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/lcd4linux.init $(1)/etc/init.d/lcd4linux + $(SED) "s|^\(Display 'GLCD2USB'\)|#\1|g" \ + -e "s|^\(Layout 'TestLayer'\)|#\1|g" \ + -e "s|^#\(Display 'Image'\)|\1|g" \ + -e "s|^#\(Layout 'Default'\)|\1|g" \ + $(1)/etc/lcd4linux.conf +endef + +Package/lcd4linux-custom/conffiles = $(Package/lcd4linux/conffiles) +Package/lcd4linux-custom/install = $(Package/lcd4linux/install) + +Package/lcd4linux-full/conffiles = $(Package/lcd4linux/conffiles) +Package/lcd4linux-full/install = $(Package/lcd4linux/install) + +$(eval $(call BuildPackage,lcd4linux-custom)) +$(eval $(call BuildPackage,lcd4linux-full)) diff --git a/lcd4linux/files/lcd4linux.init b/lcd4linux/files/lcd4linux.init new file mode 100755 index 000000000..25033f382 --- /dev/null +++ b/lcd4linux/files/lcd4linux.init @@ -0,0 +1,15 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2007-2015 OpenWrt.org + +START=98 + +SERVICE_USE_PID=1 + +start() { + service_start /usr/bin/lcd4linux -o /tmp/lcd4linux.png -q +} + +stop() { + service_stop /usr/bin/lcd4linux +} + diff --git a/lcd4linux/patches/120-remove-as-needed-linker-option.patch b/lcd4linux/patches/120-remove-as-needed-linker-option.patch new file mode 100755 index 000000000..b5e56fe7b --- /dev/null +++ b/lcd4linux/patches/120-remove-as-needed-linker-option.patch @@ -0,0 +1,11 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -18,7 +18,7 @@ ACLOCAL_AMFLAGS=-I m4 + # use this for lots of warnings + #AM_CFLAGS = -D_GNU_SOURCE -std=c99 -m64 -Wall -W -pedantic -Wno-variadic-macros -fno-strict-aliasing + +-lcd4linux_LDFLAGS ="-Wl,--as-needed" ++lcd4linux_LDFLAGS = + lcd4linux_LDADD = @DRIVERS@ @PLUGINS@ @DRVLIBS@ @PLUGINLIBS@ + lcd4linux_DEPENDENCIES = @DRIVERS@ @PLUGINS@ + diff --git a/lcd4linux/patches/140-no_repnop_T6963.patch b/lcd4linux/patches/140-no_repnop_T6963.patch new file mode 100755 index 000000000..85be2c376 --- /dev/null +++ b/lcd4linux/patches/140-no_repnop_T6963.patch @@ -0,0 +1,22 @@ +--- a/drv_T6963.c ++++ b/drv_T6963.c +@@ -114,7 +114,9 @@ static void drv_T6_status1(void) + /* wait for STA0=1 and STA1=1 */ + n = 0; + do { ++#if 0 + rep_nop(); ++#endif + if (++n > 1000) { + debug("hang in status1"); + bug = 1; +@@ -150,7 +152,9 @@ static void drv_T6_status2(void) + /* wait for STA3=1 */ + n = 0; + do { ++#if 0 + rep_nop(); ++#endif + if (++n > 1000) { + debug("hang in status2"); + bug = 1; diff --git a/lcd4linux/patches/150-addlibmpdclient.patch b/lcd4linux/patches/150-addlibmpdclient.patch new file mode 100755 index 000000000..0e51f6760 --- /dev/null +++ b/lcd4linux/patches/150-addlibmpdclient.patch @@ -0,0 +1,2624 @@ +--- /dev/null ++++ b/libmpdclient.c +@@ -0,0 +1,1957 @@ ++/* libmpdclient ++ (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) ++ This project's homepage is: http://www.musicpd.org ++ ++ Redistribution and use in source and binary forms, with or without ++ modification, are permitted provided that the following conditions ++ are met: ++ ++ - Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ ++ - Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ ++ - Neither the name of the Music Player Daemon nor the names of its ++ contributors may be used to endorse or promote products derived from ++ this software without specific prior written permission. ++ ++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR ++ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#include "libmpdclient.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef WIN32 ++# include ++# include ++#else ++# include ++# include ++# include ++# include ++#endif ++ ++/* (bits+1)/3 (plus the sign character) */ ++#define INTLEN ((sizeof(int) * CHAR_BIT + 1) / 3 + 1) ++#define LONGLONGLEN ((sizeof(long long) * CHAR_BIT + 1) / 3 + 1) ++ ++#define COMMAND_LIST 1 ++#define COMMAND_LIST_OK 2 ++ ++#ifndef MPD_NO_GAI ++# ifdef AI_ADDRCONFIG ++# define MPD_HAVE_GAI ++# endif ++#endif ++ ++#ifndef MSG_DONTWAIT ++# define MSG_DONTWAIT 0 ++#endif ++ ++#ifdef WIN32 ++# define SELECT_ERRNO_IGNORE (errno == WSAEINTR || errno == WSAEINPROGRESS) ++# define SENDRECV_ERRNO_IGNORE SELECT_ERRNO_IGNORE ++#else ++# define SELECT_ERRNO_IGNORE (errno == EINTR) ++# define SENDRECV_ERRNO_IGNORE (errno == EINTR || errno == EAGAIN) ++# define winsock_dll_error(c) 0 ++# define closesocket(s) close(s) ++# define WSACleanup() do { /* nothing */ } while (0) ++#endif ++ ++#ifdef WIN32 ++static int winsock_dll_error(mpd_Connection * connection) ++{ ++ WSADATA wsaData; ++ if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 || LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { ++ strcpy(connection->errorStr, "Could not find usable WinSock DLL."); ++ connection->error = MPD_ERROR_SYSTEM; ++ return 1; ++ } ++ return 0; ++} ++ ++static int do_connect_fail(mpd_Connection * connection, const struct sockaddr *serv_addr, int addrlen) ++{ ++ int iMode = 1; /* 0 = blocking, else non-blocking */ ++ ioctlsocket(connection->sock, FIONBIO, (u_long FAR *) & iMode); ++ return (connect(connection->sock, serv_addr, addrlen) == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK); ++} ++#else /* !WIN32 (sane operating systems) */ ++static int do_connect_fail(mpd_Connection * connection, const struct sockaddr *serv_addr, int addrlen) ++{ ++ int flags = fcntl(connection->sock, F_GETFL, 0); ++ fcntl(connection->sock, F_SETFL, flags | O_NONBLOCK); ++ return (connect(connection->sock, serv_addr, addrlen) < 0 && errno != EINPROGRESS); ++} ++#endif /* !WIN32 */ ++ ++#ifdef MPD_HAVE_GAI ++static int mpd_connect(mpd_Connection * connection, const char *host, int port, float timeout) ++{ ++ int error; ++ char service[INTLEN + 1]; ++ struct addrinfo hints; ++ struct addrinfo *res = NULL; ++ struct addrinfo *addrinfo = NULL; ++ ++ /** ++ * Setup hints ++ */ ++ hints.ai_flags = AI_ADDRCONFIG; ++ hints.ai_family = PF_UNSPEC; ++ hints.ai_socktype = SOCK_STREAM; ++ hints.ai_protocol = IPPROTO_TCP; ++ hints.ai_addrlen = 0; ++ hints.ai_addr = NULL; ++ hints.ai_canonname = NULL; ++ hints.ai_next = NULL; ++ ++ snprintf(service, sizeof(service), "%i", port); ++ ++ error = getaddrinfo(host, service, &hints, &addrinfo); ++ ++ if (error) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "host \"%s\" not found: %s", host, gai_strerror(error)); ++ connection->error = MPD_ERROR_UNKHOST; ++ return -1; ++ } ++ ++ for (res = addrinfo; res; res = res->ai_next) { ++ /* create socket */ ++ connection->sock = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); ++ if (connection->sock < 0) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems creating socket: %s", strerror(errno)); ++ connection->error = MPD_ERROR_SYSTEM; ++ freeaddrinfo(addrinfo); ++ return -1; ++ } ++ ++ mpd_setConnectionTimeout(connection, timeout); ++ ++ /* connect stuff */ ++ if (do_connect_fail(connection, res->ai_addr, res->ai_addrlen)) { ++ /* try the next address family */ ++ closesocket(connection->sock); ++ connection->sock = -1; ++ continue; ++ } ++ } ++ ++ freeaddrinfo(addrinfo); ++ ++ if (connection->sock < 0) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, ++ "problems connecting to \"%s\" on port %i: %s", host, port, strerror(errno)); ++ connection->error = MPD_ERROR_CONNPORT; ++ ++ return -1; ++ } ++ ++ return 0; ++} ++#else /* !MPD_HAVE_GAI */ ++static int mpd_connect(mpd_Connection * connection, const char *host, int port, float timeout) ++{ ++ struct hostent *he; ++ struct sockaddr *dest; ++ int destlen; ++ struct sockaddr_in sin; ++ ++ if (!(he = gethostbyname(host))) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "host \"%s\" not found", host); ++ connection->error = MPD_ERROR_UNKHOST; ++ return -1; ++ } ++ ++ memset(&sin, 0, sizeof(struct sockaddr_in)); ++ /*dest.sin_family = he->h_addrtype; */ ++ sin.sin_family = AF_INET; ++ sin.sin_port = htons(port); ++ ++ switch (he->h_addrtype) { ++ case AF_INET: ++ memcpy((char *) &sin.sin_addr.s_addr, (char *) he->h_addr, he->h_length); ++ dest = (struct sockaddr *) &sin; ++ destlen = sizeof(struct sockaddr_in); ++ break; ++ default: ++ strcpy(connection->errorStr, "address type is not IPv4"); ++ connection->error = MPD_ERROR_SYSTEM; ++ return -1; ++ break; ++ } ++ ++ if ((connection->sock = socket(dest->sa_family, SOCK_STREAM, 0)) < 0) { ++ strcpy(connection->errorStr, "problems creating socket"); ++ connection->error = MPD_ERROR_SYSTEM; ++ return -1; ++ } ++ ++ mpd_setConnectionTimeout(connection, timeout); ++ ++ /* connect stuff */ ++ if (do_connect_fail(connection, dest, destlen)) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, ++ "problems connecting to \"%s\" on port" " %i", host, port); ++ connection->error = MPD_ERROR_CONNPORT; ++ return -1; ++ } ++ ++ return 0; ++} ++#endif /* !MPD_HAVE_GAI */ ++ ++char *mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES] = { ++ "Artist", ++ "Album", ++ "Title", ++ "Track", ++ "Name", ++ "Genre", ++ "Date", ++ "Composer", ++ "Performer", ++ "Comment", ++ "Disc", ++ "Filename", ++ "Any" ++}; ++ ++static char *mpd_sanitizeArg(const char *arg) ++{ ++ size_t i; ++ char *ret; ++ register const char *c; ++ register char *rc; ++ ++ /* instead of counting in that loop above, just ++ * use a bit more memory and half running time ++ */ ++ ret = malloc(strlen(arg) * 2 + 1); ++ ++ c = arg; ++ rc = ret; ++ for (i = strlen(arg) + 1; i != 0; --i) { ++ if (*c == '"' || *c == '\\') ++ *rc++ = '\\'; ++ *(rc++) = *(c++); ++ } ++ ++ return ret; ++} ++ ++static mpd_ReturnElement *mpd_newReturnElement(const char *name, const char *value) ++{ ++ mpd_ReturnElement *ret = malloc(sizeof(mpd_ReturnElement)); ++ ++ ret->name = strdup(name); ++ ret->value = strdup(value); ++ ++ return ret; ++} ++ ++static void mpd_freeReturnElement(mpd_ReturnElement * re) ++{ ++ free(re->name); ++ free(re->value); ++ free(re); ++} ++ ++void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout) ++{ ++ connection->timeout.tv_sec = (int) timeout; ++ connection->timeout.tv_usec = (int) (timeout * 1e6 - connection->timeout.tv_sec * 1000000 + 0.5); ++} ++ ++static int mpd_parseWelcome(mpd_Connection * connection, const char *host, int port, char *rt, char *output) ++{ ++ char *tmp; ++ char *test; ++ int i; ++ ++ if (strncmp(output, MPD_WELCOME_MESSAGE, strlen(MPD_WELCOME_MESSAGE))) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, ++ "mpd not running on port %i on host \"%s\"", port, host); ++ connection->error = MPD_ERROR_NOTMPD; ++ return 1; ++ } ++ ++ tmp = &output[strlen(MPD_WELCOME_MESSAGE)]; ++ ++ for (i = 0; i < 3; i++) { ++ if (tmp) ++ connection->version[i] = strtol(tmp, &test, 10); ++ ++ if (!tmp || (test[0] != '.' && test[0] != '\0')) { ++ snprintf(connection->errorStr, ++ MPD_ERRORSTR_MAX_LENGTH, ++ "error parsing version number at " "\"%s\"", &output[strlen(MPD_WELCOME_MESSAGE)]); ++ connection->error = MPD_ERROR_NOTMPD; ++ return 1; ++ } ++ tmp = ++test; ++ } ++ ++ return 0; ++} ++ ++mpd_Connection *mpd_newConnection(const char *host, int port, float timeout) ++{ ++ int err; ++ char *rt; ++ char *output = NULL; ++ mpd_Connection *connection = malloc(sizeof(mpd_Connection)); ++ struct timeval tv; ++ fd_set fds; ++ strcpy(connection->buffer, ""); ++ connection->buflen = 0; ++ connection->bufstart = 0; ++ strcpy(connection->errorStr, ""); ++ connection->error = 0; ++ connection->doneProcessing = 0; ++ connection->commandList = 0; ++ connection->listOks = 0; ++ connection->doneListOk = 0; ++ connection->returnElement = NULL; ++ connection->request = NULL; ++ ++ if (winsock_dll_error(connection)) ++ return connection; ++ ++ if (mpd_connect(connection, host, port, timeout) < 0) ++ return connection; ++ ++ while (!(rt = strstr(connection->buffer, "\n"))) { ++ tv.tv_sec = connection->timeout.tv_sec; ++ tv.tv_usec = connection->timeout.tv_usec; ++ FD_ZERO(&fds); ++ FD_SET(connection->sock, &fds); ++ if ((err = select(connection->sock + 1, &fds, NULL, NULL, &tv)) == 1) { ++ int readed; ++ readed = recv(connection->sock, ++ &(connection->buffer[connection->buflen]), MPD_BUFFER_MAX_LENGTH - connection->buflen, 0); ++ if (readed <= 0) { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, ++ "problems getting a response from" " \"%s\" on port %i : %s", host, port, strerror(errno)); ++ connection->error = MPD_ERROR_NORESPONSE; ++ return connection; ++ } ++ connection->buflen += readed; ++ connection->buffer[connection->buflen] = '\0'; ++ } else if (err < 0) { ++ if (SELECT_ERRNO_IGNORE) ++ continue; ++ snprintf(connection->errorStr, ++ MPD_ERRORSTR_MAX_LENGTH, "problems connecting to \"%s\" on port" " %i", host, port); ++ connection->error = MPD_ERROR_CONNPORT; ++ return connection; ++ } else { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, ++ "timeout in attempting to get a response from" " \"%s\" on port %i", host, port); ++ connection->error = MPD_ERROR_NORESPONSE; ++ return connection; ++ } ++ } ++ ++ *rt = '\0'; ++ output = strdup(connection->buffer); ++ strcpy(connection->buffer, rt + 1); ++ connection->buflen = strlen(connection->buffer); ++ ++ if (mpd_parseWelcome(connection, host, port, rt, output) == 0) ++ connection->doneProcessing = 1; ++ ++ free(output); ++ ++ return connection; ++} ++ ++void mpd_clearError(mpd_Connection * connection) ++{ ++ connection->error = 0; ++ connection->errorStr[0] = '\0'; ++} ++ ++void mpd_closeConnection(mpd_Connection * connection) ++{ ++ closesocket(connection->sock); ++ if (connection->returnElement) ++ free(connection->returnElement); ++ if (connection->request) ++ free(connection->request); ++ free(connection); ++ WSACleanup(); ++} ++ ++static void mpd_executeCommand(mpd_Connection * connection, char *command) ++{ ++ int ret; ++ struct timeval tv; ++ fd_set fds; ++ char *commandPtr = command; ++ int commandLen = strlen(command); ++ ++ if (!connection->doneProcessing && !connection->commandList) { ++ strcpy(connection->errorStr, "not done processing current command"); ++ connection->error = 1; ++ return; ++ } ++ ++ mpd_clearError(connection); ++ ++ FD_ZERO(&fds); ++ FD_SET(connection->sock, &fds); ++ tv.tv_sec = connection->timeout.tv_sec; ++ tv.tv_usec = connection->timeout.tv_usec; ++ ++ while ((ret = select(connection->sock + 1, NULL, &fds, NULL, &tv) == 1) || (ret == -1 && SELECT_ERRNO_IGNORE)) { ++ ret = send(connection->sock, commandPtr, commandLen, MSG_DONTWAIT); ++ if (ret <= 0) { ++ if (SENDRECV_ERRNO_IGNORE) ++ continue; ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "problems giving command \"%s\"", command); ++ connection->error = MPD_ERROR_SENDING; ++ return; ++ } else { ++ commandPtr += ret; ++ commandLen -= ret; ++ } ++ ++ if (commandLen <= 0) ++ break; ++ } ++ ++ if (commandLen > 0) { ++ perror(""); ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "timeout sending command \"%s\"", command); ++ connection->error = MPD_ERROR_TIMEOUT; ++ return; ++ } ++ ++ if (!connection->commandList) ++ connection->doneProcessing = 0; ++ else if (connection->commandList == COMMAND_LIST_OK) { ++ connection->listOks++; ++ } ++} ++ ++static void mpd_getNextReturnElement(mpd_Connection * connection) ++{ ++ char *output = NULL; ++ char *rt = NULL; ++ char *name = NULL; ++ char *value = NULL; ++ fd_set fds; ++ struct timeval tv; ++ char *tok = NULL; ++ int readed; ++ char *bufferCheck = NULL; ++ int err; ++ int pos; ++ ++ if (connection->returnElement) ++ mpd_freeReturnElement(connection->returnElement); ++ connection->returnElement = NULL; ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ strcpy(connection->errorStr, "already done processing current command"); ++ connection->error = 1; ++ return; ++ } ++ ++ bufferCheck = connection->buffer + connection->bufstart; ++ while (connection->bufstart >= connection->buflen || !(rt = strchr(bufferCheck, '\n'))) { ++ if (connection->buflen >= MPD_BUFFER_MAX_LENGTH) { ++ memmove(connection->buffer, ++ connection->buffer + connection->bufstart, connection->buflen - connection->bufstart + 1); ++ connection->buflen -= connection->bufstart; ++ connection->bufstart = 0; ++ } ++ if (connection->buflen >= MPD_BUFFER_MAX_LENGTH) { ++ strcpy(connection->errorStr, "buffer overrun"); ++ connection->error = MPD_ERROR_BUFFEROVERRUN; ++ connection->doneProcessing = 1; ++ connection->doneListOk = 0; ++ return; ++ } ++ bufferCheck = connection->buffer + connection->buflen; ++ tv.tv_sec = connection->timeout.tv_sec; ++ tv.tv_usec = connection->timeout.tv_usec; ++ FD_ZERO(&fds); ++ FD_SET(connection->sock, &fds); ++ if ((err = select(connection->sock + 1, &fds, NULL, NULL, &tv) == 1)) { ++ readed = recv(connection->sock, ++ connection->buffer + connection->buflen, ++ MPD_BUFFER_MAX_LENGTH - connection->buflen, MSG_DONTWAIT); ++ if (readed < 0 && SENDRECV_ERRNO_IGNORE) { ++ continue; ++ } ++ if (readed <= 0) { ++ strcpy(connection->errorStr, "connection" " closed"); ++ connection->error = MPD_ERROR_CONNCLOSED; ++ connection->doneProcessing = 1; ++ connection->doneListOk = 0; ++ return; ++ } ++ connection->buflen += readed; ++ connection->buffer[connection->buflen] = '\0'; ++ } else if (err < 0 && SELECT_ERRNO_IGNORE) ++ continue; ++ else { ++ strcpy(connection->errorStr, "connection timeout"); ++ connection->error = MPD_ERROR_TIMEOUT; ++ connection->doneProcessing = 1; ++ connection->doneListOk = 0; ++ return; ++ } ++ } ++ ++ *rt = '\0'; ++ output = connection->buffer + connection->bufstart; ++ connection->bufstart = rt - connection->buffer + 1; ++ ++ if (strcmp(output, "OK") == 0) { ++ if (connection->listOks > 0) { ++ strcpy(connection->errorStr, "expected more list_OK's"); ++ connection->error = 1; ++ } ++ connection->listOks = 0; ++ connection->doneProcessing = 1; ++ connection->doneListOk = 0; ++ return; ++ } ++ ++ if (strcmp(output, "list_OK") == 0) { ++ if (!connection->listOks) { ++ strcpy(connection->errorStr, "got an unexpected list_OK"); ++ connection->error = 1; ++ } else { ++ connection->doneListOk = 1; ++ connection->listOks--; ++ } ++ return; ++ } ++ ++ if (strncmp(output, "ACK", strlen("ACK")) == 0) { ++ char *test; ++ char *needle; ++ int val; ++ ++ strcpy(connection->errorStr, output); ++ connection->error = MPD_ERROR_ACK; ++ connection->errorCode = MPD_ACK_ERROR_UNK; ++ connection->errorAt = MPD_ERROR_AT_UNK; ++ connection->doneProcessing = 1; ++ connection->doneListOk = 0; ++ ++ needle = strchr(output, '['); ++ if (!needle) ++ return; ++ val = strtol(needle + 1, &test, 10); ++ if (*test != '@') ++ return; ++ connection->errorCode = val; ++ val = strtol(test + 1, &test, 10); ++ if (*test != ']') ++ return; ++ connection->errorAt = val; ++ return; ++ } ++ ++ tok = strchr(output, ':'); ++ if (!tok) ++ return; ++ pos = tok - output; ++ value = ++tok; ++ name = output; ++ name[pos] = '\0'; ++ ++ if (value[0] == ' ') { ++ connection->returnElement = mpd_newReturnElement(name, &(value[1])); ++ } else { ++ snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, "error parsing: %s:%s", name, value); ++ connection->error = 1; ++ } ++} ++ ++void mpd_finishCommand(mpd_Connection * connection) ++{ ++ while (!connection->doneProcessing) { ++ if (connection->doneListOk) ++ connection->doneListOk = 0; ++ mpd_getNextReturnElement(connection); ++ } ++} ++ ++static void mpd_finishListOkCommand(mpd_Connection * connection) ++{ ++ while (!connection->doneProcessing && connection->listOks && !connection->doneListOk) { ++ mpd_getNextReturnElement(connection); ++ } ++} ++ ++int mpd_nextListOkCommand(mpd_Connection * connection) ++{ ++ mpd_finishListOkCommand(connection); ++ if (!connection->doneProcessing) ++ connection->doneListOk = 0; ++ if (connection->listOks == 0 || connection->doneProcessing) ++ return -1; ++ return 0; ++} ++ ++void mpd_sendStatusCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "status\n"); ++} ++ ++mpd_Status *mpd_getStatus(mpd_Connection * connection) ++{ ++ mpd_Status *status; ++ ++ /*mpd_executeCommand(connection,"status\n"); ++ ++ if(connection->error) return NULL; */ ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ if (!connection->returnElement) ++ mpd_getNextReturnElement(connection); ++ ++ status = malloc(sizeof(mpd_Status)); ++ status->volume = -1; ++ status->repeat = 0; ++ status->random = 0; ++ status->playlist = -1; ++ status->playlistLength = -1; ++ status->state = -1; ++ status->song = 0; ++ status->songid = 0; ++ status->elapsedTime = 0; ++ status->totalTime = 0; ++ status->bitRate = 0; ++ status->sampleRate = 0; ++ status->bits = 0; ++ status->channels = 0; ++ status->crossfade = -1; ++ status->error = NULL; ++ status->updatingDb = 0; ++ ++ if (connection->error) { ++ free(status); ++ return NULL; ++ } ++ while (connection->returnElement) { ++ mpd_ReturnElement *re = connection->returnElement; ++ if (strcmp(re->name, "volume") == 0) { ++ status->volume = atoi(re->value); ++ } else if (strcmp(re->name, "repeat") == 0) { ++ status->repeat = atoi(re->value); ++ } else if (strcmp(re->name, "random") == 0) { ++ status->random = atoi(re->value); ++ } else if (strcmp(re->name, "playlist") == 0) { ++ status->playlist = strtol(re->value, NULL, 10); ++ } else if (strcmp(re->name, "playlistlength") == 0) { ++ status->playlistLength = atoi(re->value); ++ } else if (strcmp(re->name, "bitrate") == 0) { ++ status->bitRate = atoi(re->value); ++ } else if (strcmp(re->name, "state") == 0) { ++ if (strcmp(re->value, "play") == 0) { ++ status->state = MPD_STATUS_STATE_PLAY; ++ } else if (strcmp(re->value, "stop") == 0) { ++ status->state = MPD_STATUS_STATE_STOP; ++ } else if (strcmp(re->value, "pause") == 0) { ++ status->state = MPD_STATUS_STATE_PAUSE; ++ } else { ++ status->state = MPD_STATUS_STATE_UNKNOWN; ++ } ++ } else if (strcmp(re->name, "song") == 0) { ++ status->song = atoi(re->value); ++ } else if (strcmp(re->name, "songid") == 0) { ++ status->songid = atoi(re->value); ++ } else if (strcmp(re->name, "time") == 0) { ++ char *tok = strchr(re->value, ':'); ++ /* the second strchr below is a safety check */ ++ if (tok && (strchr(tok, 0) > (tok + 1))) { ++ /* atoi stops at the first non-[0-9] char: */ ++ status->elapsedTime = atoi(re->value); ++ status->totalTime = atoi(tok + 1); ++ } ++ } else if (strcmp(re->name, "error") == 0) { ++ status->error = strdup(re->value); ++ } else if (strcmp(re->name, "xfade") == 0) { ++ status->crossfade = atoi(re->value); ++ } else if (strcmp(re->name, "updating_db") == 0) { ++ status->updatingDb = atoi(re->value); ++ } else if (strcmp(re->name, "audio") == 0) { ++ char *tok = strchr(re->value, ':'); ++ if (tok && (strchr(tok, 0) > (tok + 1))) { ++ status->sampleRate = atoi(re->value); ++ status->bits = atoi(++tok); ++ tok = strchr(tok, ':'); ++ if (tok && (strchr(tok, 0) > (tok + 1))) ++ status->channels = atoi(tok + 1); ++ } ++ } ++ ++ mpd_getNextReturnElement(connection); ++ if (connection->error) { ++ free(status); ++ return NULL; ++ } ++ } ++ ++ if (connection->error) { ++ free(status); ++ return NULL; ++ } else if (status->state < 0) { ++ strcpy(connection->errorStr, "state not found"); ++ connection->error = 1; ++ free(status); ++ return NULL; ++ } ++ ++ return status; ++} ++ ++void mpd_freeStatus(mpd_Status * status) ++{ ++ if (status->error) ++ free(status->error); ++ free(status); ++} ++ ++void mpd_sendStatsCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "stats\n"); ++} ++ ++mpd_Stats *mpd_getStats(mpd_Connection * connection) ++{ ++ mpd_Stats *stats; ++ ++ /*mpd_executeCommand(connection,"stats\n"); ++ ++ if(connection->error) return NULL; */ ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ if (!connection->returnElement) ++ mpd_getNextReturnElement(connection); ++ ++ stats = malloc(sizeof(mpd_Stats)); ++ stats->numberOfArtists = 0; ++ stats->numberOfAlbums = 0; ++ stats->numberOfSongs = 0; ++ stats->uptime = 0; ++ stats->dbUpdateTime = 0; ++ stats->playTime = 0; ++ stats->dbPlayTime = 0; ++ ++ if (connection->error) { ++ free(stats); ++ return NULL; ++ } ++ while (connection->returnElement) { ++ mpd_ReturnElement *re = connection->returnElement; ++ if (strcmp(re->name, "artists") == 0) { ++ stats->numberOfArtists = atoi(re->value); ++ } else if (strcmp(re->name, "albums") == 0) { ++ stats->numberOfAlbums = atoi(re->value); ++ } else if (strcmp(re->name, "songs") == 0) { ++ stats->numberOfSongs = atoi(re->value); ++ } else if (strcmp(re->name, "uptime") == 0) { ++ stats->uptime = strtol(re->value, NULL, 10); ++ } else if (strcmp(re->name, "db_update") == 0) { ++ stats->dbUpdateTime = strtol(re->value, NULL, 10); ++ } else if (strcmp(re->name, "playtime") == 0) { ++ stats->playTime = strtol(re->value, NULL, 10); ++ } else if (strcmp(re->name, "db_playtime") == 0) { ++ stats->dbPlayTime = strtol(re->value, NULL, 10); ++ } ++ ++ mpd_getNextReturnElement(connection); ++ if (connection->error) { ++ free(stats); ++ return NULL; ++ } ++ } ++ ++ if (connection->error) { ++ free(stats); ++ return NULL; ++ } ++ ++ return stats; ++} ++ ++void mpd_freeStats(mpd_Stats * stats) ++{ ++ free(stats); ++} ++ ++mpd_SearchStats *mpd_getSearchStats(mpd_Connection * connection) ++{ ++ mpd_SearchStats *stats; ++ mpd_ReturnElement *re; ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ if (!connection->returnElement) ++ mpd_getNextReturnElement(connection); ++ ++ if (connection->error) ++ return NULL; ++ ++ stats = malloc(sizeof(mpd_SearchStats)); ++ stats->numberOfSongs = 0; ++ stats->playTime = 0; ++ ++ while (connection->returnElement) { ++ re = connection->returnElement; ++ ++ if (strcmp(re->name, "songs") == 0) { ++ stats->numberOfSongs = atoi(re->value); ++ } else if (strcmp(re->name, "playtime") == 0) { ++ stats->playTime = strtol(re->value, NULL, 10); ++ } ++ ++ mpd_getNextReturnElement(connection); ++ if (connection->error) { ++ free(stats); ++ return NULL; ++ } ++ } ++ ++ if (connection->error) { ++ free(stats); ++ return NULL; ++ } ++ ++ return stats; ++} ++ ++void mpd_freeSearchStats(mpd_SearchStats * stats) ++{ ++ free(stats); ++} ++ ++static void mpd_initSong(mpd_Song * song) ++{ ++ song->file = NULL; ++ song->artist = NULL; ++ song->album = NULL; ++ song->track = NULL; ++ song->title = NULL; ++ song->name = NULL; ++ song->date = NULL; ++ /* added by Qball */ ++ song->genre = NULL; ++ song->composer = NULL; ++ song->performer = NULL; ++ song->disc = NULL; ++ song->comment = NULL; ++ ++ song->time = MPD_SONG_NO_TIME; ++ song->pos = MPD_SONG_NO_NUM; ++ song->id = MPD_SONG_NO_ID; ++} ++ ++static void mpd_finishSong(mpd_Song * song) ++{ ++ if (song->file) ++ free(song->file); ++ if (song->artist) ++ free(song->artist); ++ if (song->album) ++ free(song->album); ++ if (song->title) ++ free(song->title); ++ if (song->track) ++ free(song->track); ++ if (song->name) ++ free(song->name); ++ if (song->date) ++ free(song->date); ++ if (song->genre) ++ free(song->genre); ++ if (song->composer) ++ free(song->composer); ++ if (song->disc) ++ free(song->disc); ++ if (song->comment) ++ free(song->comment); ++} ++ ++mpd_Song *mpd_newSong(void) ++{ ++ mpd_Song *ret = malloc(sizeof(mpd_Song)); ++ ++ mpd_initSong(ret); ++ ++ return ret; ++} ++ ++void mpd_freeSong(mpd_Song * song) ++{ ++ mpd_finishSong(song); ++ free(song); ++} ++ ++mpd_Song *mpd_songDup(mpd_Song * song) ++{ ++ mpd_Song *ret = mpd_newSong(); ++ ++ if (song->file) ++ ret->file = strdup(song->file); ++ if (song->artist) ++ ret->artist = strdup(song->artist); ++ if (song->album) ++ ret->album = strdup(song->album); ++ if (song->title) ++ ret->title = strdup(song->title); ++ if (song->track) ++ ret->track = strdup(song->track); ++ if (song->name) ++ ret->name = strdup(song->name); ++ if (song->date) ++ ret->date = strdup(song->date); ++ if (song->genre) ++ ret->genre = strdup(song->genre); ++ if (song->composer) ++ ret->composer = strdup(song->composer); ++ if (song->disc) ++ ret->disc = strdup(song->disc); ++ if (song->comment) ++ ret->comment = strdup(song->comment); ++ ret->time = song->time; ++ ret->pos = song->pos; ++ ret->id = song->id; ++ ++ return ret; ++} ++ ++static void mpd_initDirectory(mpd_Directory * directory) ++{ ++ directory->path = NULL; ++} ++ ++static void mpd_finishDirectory(mpd_Directory * directory) ++{ ++ if (directory->path) ++ free(directory->path); ++} ++ ++mpd_Directory *mpd_newDirectory(void) ++{ ++ mpd_Directory *directory = malloc(sizeof(mpd_Directory));; ++ ++ mpd_initDirectory(directory); ++ ++ return directory; ++} ++ ++void mpd_freeDirectory(mpd_Directory * directory) ++{ ++ mpd_finishDirectory(directory); ++ ++ free(directory); ++} ++ ++mpd_Directory *mpd_directoryDup(mpd_Directory * directory) ++{ ++ mpd_Directory *ret = mpd_newDirectory(); ++ ++ if (directory->path) ++ ret->path = strdup(directory->path); ++ ++ return ret; ++} ++ ++static void mpd_initPlaylistFile(mpd_PlaylistFile * playlist) ++{ ++ playlist->path = NULL; ++} ++ ++static void mpd_finishPlaylistFile(mpd_PlaylistFile * playlist) ++{ ++ if (playlist->path) ++ free(playlist->path); ++} ++ ++mpd_PlaylistFile *mpd_newPlaylistFile(void) ++{ ++ mpd_PlaylistFile *playlist = malloc(sizeof(mpd_PlaylistFile)); ++ ++ mpd_initPlaylistFile(playlist); ++ ++ return playlist; ++} ++ ++void mpd_freePlaylistFile(mpd_PlaylistFile * playlist) ++{ ++ mpd_finishPlaylistFile(playlist); ++ free(playlist); ++} ++ ++mpd_PlaylistFile *mpd_playlistFileDup(mpd_PlaylistFile * playlist) ++{ ++ mpd_PlaylistFile *ret = mpd_newPlaylistFile(); ++ ++ if (playlist->path) ++ ret->path = strdup(playlist->path); ++ ++ return ret; ++} ++ ++static void mpd_initInfoEntity(mpd_InfoEntity * entity) ++{ ++ entity->info.directory = NULL; ++} ++ ++static void mpd_finishInfoEntity(mpd_InfoEntity * entity) ++{ ++ if (entity->info.directory) { ++ if (entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { ++ mpd_freeDirectory(entity->info.directory); ++ } else if (entity->type == MPD_INFO_ENTITY_TYPE_SONG) { ++ mpd_freeSong(entity->info.song); ++ } else if (entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { ++ mpd_freePlaylistFile(entity->info.playlistFile); ++ } ++ } ++} ++ ++mpd_InfoEntity *mpd_newInfoEntity(void) ++{ ++ mpd_InfoEntity *entity = malloc(sizeof(mpd_InfoEntity)); ++ ++ mpd_initInfoEntity(entity); ++ ++ return entity; ++} ++ ++void mpd_freeInfoEntity(mpd_InfoEntity * entity) ++{ ++ mpd_finishInfoEntity(entity); ++ free(entity); ++} ++ ++static void mpd_sendInfoCommand(mpd_Connection * connection, char *command) ++{ ++ mpd_executeCommand(connection, command); ++} ++ ++mpd_InfoEntity *mpd_getNextInfoEntity(mpd_Connection * connection) ++{ ++ mpd_InfoEntity *entity = NULL; ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ if (!connection->returnElement) ++ mpd_getNextReturnElement(connection); ++ ++ if (connection->returnElement) { ++ if (strcmp(connection->returnElement->name, "file") == 0) { ++ entity = mpd_newInfoEntity(); ++ entity->type = MPD_INFO_ENTITY_TYPE_SONG; ++ entity->info.song = mpd_newSong(); ++ entity->info.song->file = strdup(connection->returnElement->value); ++ } else if (strcmp(connection->returnElement->name, "directory") == 0) { ++ entity = mpd_newInfoEntity(); ++ entity->type = MPD_INFO_ENTITY_TYPE_DIRECTORY; ++ entity->info.directory = mpd_newDirectory(); ++ entity->info.directory->path = strdup(connection->returnElement->value); ++ } else if (strcmp(connection->returnElement->name, "playlist") == 0) { ++ entity = mpd_newInfoEntity(); ++ entity->type = MPD_INFO_ENTITY_TYPE_PLAYLISTFILE; ++ entity->info.playlistFile = mpd_newPlaylistFile(); ++ entity->info.playlistFile->path = strdup(connection->returnElement->value); ++ } else if (strcmp(connection->returnElement->name, "cpos") == 0) { ++ entity = mpd_newInfoEntity(); ++ entity->type = MPD_INFO_ENTITY_TYPE_SONG; ++ entity->info.song = mpd_newSong(); ++ entity->info.song->pos = atoi(connection->returnElement->value); ++ } else { ++ connection->error = 1; ++ strcpy(connection->errorStr, "problem parsing song info"); ++ return NULL; ++ } ++ } else ++ return NULL; ++ ++ mpd_getNextReturnElement(connection); ++ while (connection->returnElement) { ++ mpd_ReturnElement *re = connection->returnElement; ++ ++ if (strcmp(re->name, "file") == 0) ++ return entity; ++ else if (strcmp(re->name, "directory") == 0) ++ return entity; ++ else if (strcmp(re->name, "playlist") == 0) ++ return entity; ++ else if (strcmp(re->name, "cpos") == 0) ++ return entity; ++ ++ if (entity->type == MPD_INFO_ENTITY_TYPE_SONG && strlen(re->value)) { ++ if (!entity->info.song->artist && strcmp(re->name, "Artist") == 0) { ++ entity->info.song->artist = strdup(re->value); ++ } else if (!entity->info.song->album && strcmp(re->name, "Album") == 0) { ++ entity->info.song->album = strdup(re->value); ++ } else if (!entity->info.song->title && strcmp(re->name, "Title") == 0) { ++ entity->info.song->title = strdup(re->value); ++ } else if (!entity->info.song->track && strcmp(re->name, "Track") == 0) { ++ entity->info.song->track = strdup(re->value); ++ } else if (!entity->info.song->name && strcmp(re->name, "Name") == 0) { ++ entity->info.song->name = strdup(re->value); ++ } else if (entity->info.song->time == MPD_SONG_NO_TIME && strcmp(re->name, "Time") == 0) { ++ entity->info.song->time = atoi(re->value); ++ } else if (entity->info.song->pos == MPD_SONG_NO_NUM && strcmp(re->name, "Pos") == 0) { ++ entity->info.song->pos = atoi(re->value); ++ } else if (entity->info.song->id == MPD_SONG_NO_ID && strcmp(re->name, "Id") == 0) { ++ entity->info.song->id = atoi(re->value); ++ } else if (!entity->info.song->date && strcmp(re->name, "Date") == 0) { ++ entity->info.song->date = strdup(re->value); ++ } else if (!entity->info.song->genre && strcmp(re->name, "Genre") == 0) { ++ entity->info.song->genre = strdup(re->value); ++ } else if (!entity->info.song->composer && strcmp(re->name, "Composer") == 0) { ++ entity->info.song->composer = strdup(re->value); ++ } else if (!entity->info.song->performer && strcmp(re->name, "Performer") == 0) { ++ entity->info.song->performer = strdup(re->value); ++ } else if (!entity->info.song->disc && strcmp(re->name, "Disc") == 0) { ++ entity->info.song->disc = strdup(re->value); ++ } else if (!entity->info.song->comment && strcmp(re->name, "Comment") == 0) { ++ entity->info.song->comment = strdup(re->value); ++ } ++ } else if (entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { ++ } else if (entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { ++ } ++ ++ mpd_getNextReturnElement(connection); ++ } ++ ++ return entity; ++} ++ ++static char *mpd_getNextReturnElementNamed(mpd_Connection * connection, const char *name) ++{ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ mpd_getNextReturnElement(connection); ++ while (connection->returnElement) { ++ mpd_ReturnElement *re = connection->returnElement; ++ ++ if (strcmp(re->name, name) == 0) ++ return strdup(re->value); ++ mpd_getNextReturnElement(connection); ++ } ++ ++ return NULL; ++} ++ ++char *mpd_getNextTag(mpd_Connection * connection, int type) ++{ ++ if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES || type == MPD_TAG_ITEM_ANY) ++ return NULL; ++ if (type == MPD_TAG_ITEM_FILENAME) ++ return mpd_getNextReturnElementNamed(connection, "file"); ++ return mpd_getNextReturnElementNamed(connection, mpdTagItemKeys[type]); ++} ++ ++char *mpd_getNextArtist(mpd_Connection * connection) ++{ ++ return mpd_getNextReturnElementNamed(connection, "Artist"); ++} ++ ++char *mpd_getNextAlbum(mpd_Connection * connection) ++{ ++ return mpd_getNextReturnElementNamed(connection, "Album"); ++} ++ ++void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songPos) ++{ ++ int len = strlen("playlistinfo") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistinfo \"%i\"\n", songPos); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendPlaylistIdCommand(mpd_Connection * connection, int id) ++{ ++ int len = strlen("playlistid") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistid \"%i\"\n", id); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist) ++{ ++ int len = strlen("plchanges") + 2 + LONGLONGLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "plchanges \"%lld\"\n", playlist); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendPlChangesPosIdCommand(mpd_Connection * connection, long long playlist) ++{ ++ int len = strlen("plchangesposid") + 2 + LONGLONGLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "plchangesposid \"%lld\"\n", playlist); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendListallCommand(mpd_Connection * connection, const char *dir) ++{ ++ char *sDir = mpd_sanitizeArg(dir); ++ int len = strlen("listall") + 2 + strlen(sDir) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "listall \"%s\"\n", sDir); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++ free(sDir); ++} ++ ++void mpd_sendListallInfoCommand(mpd_Connection * connection, const char *dir) ++{ ++ char *sDir = mpd_sanitizeArg(dir); ++ int len = strlen("listallinfo") + 2 + strlen(sDir) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "listallinfo \"%s\"\n", sDir); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++ free(sDir); ++} ++ ++void mpd_sendLsInfoCommand(mpd_Connection * connection, const char *dir) ++{ ++ char *sDir = mpd_sanitizeArg(dir); ++ int len = strlen("lsinfo") + 2 + strlen(sDir) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "lsinfo \"%s\"\n", sDir); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++ free(sDir); ++} ++ ++void mpd_sendCurrentSongCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "currentsong\n"); ++} ++ ++void mpd_sendSearchCommand(mpd_Connection * connection, int table, const char *str) ++{ ++ mpd_startSearch(connection, 0); ++ mpd_addConstraintSearch(connection, table, str); ++ mpd_commitSearch(connection); ++} ++ ++void mpd_sendFindCommand(mpd_Connection * connection, int table, const char *str) ++{ ++ mpd_startSearch(connection, 1); ++ mpd_addConstraintSearch(connection, table, str); ++ mpd_commitSearch(connection); ++} ++ ++void mpd_sendListCommand(mpd_Connection * connection, int table, const char *arg1) ++{ ++ char st[10]; ++ int len; ++ char *string; ++ if (table == MPD_TABLE_ARTIST) ++ strcpy(st, "artist"); ++ else if (table == MPD_TABLE_ALBUM) ++ strcpy(st, "album"); ++ else { ++ connection->error = 1; ++ strcpy(connection->errorStr, "unknown table for list"); ++ return; ++ } ++ if (arg1) { ++ char *sanitArg1 = mpd_sanitizeArg(arg1); ++ len = strlen("list") + 1 + strlen(sanitArg1) + 2 + strlen(st) + 3; ++ string = malloc(len); ++ snprintf(string, len, "list %s \"%s\"\n", st, sanitArg1); ++ free(sanitArg1); ++ } else { ++ len = strlen("list") + 1 + strlen(st) + 2; ++ string = malloc(len); ++ snprintf(string, len, "list %s\n", st); ++ } ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendAddCommand(mpd_Connection * connection, const char *file) ++{ ++ char *sFile = mpd_sanitizeArg(file); ++ int len = strlen("add") + 2 + strlen(sFile) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "add \"%s\"\n", sFile); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sFile); ++} ++ ++int mpd_sendAddIdCommand(mpd_Connection * connection, const char *file) ++{ ++ int retval = -1; ++ char *sFile = mpd_sanitizeArg(file); ++ int len = strlen("addid") + 2 + strlen(sFile) + 3; ++ char *string = malloc(len); ++ ++ snprintf(string, len, "addid \"%s\"\n", sFile); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++ free(sFile); ++ ++ string = mpd_getNextReturnElementNamed(connection, "Id"); ++ if (string) { ++ retval = atoi(string); ++ free(string); ++ } ++ ++ return retval; ++} ++ ++void mpd_sendDeleteCommand(mpd_Connection * connection, int songPos) ++{ ++ int len = strlen("delete") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "delete \"%i\"\n", songPos); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendDeleteIdCommand(mpd_Connection * connection, int id) ++{ ++ int len = strlen("deleteid") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "deleteid \"%i\"\n", id); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSaveCommand(mpd_Connection * connection, const char *name) ++{ ++ char *sName = mpd_sanitizeArg(name); ++ int len = strlen("save") + 2 + strlen(sName) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "save \"%s\"\n", sName); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sName); ++} ++ ++void mpd_sendLoadCommand(mpd_Connection * connection, const char *name) ++{ ++ char *sName = mpd_sanitizeArg(name); ++ int len = strlen("load") + 2 + strlen(sName) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "load \"%s\"\n", sName); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sName); ++} ++ ++void mpd_sendRmCommand(mpd_Connection * connection, const char *name) ++{ ++ char *sName = mpd_sanitizeArg(name); ++ int len = strlen("rm") + 2 + strlen(sName) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "rm \"%s\"\n", sName); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sName); ++} ++ ++void mpd_sendRenameCommand(mpd_Connection * connection, const char *from, const char *to) ++{ ++ char *sFrom = mpd_sanitizeArg(from); ++ char *sTo = mpd_sanitizeArg(to); ++ int len = strlen("rename") + 2 + strlen(sFrom) + 3 + strlen(sTo) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "rename \"%s\" \"%s\"\n", sFrom, sTo); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sFrom); ++ free(sTo); ++} ++ ++void mpd_sendShuffleCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "shuffle\n"); ++} ++ ++void mpd_sendClearCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "clear\n"); ++} ++ ++void mpd_sendPlayCommand(mpd_Connection * connection, int songPos) ++{ ++ int len = strlen("play") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "play \"%i\"\n", songPos); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendPlayIdCommand(mpd_Connection * connection, int id) ++{ ++ int len = strlen("playid") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playid \"%i\"\n", id); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendStopCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "stop\n"); ++} ++ ++void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode) ++{ ++ int len = strlen("pause") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "pause \"%i\"\n", pauseMode); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendNextCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "next\n"); ++} ++ ++void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to) ++{ ++ int len = strlen("move") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "move \"%i\" \"%i\"\n", from, to); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendMoveIdCommand(mpd_Connection * connection, int id, int to) ++{ ++ int len = strlen("moveid") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "moveid \"%i\" \"%i\"\n", id, to); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) ++{ ++ int len = strlen("swap") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "swap \"%i\" \"%i\"\n", song1, song2); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSwapIdCommand(mpd_Connection * connection, int id1, int id2) ++{ ++ int len = strlen("swapid") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "swapid \"%i\" \"%i\"\n", id1, id2); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) ++{ ++ int len = strlen("seek") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "seek \"%i\" \"%i\"\n", song, time); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSeekIdCommand(mpd_Connection * connection, int id, int time) ++{ ++ int len = strlen("seekid") + 2 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "seekid \"%i\" \"%i\"\n", id, time); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendUpdateCommand(mpd_Connection * connection, char *path) ++{ ++ char *sPath = mpd_sanitizeArg(path); ++ int len = strlen("update") + 2 + strlen(sPath) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "update \"%s\"\n", sPath); ++ mpd_sendInfoCommand(connection, string); ++ free(string); ++ free(sPath); ++} ++ ++int mpd_getUpdateId(mpd_Connection * connection) ++{ ++ char *jobid; ++ int ret = 0; ++ ++ jobid = mpd_getNextReturnElementNamed(connection, "updating_db"); ++ if (jobid) { ++ ret = atoi(jobid); ++ free(jobid); ++ } ++ ++ return ret; ++} ++ ++void mpd_sendPrevCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "previous\n"); ++} ++ ++void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode) ++{ ++ int len = strlen("repeat") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "repeat \"%i\"\n", repeatMode); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode) ++{ ++ int len = strlen("random") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "random \"%i\"\n", randomMode); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange) ++{ ++ int len = strlen("setvol") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "setvol \"%i\"\n", volumeChange); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange) ++{ ++ int len = strlen("volume") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "volume \"%i\"\n", volumeChange); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds) ++{ ++ int len = strlen("crossfade") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "crossfade \"%i\"\n", seconds); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendPasswordCommand(mpd_Connection * connection, const char *pass) ++{ ++ char *sPass = mpd_sanitizeArg(pass); ++ int len = strlen("password") + 2 + strlen(sPass) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "password \"%s\"\n", sPass); ++ mpd_executeCommand(connection, string); ++ free(string); ++ free(sPass); ++} ++ ++void mpd_sendCommandListBegin(mpd_Connection * connection) ++{ ++ if (connection->commandList) { ++ strcpy(connection->errorStr, "already in command list mode"); ++ connection->error = 1; ++ return; ++ } ++ connection->commandList = COMMAND_LIST; ++ mpd_executeCommand(connection, "command_list_begin\n"); ++} ++ ++void mpd_sendCommandListOkBegin(mpd_Connection * connection) ++{ ++ if (connection->commandList) { ++ strcpy(connection->errorStr, "already in command list mode"); ++ connection->error = 1; ++ return; ++ } ++ connection->commandList = COMMAND_LIST_OK; ++ mpd_executeCommand(connection, "command_list_ok_begin\n"); ++ connection->listOks = 0; ++} ++ ++void mpd_sendCommandListEnd(mpd_Connection * connection) ++{ ++ if (!connection->commandList) { ++ strcpy(connection->errorStr, "not in command list mode"); ++ connection->error = 1; ++ return; ++ } ++ connection->commandList = 0; ++ mpd_executeCommand(connection, "command_list_end\n"); ++} ++ ++void mpd_sendOutputsCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "outputs\n"); ++} ++ ++mpd_OutputEntity *mpd_getNextOutput(mpd_Connection * connection) ++{ ++ mpd_OutputEntity *output = NULL; ++ ++ if (connection->doneProcessing || (connection->listOks && connection->doneListOk)) { ++ return NULL; ++ } ++ ++ if (connection->error) ++ return NULL; ++ ++ output = malloc(sizeof(mpd_OutputEntity)); ++ output->id = -10; ++ output->name = NULL; ++ output->enabled = 0; ++ ++ if (!connection->returnElement) ++ mpd_getNextReturnElement(connection); ++ ++ while (connection->returnElement) { ++ mpd_ReturnElement *re = connection->returnElement; ++ if (strcmp(re->name, "outputid") == 0) { ++ if (output != NULL && output->id >= 0) ++ return output; ++ output->id = atoi(re->value); ++ } else if (strcmp(re->name, "outputname") == 0) { ++ output->name = strdup(re->value); ++ } else if (strcmp(re->name, "outputenabled") == 0) { ++ output->enabled = atoi(re->value); ++ } ++ ++ mpd_getNextReturnElement(connection); ++ if (connection->error) { ++ free(output); ++ return NULL; ++ } ++ ++ } ++ ++ return output; ++} ++ ++void mpd_sendEnableOutputCommand(mpd_Connection * connection, int outputId) ++{ ++ int len = strlen("enableoutput") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "enableoutput \"%i\"\n", outputId); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_sendDisableOutputCommand(mpd_Connection * connection, int outputId) ++{ ++ int len = strlen("disableoutput") + 2 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "disableoutput \"%i\"\n", outputId); ++ mpd_executeCommand(connection, string); ++ free(string); ++} ++ ++void mpd_freeOutputElement(mpd_OutputEntity * output) ++{ ++ free(output->name); ++ free(output); ++} ++ ++/** ++ * mpd_sendNotCommandsCommand ++ * odd naming, but it gets the not allowed commands ++ */ ++ ++void mpd_sendNotCommandsCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "notcommands\n"); ++} ++ ++/** ++ * mpd_sendCommandsCommand ++ * odd naming, but it gets the allowed commands ++ */ ++void mpd_sendCommandsCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "commands\n"); ++} ++ ++/** ++ * Get the next returned command ++ */ ++char *mpd_getNextCommand(mpd_Connection * connection) ++{ ++ return mpd_getNextReturnElementNamed(connection, "command"); ++} ++ ++void mpd_sendUrlHandlersCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "urlhandlers\n"); ++} ++ ++char *mpd_getNextHandler(mpd_Connection * connection) ++{ ++ return mpd_getNextReturnElementNamed(connection, "handler"); ++} ++ ++void mpd_sendTagTypesCommand(mpd_Connection * connection) ++{ ++ mpd_executeCommand(connection, "tagtypes\n"); ++} ++ ++char *mpd_getNextTagType(mpd_Connection * connection) ++{ ++ return mpd_getNextReturnElementNamed(connection, "tagtype"); ++} ++ ++void mpd_startSearch(mpd_Connection * connection, int exact) ++{ ++ if (connection->request) { ++ strcpy(connection->errorStr, "search already in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ if (exact) ++ connection->request = strdup("find"); ++ else ++ connection->request = strdup("search"); ++} ++ ++void mpd_startStatsSearch(mpd_Connection * connection) ++{ ++ if (connection->request) { ++ strcpy(connection->errorStr, "search already in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ connection->request = strdup("count"); ++} ++ ++void mpd_startPlaylistSearch(mpd_Connection * connection, int exact) ++{ ++ if (connection->request) { ++ strcpy(connection->errorStr, "search already in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ if (exact) ++ connection->request = strdup("playlistfind"); ++ else ++ connection->request = strdup("playlistsearch"); ++} ++ ++void mpd_startFieldSearch(mpd_Connection * connection, int type) ++{ ++ char *strtype; ++ int len; ++ ++ if (connection->request) { ++ strcpy(connection->errorStr, "search already in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { ++ strcpy(connection->errorStr, "invalid type specified"); ++ connection->error = 1; ++ return; ++ } ++ ++ strtype = mpdTagItemKeys[type]; ++ ++ len = 5 + strlen(strtype) + 1; ++ connection->request = malloc(len); ++ ++ snprintf(connection->request, len, "list %c%s", tolower(strtype[0]), strtype + 1); ++} ++ ++void mpd_addConstraintSearch(mpd_Connection * connection, int type, const char *name) ++{ ++ char *strtype; ++ char *arg; ++ int len; ++ char *string; ++ ++ if (!connection->request) { ++ strcpy(connection->errorStr, "no search in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { ++ strcpy(connection->errorStr, "invalid type specified"); ++ connection->error = 1; ++ return; ++ } ++ ++ if (name == NULL) { ++ strcpy(connection->errorStr, "no name specified"); ++ connection->error = 1; ++ return; ++ } ++ ++ string = strdup(connection->request); ++ strtype = mpdTagItemKeys[type]; ++ arg = mpd_sanitizeArg(name); ++ ++ len = strlen(string) + 1 + strlen(strtype) + 2 + strlen(arg) + 2; ++ connection->request = realloc(connection->request, len); ++ snprintf(connection->request, len, "%s %c%s \"%s\"", string, tolower(strtype[0]), strtype + 1, arg); ++ ++ free(string); ++ free(arg); ++} ++ ++void mpd_commitSearch(mpd_Connection * connection) ++{ ++ int len; ++ ++ if (!connection->request) { ++ strcpy(connection->errorStr, "no search in progress"); ++ connection->error = 1; ++ return; ++ } ++ ++ len = strlen(connection->request) + 2; ++ connection->request = realloc(connection->request, len); ++ connection->request[len - 2] = '\n'; ++ connection->request[len - 1] = '\0'; ++ mpd_sendInfoCommand(connection, connection->request); ++ ++ free(connection->request); ++ connection->request = NULL; ++} ++ ++/** ++ * @param connection a MpdConnection ++ * @param path the path to the playlist. ++ * ++ * List the content, with full metadata, of a stored playlist. ++ * ++ */ ++void mpd_sendListPlaylistInfoCommand(mpd_Connection * connection, char *path) ++{ ++ char *arg = mpd_sanitizeArg(path); ++ int len = strlen("listplaylistinfo") + 2 + strlen(arg) + 3; ++ char *query = malloc(len); ++ snprintf(query, len, "listplaylistinfo \"%s\"\n", arg); ++ mpd_sendInfoCommand(connection, query); ++ free(arg); ++ free(query); ++} ++ ++/** ++ * @param connection a MpdConnection ++ * @param path the path to the playlist. ++ * ++ * List the content of a stored playlist. ++ * ++ */ ++void mpd_sendListPlaylistCommand(mpd_Connection * connection, char *path) ++{ ++ char *arg = mpd_sanitizeArg(path); ++ int len = strlen("listplaylist") + 2 + strlen(arg) + 3; ++ char *query = malloc(len); ++ snprintf(query, len, "listplaylist \"%s\"\n", arg); ++ mpd_sendInfoCommand(connection, query); ++ free(arg); ++ free(query); ++} ++ ++void mpd_sendPlaylistClearCommand(mpd_Connection * connection, char *path) ++{ ++ char *sPath = mpd_sanitizeArg(path); ++ int len = strlen("playlistclear") + 2 + strlen(sPath) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistclear \"%s\"\n", sPath); ++ mpd_executeCommand(connection, string); ++ free(sPath); ++ free(string); ++} ++ ++void mpd_sendPlaylistAddCommand(mpd_Connection * connection, char *playlist, char *path) ++{ ++ char *sPlaylist = mpd_sanitizeArg(playlist); ++ char *sPath = mpd_sanitizeArg(path); ++ int len = strlen("playlistadd") + 2 + strlen(sPlaylist) + 3 + strlen(sPath) + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistadd \"%s\" \"%s\"\n", sPlaylist, sPath); ++ mpd_executeCommand(connection, string); ++ free(sPlaylist); ++ free(sPath); ++ free(string); ++} ++ ++void mpd_sendPlaylistMoveCommand(mpd_Connection * connection, char *playlist, int from, int to) ++{ ++ char *sPlaylist = mpd_sanitizeArg(playlist); ++ int len = strlen("playlistmove") + 2 + strlen(sPlaylist) + 3 + INTLEN + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistmove \"%s\" \"%i\" \"%i\"\n", sPlaylist, from, to); ++ mpd_executeCommand(connection, string); ++ free(sPlaylist); ++ free(string); ++} ++ ++void mpd_sendPlaylistDeleteCommand(mpd_Connection * connection, char *playlist, int pos) ++{ ++ char *sPlaylist = mpd_sanitizeArg(playlist); ++ int len = strlen("playlistdelete") + 2 + strlen(sPlaylist) + 3 + INTLEN + 3; ++ char *string = malloc(len); ++ snprintf(string, len, "playlistdelete \"%s\" \"%i\"\n", sPlaylist, pos); ++ mpd_executeCommand(connection, string); ++ free(sPlaylist); ++ free(string); ++} +--- /dev/null ++++ b/libmpdclient.h +@@ -0,0 +1,661 @@ ++/* libmpdclient ++ (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) ++ This project's homepage is: http://www.musicpd.org ++ ++ Redistribution and use in source and binary forms, with or without ++ modification, are permitted provided that the following conditions ++ are met: ++ ++ - Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ ++ - Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in the ++ documentation and/or other materials provided with the distribution. ++ ++ - Neither the name of the Music Player Daemon nor the names of its ++ contributors may be used to endorse or promote products derived from ++ this software without specific prior written permission. ++ ++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR ++ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++#ifndef LIBMPDCLIENT_H ++#define LIBMPDCLIENT_H ++ ++#ifdef WIN32 ++# define __W32API_USE_DLLIMPORT__ 1 ++#endif ++ ++#include ++#include ++#define MPD_BUFFER_MAX_LENGTH 50000 ++#define MPD_ERRORSTR_MAX_LENGTH 1000 ++#define MPD_WELCOME_MESSAGE "OK MPD " ++ ++#define MPD_ERROR_TIMEOUT 10 /* timeout trying to talk to mpd */ ++#define MPD_ERROR_SYSTEM 11 /* system error */ ++#define MPD_ERROR_UNKHOST 12 /* unknown host */ ++#define MPD_ERROR_CONNPORT 13 /* problems connecting to port on host */ ++#define MPD_ERROR_NOTMPD 14 /* mpd not running on port at host */ ++#define MPD_ERROR_NORESPONSE 15 /* no response on attempting to connect */ ++#define MPD_ERROR_SENDING 16 /* error sending command */ ++#define MPD_ERROR_CONNCLOSED 17 /* connection closed by mpd */ ++#define MPD_ERROR_ACK 18 /* ACK returned! */ ++#define MPD_ERROR_BUFFEROVERRUN 19 /* Buffer was overrun! */ ++ ++#define MPD_ACK_ERROR_UNK -1 ++#define MPD_ERROR_AT_UNK -1 ++ ++#define MPD_ACK_ERROR_NOT_LIST 1 ++#define MPD_ACK_ERROR_ARG 2 ++#define MPD_ACK_ERROR_PASSWORD 3 ++#define MPD_ACK_ERROR_PERMISSION 4 ++#define MPD_ACK_ERROR_UNKNOWN_CMD 5 ++ ++#define MPD_ACK_ERROR_NO_EXIST 50 ++#define MPD_ACK_ERROR_PLAYLIST_MAX 51 ++#define MPD_ACK_ERROR_SYSTEM 52 ++#define MPD_ACK_ERROR_PLAYLIST_LOAD 53 ++#define MPD_ACK_ERROR_UPDATE_ALREADY 54 ++#define MPD_ACK_ERROR_PLAYER_SYNC 55 ++#define MPD_ACK_ERROR_EXIST 56 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ typedef enum mpd_TagItems { ++ MPD_TAG_ITEM_ARTIST, ++ MPD_TAG_ITEM_ALBUM, ++ MPD_TAG_ITEM_TITLE, ++ MPD_TAG_ITEM_TRACK, ++ MPD_TAG_ITEM_NAME, ++ MPD_TAG_ITEM_GENRE, ++ MPD_TAG_ITEM_DATE, ++ MPD_TAG_ITEM_COMPOSER, ++ MPD_TAG_ITEM_PERFORMER, ++ MPD_TAG_ITEM_COMMENT, ++ MPD_TAG_ITEM_DISC, ++ MPD_TAG_ITEM_FILENAME, ++ MPD_TAG_ITEM_ANY, ++ MPD_TAG_NUM_OF_ITEM_TYPES ++ } mpd_TagItems; ++ ++ extern char *mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES]; ++ ++/* internal stuff don't touch this struct */ ++ typedef struct _mpd_ReturnElement { ++ char *name; ++ char *value; ++ } mpd_ReturnElement; ++ ++/* mpd_Connection ++ * holds info about connection to mpd ++ * use error, and errorStr to detect errors ++ */ ++ typedef struct _mpd_Connection { ++ /* use this to check the version of mpd */ ++ int version[3]; ++ /* IMPORTANT, you want to get the error messages from here */ ++ char errorStr[MPD_ERRORSTR_MAX_LENGTH + 1]; ++ int errorCode; ++ int errorAt; ++ /* this will be set to MPD_ERROR_* if there is an error, 0 if not */ ++ int error; ++ /* DON'T TOUCH any of the rest of this stuff */ ++ int sock; ++ char buffer[MPD_BUFFER_MAX_LENGTH + 1]; ++ int buflen; ++ int bufstart; ++ int doneProcessing; ++ int listOks; ++ int doneListOk; ++ int commandList; ++ mpd_ReturnElement *returnElement; ++ struct timeval timeout; ++ char *request; ++ } mpd_Connection; ++ ++/* mpd_newConnection ++ * use this to open a new connection ++ * you should use mpd_closeConnection, when your done with the connection, ++ * even if an error has occurred ++ * _timeout_ is the connection timeout period in seconds ++ */ ++ mpd_Connection *mpd_newConnection(const char *host, int port, float timeout); ++ ++ void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout); ++ ++/* mpd_closeConnection ++ * use this to close a connection and free'ing subsequent memory ++ */ ++ void mpd_closeConnection(mpd_Connection * connection); ++ ++/* mpd_clearError ++ * clears error ++ */ ++ void mpd_clearError(mpd_Connection * connection); ++ ++/* STATUS STUFF */ ++ ++/* use these with status.state to determine what state the player is in */ ++#define MPD_STATUS_STATE_UNKNOWN 0 ++#define MPD_STATUS_STATE_STOP 1 ++#define MPD_STATUS_STATE_PLAY 2 ++#define MPD_STATUS_STATE_PAUSE 3 ++ ++/* us this with status.volume to determine if mpd has volume support */ ++#define MPD_STATUS_NO_VOLUME -1 ++ ++/* mpd_Status ++ * holds info return from status command ++ */ ++ typedef struct mpd_Status { ++ /* 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */ ++ int volume; ++ /* 1 if repeat is on, 0 otherwise */ ++ int repeat; ++ /* 1 if random is on, 0 otherwise */ ++ int random; ++ /* playlist length */ ++ int playlistLength; ++ /* playlist, use this to determine when the playlist has changed */ ++ long long playlist; ++ /* use with MPD_STATUS_STATE_* to determine state of player */ ++ int state; ++ /* crossfade setting in seconds */ ++ int crossfade; ++ /* if a song is currently selected (always the case when state is ++ * PLAY or PAUSE), this is the position of the currently ++ * playing song in the playlist, beginning with 0 ++ */ ++ int song; ++ /* Song ID of the currently selected song */ ++ int songid; ++ /* time in seconds that have elapsed in the currently playing/paused ++ * song ++ */ ++ int elapsedTime; ++ /* length in seconds of the currently playing/paused song */ ++ int totalTime; ++ /* current bit rate in kbs */ ++ int bitRate; ++ /* audio sample rate */ ++ unsigned int sampleRate; ++ /* audio bits */ ++ int bits; ++ /* audio channels */ ++ int channels; ++ /* 1 if mpd is updating, 0 otherwise */ ++ int updatingDb; ++ /* error */ ++ char *error; ++ } mpd_Status; ++ ++ void mpd_sendStatusCommand(mpd_Connection * connection); ++ ++/* mpd_getStatus ++ * returns status info, be sure to free it with mpd_freeStatus() ++ * call this after mpd_sendStatusCommand() ++ */ ++ mpd_Status *mpd_getStatus(mpd_Connection * connection); ++ ++/* mpd_freeStatus ++ * free's status info malloc'd and returned by mpd_getStatus ++ */ ++ void mpd_freeStatus(mpd_Status * status); ++ ++ typedef struct _mpd_Stats { ++ int numberOfArtists; ++ int numberOfAlbums; ++ int numberOfSongs; ++ unsigned long uptime; ++ unsigned long dbUpdateTime; ++ unsigned long playTime; ++ unsigned long dbPlayTime; ++ } mpd_Stats; ++ ++ typedef struct _mpd_SearchStats { ++ int numberOfSongs; ++ unsigned long playTime; ++ } mpd_SearchStats; ++ ++ void mpd_sendStatsCommand(mpd_Connection * connection); ++ ++ mpd_Stats *mpd_getStats(mpd_Connection * connection); ++ ++ void mpd_freeStats(mpd_Stats * stats); ++ ++ mpd_SearchStats *mpd_getSearchStats(mpd_Connection * connection); ++ ++ void mpd_freeSearchStats(mpd_SearchStats * stats); ++ ++/* SONG STUFF */ ++ ++#define MPD_SONG_NO_TIME -1 ++#define MPD_SONG_NO_NUM -1 ++#define MPD_SONG_NO_ID -1 ++ ++/* mpd_Song ++ * for storing song info returned by mpd ++ */ ++ typedef struct _mpd_Song { ++ /* filename of song */ ++ char *file; ++ /* artist, maybe NULL if there is no tag */ ++ char *artist; ++ /* title, maybe NULL if there is no tag */ ++ char *title; ++ /* album, maybe NULL if there is no tag */ ++ char *album; ++ /* track, maybe NULL if there is no tag */ ++ char *track; ++ /* name, maybe NULL if there is no tag; it's the name of the current ++ * song, f.e. the icyName of the stream */ ++ char *name; ++ /* date */ ++ char *date; ++ ++ /* added by qball */ ++ /* Genre */ ++ char *genre; ++ /* Composer */ ++ char *composer; ++ /* Performer */ ++ char *performer; ++ /* Disc */ ++ char *disc; ++ /* Comment */ ++ char *comment; ++ ++ /* length of song in seconds, check that it is not MPD_SONG_NO_TIME */ ++ int time; ++ /* if plchanges/playlistinfo/playlistid used, is the position of the ++ * song in the playlist */ ++ int pos; ++ /* song id for a song in the playlist */ ++ int id; ++ } mpd_Song; ++ ++/* mpd_newSong ++ * use to allocate memory for a new mpd_Song ++ * file, artist, etc all initialized to NULL ++ * if your going to assign values to file, artist, etc ++ * be sure to malloc or strdup the memory ++ * use mpd_freeSong to free the memory for the mpd_Song, it will also ++ * free memory for file, artist, etc, so don't do it yourself ++ */ ++ mpd_Song *mpd_newSong(void); ++ ++/* mpd_freeSong ++ * use to free memory allocated by mpd_newSong ++ * also it will free memory pointed to by file, artist, etc, so be careful ++ */ ++ void mpd_freeSong(mpd_Song * song); ++ ++/* mpd_songDup ++ * works like strDup, but for a mpd_Song ++ */ ++ mpd_Song *mpd_songDup(mpd_Song * song); ++ ++/* DIRECTORY STUFF */ ++ ++/* mpd_Directory ++ * used to store info fro directory (right now that just the path) ++ */ ++ typedef struct _mpd_Directory { ++ char *path; ++ } mpd_Directory; ++ ++/* mpd_newDirectory ++ * allocates memory for a new directory ++ * use mpd_freeDirectory to free this memory ++ */ ++ mpd_Directory *mpd_newDirectory(void); ++ ++/* mpd_freeDirectory ++ * used to free memory allocated with mpd_newDirectory, and it frees ++ * path of mpd_Directory, so be careful ++ */ ++ void mpd_freeDirectory(mpd_Directory * directory); ++ ++/* mpd_directoryDup ++ * works like strdup, but for mpd_Directory ++ */ ++ mpd_Directory *mpd_directoryDup(mpd_Directory * directory); ++ ++/* PLAYLISTFILE STUFF */ ++ ++/* mpd_PlaylistFile ++ * stores info about playlist file returned by lsinfo ++ */ ++ typedef struct _mpd_PlaylistFile { ++ char *path; ++ } mpd_PlaylistFile; ++ ++/* mpd_newPlaylistFile ++ * allocates memory for new mpd_PlaylistFile, path is set to NULL ++ * free this memory with mpd_freePlaylistFile ++ */ ++ mpd_PlaylistFile *mpd_newPlaylistFile(void); ++ ++/* mpd_freePlaylist ++ * free memory allocated for freePlaylistFile, will also free ++ * path, so be careful ++ */ ++ void mpd_freePlaylistFile(mpd_PlaylistFile * playlist); ++ ++/* mpd_playlistFileDup ++ * works like strdup, but for mpd_PlaylistFile ++ */ ++ mpd_PlaylistFile *mpd_playlistFileDup(mpd_PlaylistFile * playlist); ++ ++/* INFO ENTITY STUFF */ ++ ++/* the type of entity returned from one of the commands that generates info ++ * use in conjunction with mpd_InfoEntity.type ++ */ ++#define MPD_INFO_ENTITY_TYPE_DIRECTORY 0 ++#define MPD_INFO_ENTITY_TYPE_SONG 1 ++#define MPD_INFO_ENTITY_TYPE_PLAYLISTFILE 2 ++ ++/* mpd_InfoEntity ++ * stores info on stuff returned info commands ++ */ ++ typedef struct mpd_InfoEntity { ++ /* the type of entity, use with MPD_INFO_ENTITY_TYPE_* to determine ++ * what this entity is (song, directory, etc...) ++ */ ++ int type; ++ /* the actual data you want, mpd_Song, mpd_Directory, etc */ ++ union { ++ mpd_Directory *directory; ++ mpd_Song *song; ++ mpd_PlaylistFile *playlistFile; ++ } info; ++ } mpd_InfoEntity; ++ ++ mpd_InfoEntity *mpd_newInfoEntity(void); ++ ++ void mpd_freeInfoEntity(mpd_InfoEntity * entity); ++ ++/* INFO COMMANDS AND STUFF */ ++ ++/* use this function to loop over after calling Info/Listall functions */ ++ mpd_InfoEntity *mpd_getNextInfoEntity(mpd_Connection * connection); ++ ++/* fetches the currently seeletect song (the song referenced by status->song ++ * and status->songid*/ ++ void mpd_sendCurrentSongCommand(mpd_Connection * connection); ++ ++/* songNum of -1, means to display the whole list */ ++ void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum); ++ ++/* songId of -1, means to display the whole list */ ++ void mpd_sendPlaylistIdCommand(mpd_Connection * connection, int songId); ++ ++/* use this to get the changes in the playlist since version _playlist_ */ ++ void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist); ++ ++/** ++ * @param connection: A valid and connected mpd_Connection. ++ * @param playlist: The playlist version you want the diff with. ++ * A more bandwidth efficient version of the mpd_sendPlChangesCommand. ++ * It only returns the pos+id of the changes song. ++ */ ++ void mpd_sendPlChangesPosIdCommand(mpd_Connection * connection, long long playlist); ++ ++/* recursivel fetches all songs/dir/playlists in "dir* (no metadata is ++ * returned) */ ++ void mpd_sendListallCommand(mpd_Connection * connection, const char *dir); ++ ++/* same as sendListallCommand, but also metadata is returned */ ++ void mpd_sendListallInfoCommand(mpd_Connection * connection, const char *dir); ++ ++/* non-recursive version of ListallInfo */ ++ void mpd_sendLsInfoCommand(mpd_Connection * connection, const char *dir); ++ ++#define MPD_TABLE_ARTIST MPD_TAG_ITEM_ARTIST ++#define MPD_TABLE_ALBUM MPD_TAG_ITEM_ALBUM ++#define MPD_TABLE_TITLE MPD_TAG_ITEM_TITLE ++#define MPD_TABLE_FILENAME MPD_TAG_ITEM_FILENAME ++ ++ void mpd_sendSearchCommand(mpd_Connection * connection, int table, const char *str); ++ ++ void mpd_sendFindCommand(mpd_Connection * connection, int table, const char *str); ++ ++/* LIST TAG COMMANDS */ ++ ++/* use this function fetch next artist entry, be sure to free the returned ++ * string. NULL means there are no more. Best used with sendListArtists ++ */ ++ char *mpd_getNextArtist(mpd_Connection * connection); ++ ++ char *mpd_getNextAlbum(mpd_Connection * connection); ++ ++ char *mpd_getNextTag(mpd_Connection * connection, int type); ++ ++/* list artist or albums by artist, arg1 should be set to the artist if ++ * listing albums by a artist, otherwise NULL for listing all artists or albums ++ */ ++ void mpd_sendListCommand(mpd_Connection * connection, int table, const char *arg1); ++ ++/* SIMPLE COMMANDS */ ++ ++ void mpd_sendAddCommand(mpd_Connection * connection, const char *file); ++ ++ int mpd_sendAddIdCommand(mpd_Connection * connection, const char *file); ++ ++ void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum); ++ ++ void mpd_sendDeleteIdCommand(mpd_Connection * connection, int songNum); ++ ++ void mpd_sendSaveCommand(mpd_Connection * connection, const char *name); ++ ++ void mpd_sendLoadCommand(mpd_Connection * connection, const char *name); ++ ++ void mpd_sendRmCommand(mpd_Connection * connection, const char *name); ++ ++ void mpd_sendRenameCommand(mpd_Connection * connection, const char *from, const char *to); ++ ++ void mpd_sendShuffleCommand(mpd_Connection * connection); ++ ++ void mpd_sendClearCommand(mpd_Connection * connection); ++ ++/* use this to start playing at the beginning, useful when in random mode */ ++#define MPD_PLAY_AT_BEGINNING -1 ++ ++ void mpd_sendPlayCommand(mpd_Connection * connection, int songNum); ++ ++ void mpd_sendPlayIdCommand(mpd_Connection * connection, int songNum); ++ ++ void mpd_sendStopCommand(mpd_Connection * connection); ++ ++ void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode); ++ ++ void mpd_sendNextCommand(mpd_Connection * connection); ++ ++ void mpd_sendPrevCommand(mpd_Connection * connection); ++ ++ void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to); ++ ++ void mpd_sendMoveIdCommand(mpd_Connection * connection, int from, int to); ++ ++ void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2); ++ ++ void mpd_sendSwapIdCommand(mpd_Connection * connection, int song1, int song2); ++ ++ void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time); ++ ++ void mpd_sendSeekIdCommand(mpd_Connection * connection, int song, int time); ++ ++ void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode); ++ ++ void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode); ++ ++ void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange); ++ ++/* WARNING: don't use volume command, its depreacted */ ++ void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange); ++ ++ void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds); ++ ++ void mpd_sendUpdateCommand(mpd_Connection * connection, char *path); ++ ++/* returns the update job id, call this after a update command*/ ++ int mpd_getUpdateId(mpd_Connection * connection); ++ ++ void mpd_sendPasswordCommand(mpd_Connection * connection, const char *pass); ++ ++/* after executing a command, when your done with it to get its status ++ * (you want to check connection->error for an error) ++ */ ++ void mpd_finishCommand(mpd_Connection * connection); ++ ++/* command list stuff, use this to do things like add files very quickly */ ++ void mpd_sendCommandListBegin(mpd_Connection * connection); ++ ++ void mpd_sendCommandListOkBegin(mpd_Connection * connection); ++ ++ void mpd_sendCommandListEnd(mpd_Connection * connection); ++ ++/* advance to the next listOk ++ * returns 0 if advanced to the next list_OK, ++ * returns -1 if it advanced to an OK or ACK */ ++ int mpd_nextListOkCommand(mpd_Connection * connection); ++ ++ typedef struct _mpd_OutputEntity { ++ int id; ++ char *name; ++ int enabled; ++ } mpd_OutputEntity; ++ ++ void mpd_sendOutputsCommand(mpd_Connection * connection); ++ ++ mpd_OutputEntity *mpd_getNextOutput(mpd_Connection * connection); ++ ++ void mpd_sendEnableOutputCommand(mpd_Connection * connection, int outputId); ++ ++ void mpd_sendDisableOutputCommand(mpd_Connection * connection, int outputId); ++ ++ void mpd_freeOutputElement(mpd_OutputEntity * output); ++ ++/** ++ * @param connection a #mpd_Connection ++ * ++ * Queries mpd for the allowed commands ++ */ ++ void mpd_sendCommandsCommand(mpd_Connection * connection); ++ ++/** ++ * @param connection a #mpd_Connection ++ * ++ * Queries mpd for the not allowed commands ++ */ ++ void mpd_sendNotCommandsCommand(mpd_Connection * connection); ++ ++/** ++ * @param connection a #mpd_Connection ++ * ++ * returns the next supported command. ++ * ++ * @returns a string, needs to be free'ed ++ */ ++ char *mpd_getNextCommand(mpd_Connection * connection); ++ ++ void mpd_sendUrlHandlersCommand(mpd_Connection * connection); ++ ++ char *mpd_getNextHandler(mpd_Connection * connection); ++ ++ void mpd_sendTagTypesCommand(mpd_Connection * connection); ++ ++ char *mpd_getNextTagType(mpd_Connection * connection); ++ ++/** ++ * @param connection a MpdConnection ++ * @param path the path to the playlist. ++ * ++ * List the content, with full metadata, of a stored playlist. ++ * ++ */ ++ void mpd_sendListPlaylistInfoCommand(mpd_Connection * connection, char *path); ++ ++/** ++ * @param connection a MpdConnection ++ * @param path the path to the playlist. ++ * ++ * List the content of a stored playlist. ++ * ++ */ ++ void mpd_sendListPlaylistCommand(mpd_Connection * connection, char *path); ++ ++/** ++ * @param connection a #mpd_Connection ++ * @param exact if to match exact ++ * ++ * starts a search, use mpd_addConstraintSearch to add ++ * a constraint to the search, and mpd_commitSearch to do the actual search ++ */ ++ void mpd_startSearch(mpd_Connection * connection, int exact); ++ ++/** ++ * @param connection a #mpd_Connection ++ * @param type ++ * @param name ++ */ ++ void mpd_addConstraintSearch(mpd_Connection * connection, int type, const char *name); ++ ++/** ++ * @param connection a #mpd_Connection ++ */ ++ void mpd_commitSearch(mpd_Connection * connection); ++ ++/** ++ * @param connection a #mpd_Connection ++ * @param type The type to search for ++ * ++ * starts a search for fields... f.e. get a list of artists would be: ++ * @code ++ * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); ++ * mpd_commitSearch(connection); ++ * @endcode ++ * ++ * or get a list of artist in genre "jazz" would be: ++ * @code ++ * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); ++ * mpd_addConstraintSearch(connection, MPD_TAG_ITEM_GENRE, "jazz") ++ * mpd_commitSearch(connection); ++ * @endcode ++ * ++ * mpd_startSearch will return a list of songs (and you need mpd_getNextInfoEntity) ++ * this one will return a list of only one field (the one specified with type) and you need ++ * mpd_getNextTag to get the results ++ */ ++ void mpd_startFieldSearch(mpd_Connection * connection, int type); ++ ++ void mpd_startPlaylistSearch(mpd_Connection * connection, int exact); ++ ++ void mpd_startStatsSearch(mpd_Connection * connection); ++ ++ void mpd_sendPlaylistClearCommand(mpd_Connection * connection, char *path); ++ ++ void mpd_sendPlaylistAddCommand(mpd_Connection * connection, char *playlist, char *path); ++ ++ void mpd_sendPlaylistMoveCommand(mpd_Connection * connection, char *playlist, int from, int to); ++ ++ void mpd_sendPlaylistDeleteCommand(mpd_Connection * connection, char *playlist, int pos); ++#ifdef __cplusplus ++} ++#endif ++#endif diff --git a/lcd4linux/patches/160-uinput_defs.patch b/lcd4linux/patches/160-uinput_defs.patch new file mode 100755 index 000000000..44b24b3c8 --- /dev/null +++ b/lcd4linux/patches/160-uinput_defs.patch @@ -0,0 +1,24 @@ +--- a/drv_G15.c ++++ b/drv_G15.c +@@ -42,6 +42,7 @@ + + #include + #include ++#include + #include + #include + +@@ -269,8 +270,13 @@ void drv_G15_initKeyHandling(char *devic + } + memset(&device, 0, sizeof(device)); + strncpy(device.name, "G15 Keys", UINPUT_MAX_NAME_SIZE); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + device.id.bustype = BUS_USB; + device.id.version = 4; ++#else ++ device.idbus = BUS_USB; ++ device.idversion = 4; ++#endif + + ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY); + diff --git a/lcd4linux/patches/170-add-generic-spidev-driver.patch b/lcd4linux/patches/170-add-generic-spidev-driver.patch new file mode 100755 index 000000000..4cd53d6a5 --- /dev/null +++ b/lcd4linux/patches/170-add-generic-spidev-driver.patch @@ -0,0 +1,195 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -71,6 +71,8 @@ drv_generic_i2c.c \ + drv_generic_i2c.h \ + drv_generic_keypad.c \ + drv_generic_keypad.h \ ++drv_generic_spidev.c \ ++drv_generic_spidev.h \ + drv_ASTUSB.c \ + drv_BeckmannEgle.c \ + drv_BWCT.c \ +--- /dev/null ++++ b/drv_generic_spidev.c +@@ -0,0 +1,89 @@ ++/* $Id$ ++ * $URL$ ++ * ++ * generic driver helper for displays connected via SPI bus ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * ++ * This file is part of LCD4Linux. ++ * ++ * LCD4Linux is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * LCD4Linux is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "debug.h" ++#include "qprintf.h" ++#include "cfg.h" ++#include "drv_generic_spidev.h" ++ ++static char *generic_spidev_section = ""; ++static char *generic_spidev_driver = ""; ++static int generic_spidev_fd; ++ ++int drv_generic_spidev_open(const char *section, const char *driver) ++{ ++ char *spidev; ++ ++ udelay_init(); ++ ++ generic_spidev_section = (char *) section; ++ generic_spidev_driver = (char *) driver; ++ ++ spidev = cfg_get(generic_spidev_section, "Port", NULL); ++ ++ info("%s: initializing SPI device %s", generic_spidev_driver, spidev); ++ generic_spidev_fd = open(spidev, O_WRONLY); ++ if (generic_spidev_fd < 0) { ++ error("%s: unable to open SPI device %s!\n", generic_spidev_driver, spidev); ++ goto exit_error; ++ } ++ ++ return 0; ++ ++ exit_error: ++ free(spidev); ++ return -1; ++} ++ ++int drv_generic_spidev_close(void) ++{ ++ close(generic_spidev_fd); ++ return 0; ++} ++ ++int drv_generic_spidev_transfer(const int count, struct spi_ioc_transfer *tr) ++{ ++ int ret; ++ ++ ret = ioctl(generic_spidev_fd, SPI_IOC_MESSAGE(count), tr); ++ if (ret < count) { ++ error("%s: can't send SPI message! (%s)\n", ++ generic_spidev_driver, strerror(errno)); ++ return -1; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drv_generic_spidev.h +@@ -0,0 +1,54 @@ ++/* $Id$ ++ * $URL$ ++ * ++ * generic driver helper for displays connected via SPI bus ++ * ++ * Copyright (C) 2012 Gabor Juhos ++ * Copyright (C) 2012 The LCD4Linux Team ++ * ++ * This file is part of LCD4Linux. ++ * ++ * LCD4Linux is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * LCD4Linux is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++/* ++ * ++ * exported fuctions: ++ * ++ * int drv_generic_spidev_open (const char *section, const char *driver) ++ * reads 'Port' entry from config and opens ++ * the SPI device ++ * returns 0 if ok, -1 on failure ++ * ++ * int drv_generic_spidev_close (void) ++ * closes SPI device ++ * returns 0 if ok, -1 on failure ++ * ++ * void drv_generic_spidev_transfer (int count, struct spi_ioc_transfer *tr) ++ * transfer data to/from the SPI device ++ * ++ */ ++ ++#ifndef _DRV_GENERIC_SPIDEV_H_ ++#define _DRV_GENERIC_SPIDEV_H_ ++ ++#include ++ ++int drv_generic_spidev_open(const char *section, const char *driver); ++int drv_generic_spidev_close(void); ++int drv_generic_spidev_transfer(const int count, struct spi_ioc_transfer *tr); ++ ++#endif /* _DRV_GENERIC_SPIDEV_H_ */ +--- a/drivers.m4 ++++ b/drivers.m4 +@@ -301,6 +301,7 @@ PARPORT="no" + SERIAL="no" + I2C="no" + KEYPAD="no" ++SPIDEV="no" + + # generic libraries + LIBUSB="no" +@@ -936,6 +937,12 @@ if test "$LIBJPEG" = "yes"; then + DRVLIBS="$DRVLIBS -ljpeg" + fi + ++# generic spidev driver ++if test "$SPIDEV" = "yes"; then ++ DRIVERS="$DRIVERS drv_generic_spidev.o" ++ AC_DEFINE(WITH_SPIDEV, 1, [SPIDEV driver]) ++fi ++ + # libusb + if test "$LIBUSB" = "yes"; then + DRVLIBS="$DRVLIBS -lusb" +--- a/configure.ac ++++ b/configure.ac +@@ -115,6 +115,9 @@ AC_ARG_WITH(outb, + + AC_CHECK_HEADERS([asm/io.h] [linux/parport.h linux/ppdev.h], [has_parport="true"], [has_parport="false"]) + ++# check for spidev ++AC_CHECK_HEADERS([linux/spi/spidev.h], [has_spidev="true"], [has_spidev="false"]) ++ + # drivers + sinclude(drivers.m4) + diff --git a/lcd4linux/patches/173-glcd2usb-bigendian-fix.patch b/lcd4linux/patches/173-glcd2usb-bigendian-fix.patch new file mode 100755 index 000000000..97e03c748 --- /dev/null +++ b/lcd4linux/patches/173-glcd2usb-bigendian-fix.patch @@ -0,0 +1,20 @@ +--- a/drv_GLCD2USB.c ++++ b/drv_GLCD2USB.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "cfg.h" +@@ -487,6 +488,9 @@ static int drv_GLCD2USB_start(const char + return -1; + } + ++ buffer.display_info.width = le16toh(buffer.display_info.width); ++ buffer.display_info.height = le16toh(buffer.display_info.height); ++ + info("%s: display name = %s", Name, buffer.display_info.name); + info("%s: display resolution = %d * %d", Name, buffer.display_info.width, buffer.display_info.height); + info("%s: display flags: %x", Name, buffer.display_info.flags); diff --git a/libell/Makefile b/libell/Makefile old mode 100644 new mode 100755 diff --git a/libmbim/Makefile b/libmbim/Makefile deleted file mode 100755 index cfcb5ba96..000000000 --- a/libmbim/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=libmbim -PKG_SOURCE_VERSION:=1.29.2 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git -#PKG_MIRROR_HASH:=0b0b46016738fc22355d5a58c8a2d1b2f04906c49c51a50b57a09640d13b00b7 - -PKG_MAINTAINER:=Nicholas Smith - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk -include $(INCLUDE_DIR)/meson.mk - -TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants -TARGET_LDFLAGS += -Wl,--gc-sections - -MESON_ARGS += \ - -Dintrospection=false \ - -Dman=false \ - -Dbash_completion=false \ - -Db_lto=true - -define Package/libmbim - SECTION:=libs - CATEGORY:=Libraries - DEPENDS:=+glib2 - TITLE:=Helper library and utils to talk to MBIM enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libmbim - LICENSE:=LGPL-2.0-or-later - LICENSE_FILES:=COPYING.LIB -endef - -define Package/libmbim/description - Helper library to talk to MBIM enabled modems. - Add mbim-utils for extra utilities. -endef - -define Package/mbim-utils - SECTION:=utils - CATEGORY:=Utilities - DEPENDS:=+libmbim - TITLE:=Utilities to talk to MBIM enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libmbim - LICENSE:=GPL-2.0-or-later - LICENSE_FILES:=COPYING -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) \ - $(PKG_INSTALL_DIR)/usr/include/libmbim-glib \ - $(1)/usr/include/ - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so* \ - $(1)/usr/lib/ - - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mbim-glib.pc \ - $(1)/usr/lib/pkgconfig -endef - -define Package/libmbim/install - $(INSTALL_DIR) \ - $(1)/usr/lib \ - $(1)/usr/libexec - - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so.* \ - $(1)/usr/lib/ - - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/mbim-proxy $(1)/usr/libexec/ -endef - -define Package/mbim-utils/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbimcli $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbim-network $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,libmbim)) -$(eval $(call BuildPackage,mbim-utils)) diff --git a/libqmi/Config.in b/libqmi/Config.in deleted file mode 100755 index 7dfa7ca52..000000000 --- a/libqmi/Config.in +++ /dev/null @@ -1,31 +0,0 @@ -menu "Configuration" - depends on PACKAGE_libqmi - -config LIBQMI_WITH_MBIM_QMUX - bool "Include MBIM QMUX service support" - default y - help - Compile libqmi with QMI-over-MBIM support - -config LIBQMI_WITH_QRTR_GLIB - bool "Include QRTR support" - default y - help - Compile libqmi with QRTR support - -choice - prompt "Select QMI message collection to build" - default LIBQMI_COLLECTION_BASIC - - config LIBQMI_COLLECTION_MINIMAL - depends on !MODEMMANAGER_WITH_QMI - bool "minimal" - - config LIBQMI_COLLECTION_BASIC - bool "basic (default)" - - config LIBQMI_COLLECTION_FULL - bool "full" -endchoice - -endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile deleted file mode 100755 index cecee6cb6..000000000 --- a/libqmi/Makefile +++ /dev/null @@ -1,111 +0,0 @@ -# -# Copyright (C) 2016 Velocloud Inc. -# Copyright (C) 2016 Aleksander Morgado -# -# This is free software, licensed under the GNU General Public License v2. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=libqmi -PKG_SOURCE_VERSION:=1.33.3 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git -#PKG_MIRROR_HASH:=711d16d75a6a9afaefcf2be1bc845a4a6181dff786dfbd079e41e91279a0be91 - -PKG_MAINTAINER:=Nicholas Smith - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk -include $(INCLUDE_DIR)/meson.mk - -TARGET_CFLAGS += -ffunction-sections -fdata-sections -fno-merge-all-constants -fmerge-constants -TARGET_LDFLAGS += -Wl,--gc-sections - -define Package/libqmi/config - source "$(SOURCE)/Config.in" -endef - -define Package/libqmi - SECTION:=libs - CATEGORY:=Libraries - DEPENDS:= \ - +glib2 \ - +LIBQMI_WITH_MBIM_QMUX:libmbim \ - +LIBQMI_WITH_QRTR_GLIB:libqrtr-glib - TITLE:=Helper library to talk to QMI enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libqmi - LICENSE:=LGPL-2.0-or-later - LICENSE_FILES:=COPYING.LIB -endef - -define Package/libqmi/description - Helper library talk to QMI enabled modems. - Add qmi-utils for extra utilities. -endef - -define Package/qmi-utils - SECTION:=utils - CATEGORY:=Utilities - DEPENDS:=+libqmi - TITLE:=Utilities to talk to QMI enabled modems - URL:=https://www.freedesktop.org/wiki/Software/libqmi - LICENSE:=GPL-2.0-or-later - LICENSE_FILES:=COPYING -endef - -define Package/libqmi-utils/description - Utils to talk to QMI enabled modems -endef - -MESON_ARGS += \ - -Dudev=false \ - -Dintrospection=false \ - -Dman=false \ - -Dbash_completion=false \ - -Db_lto=true \ - -Dmbim_qmux=$(if $(CONFIG_LIBQMI_WITH_MBIM_QMUX),true,false) \ - -Dqrtr=$(if $(CONFIG_LIBQMI_WITH_QRTR_GLIB),true,false) \ - -Dcollection=$(if $(CONFIG_LIBQMI_COLLECTION_MINIMAL),minimal\ - ,$(if $(CONFIG_LIBQMI_COLLECTION_BASIC),basic,full)) - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(CP) \ - $(PKG_INSTALL_DIR)/usr/include/libqmi-glib \ - $(1)/usr/include/ - - $(INSTALL_DIR) $(1)/usr/lib - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so* \ - $(1)/usr/lib/ - - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/qmi-glib.pc \ - $(1)/usr/lib/pkgconfig -endef - -define Package/libqmi/install - $(INSTALL_DIR) \ - $(1)/usr/lib \ - $(1)/usr/libexec - - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ - $(1)/usr/lib/ - - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/qmi-proxy $(1)/usr/libexec/ -endef - -define Package/qmi-utils/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmicli $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-network $(1)/usr/bin/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-firmware-update $(1)/usr/bin/ -endef - -$(eval $(call BuildPackage,libqmi)) -$(eval $(call BuildPackage,qmi-utils)) diff --git a/luci-app-adguardhome/Makefile b/luci-app-adguardhome/Makefile new file mode 100755 index 000000000..db03e8acb --- /dev/null +++ b/luci-app-adguardhome/Makefile @@ -0,0 +1,57 @@ +# Copyright (C) 2018-2019 Lienol +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-adguardhome +PKG_MAINTAINER:= + +LUCI_TITLE:=LuCI app for AdGuardHome +LUCI_PKGARCH:=all +LUCI_DEPENDS:=+ca-certs +curl +wget-ssl +PACKAGE_$(PKG_NAME)_INCLUDE_binary:adguardhome +LUCI_DESCRIPTION:=LuCI support for AdGuardHome + +define Package/$(PKG_NAME)/config +config PACKAGE_$(PKG_NAME)_INCLUDE_binary + bool "Include Binary File" + default y +endef + +PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_binary + +define Package/luci-app-adguardhome/conffiles +/usr/share/AdGuardHome/links.txt +/etc/config/AdGuardHome +/etc/AdGuardHome.yaml +endef + +define Package/luci-app-adguardhome/postinst +#!/bin/sh + /etc/init.d/AdGuardHome enable >/dev/null 2>&1 + enable=$(uci get AdGuardHome.AdGuardHome.enabled 2>/dev/null) + if [ "$enable" == "1" ]; then + /etc/init.d/AdGuardHome reload + fi + rm -f /tmp/luci-indexcache + rm -f /tmp/luci-modulecache/* +exit 0 +endef + +define Package/luci-app-adguardhome/prerm +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + /etc/init.d/AdGuardHome disable + /etc/init.d/AdGuardHome stop +uci -q batch <<-EOF >/dev/null 2>&1 + delete ucitrack.@AdGuardHome[-1] + commit ucitrack +EOF +fi +exit 0 +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua b/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua new file mode 100755 index 000000000..e9d37a766 --- /dev/null +++ b/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua @@ -0,0 +1,130 @@ +module("luci.controller.AdGuardHome",package.seeall) +local fs=require"nixio.fs" +local http=require"luci.http" +local uci=require"luci.model.uci".cursor() +function index() +local page = entry({"admin", "services", "AdGuardHome"},alias("admin", "services", "AdGuardHome", "base"),_("AdGuard Home")) +page.order = 10 +page.dependent = true +page.acl_depends = { "luci-app-adguardhome" } +entry({"admin","services","AdGuardHome","base"},cbi("AdGuardHome/base"),_("Base Setting"),1).leaf = true +entry({"admin","services","AdGuardHome","log"},form("AdGuardHome/log"),_("Log"),2).leaf = true +entry({"admin","services","AdGuardHome","manual"},cbi("AdGuardHome/manual"),_("Manual Config"),3).leaf = true +entry({"admin","services","AdGuardHome","status"},call("act_status")).leaf=true +entry({"admin", "services", "AdGuardHome", "check"}, call("check_update")) +entry({"admin", "services", "AdGuardHome", "doupdate"}, call("do_update")) +entry({"admin", "services", "AdGuardHome", "getlog"}, call("get_log")) +entry({"admin", "services", "AdGuardHome", "dodellog"}, call("do_dellog")) +entry({"admin", "services", "AdGuardHome", "reloadconfig"}, call("reload_config")) +entry({"admin", "services", "AdGuardHome", "gettemplateconfig"}, call("get_template_config")) +end +function get_template_config() + local b + local d="" + for cnt in io.lines("/tmp/resolv.conf.d/resolv.conf.auto") do + b=string.match (cnt,"^[^#]*nameserver%s+([^%s]+)$") + if (b~=nil) then + d=d.." - "..b.."\n" + end + end + local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") + local tbl = {} + local a="" + while (1) do + a=f:read("*l") + if (a=="#bootstrap_dns") then + a=d + elseif (a=="#upstream_dns") then + a=d + elseif (a==nil) then + break + end + table.insert(tbl, a) + end + f:close() + http.prepare_content("text/plain; charset=utf-8") + http.write(table.concat(tbl, "\n")) +end +function reload_config() + fs.remove("/tmp/AdGuardHometmpconfig.yaml") + http.prepare_content("application/json") + http.write('') +end +function act_status() + local e={} + local binpath=uci:get("AdGuardHome","AdGuardHome","binpath") + e.running=luci.sys.call("pgrep "..binpath.." >/dev/null")==0 + e.redirect=(fs.readfile("/var/run/AdGredir")=="1") + http.prepare_content("application/json") + http.write_json(e) +end +function do_update() + fs.writefile("/var/run/lucilogpos","0") + http.prepare_content("application/json") + http.write('') + local arg + if luci.http.formvalue("force") == "1" then + arg="force" + else + arg="" + end + if fs.access("/var/run/update_core") then + if arg=="force" then + luci.sys.exec("kill $(pgrep /usr/share/AdGuardHome/update_core.sh) ; sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") + end + else + luci.sys.exec("sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") + end +end +function get_log() + local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") + if (logfile==nil) then + http.write("no log available\n") + return + elseif (logfile=="syslog") then + if not fs.access("/var/run/AdGuardHomesyslog") then + luci.sys.exec("(/usr/share/AdGuardHome/getsyslog.sh &); sleep 1;") + end + logfile="/tmp/AdGuardHometmp.log" + fs.writefile("/var/run/AdGuardHomesyslog","1") + elseif not fs.access(logfile) then + http.write("") + return + end + http.prepare_content("text/plain; charset=utf-8") + local fdp + if fs.access("/var/run/lucilogreload") then + fdp=0 + fs.remove("/var/run/lucilogreload") + else + fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0 + end + local f=io.open(logfile, "r+") + f:seek("set",fdp) + local a=f:read(2048000) or "" + fdp=f:seek() + fs.writefile("/var/run/lucilogpos",tostring(fdp)) + f:close() + http.write(a) +end +function do_dellog() + local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") + fs.writefile(logfile,"") + http.prepare_content("application/json") + http.write('') +end +function check_update() + http.prepare_content("text/plain; charset=utf-8") + local fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0 + local f=io.open("/tmp/AdGuardHome_update.log", "r+") + f:seek("set",fdp) + local a=f:read(2048000) or "" + fdp=f:seek() + fs.writefile("/var/run/lucilogpos",tostring(fdp)) + f:close() +if fs.access("/var/run/update_core") then + http.write(a) +else + http.write(a.."\0") +end +end diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua new file mode 100755 index 000000000..6896b61ef --- /dev/null +++ b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua @@ -0,0 +1,304 @@ +require("luci.sys") +require("luci.util") +require("io") +local m,s,o,o1 +local fs=require"nixio.fs" +local uci=require"luci.model.uci".cursor() +local configpath=uci:get("AdGuardHome","AdGuardHome","configpath") or "/etc/AdGuardHome.yaml" +local binpath=uci:get("AdGuardHome","AdGuardHome","binpath") or "/usr/bin/AdGuardHome" +httpport=uci:get("AdGuardHome","AdGuardHome","httpport") or "3000" +m = Map("AdGuardHome", "AdGuard Home") +m.description = translate("Free and open source, powerful network-wide ads & trackers blocking DNS server.") +m:section(SimpleSection).template = "AdGuardHome/AdGuardHome_status" + +s = m:section(TypedSection, "AdGuardHome") +s.anonymous=true +s.addremove=false +---- enable +o = s:option(Flag, "enabled", translate("Enable")) +o.default = 0 +o.optional = false +---- httpport +o =s:option(Value,"httpport",translate("Browser management port")) +o.placeholder=3000 +o.default=3000 +o.datatype="port" +o.optional = false +o.description = translate("") +---- update warning not safe +local binmtime=uci:get("AdGuardHome","AdGuardHome","binmtime") or "0" +local e="" +if not fs.access(configpath) then + e=e.." "..translate("no config") +end +if not fs.access(binpath) then + e=e.." "..translate("no core") +else + local version=uci:get("AdGuardHome","AdGuardHome","version") + local testtime=fs.stat(binpath,"mtime") + if testtime~=tonumber(binmtime) or version==nil then + local tmp=luci.sys.exec(binpath.." --version | grep -m 1 -E 'v[0-9.]+' -o ") + version=string.sub(tmp, 1) + if version=="" then version="core error" end + uci:set("AdGuardHome","AdGuardHome","version",version) + uci:set("AdGuardHome","AdGuardHome","binmtime",testtime) + uci:save("AdGuardHome") + end + e=version..e +end +o=s:option(Button,"restart",translate("Update")) +o.inputtitle=translate("Update core version") +o.template = "AdGuardHome/AdGuardHome_check" +o.showfastconfig=(not fs.access(configpath)) +o.description=string.format(translate("core version:").."%s ",e) +---- port warning not safe +local port=luci.sys.exec("awk '/ port:/{printf($2);exit;}' "..configpath.." 2>nul") +if (port=="") then port="?" end +---- Redirect +o = s:option(ListValue, "redirect", port..translate("Redirect"), translate("AdGuardHome redirect mode")) +o.placeholder = "none" +o:value("none", translate("none")) +o:value("dnsmasq-upstream", translate("Run as dnsmasq upstream server")) +o:value("redirect", translate("Redirect 53 port to AdGuardHome")) +o:value("exchange", translate("Use port 53 replace dnsmasq")) +o.default = "none" +o.optional = true +---- bin path +o = s:option(Value, "binpath", translate("Bin Path"), translate("AdGuardHome Bin path if no bin will auto download")) +o.default = "/usr/bin/AdGuardHome" +o.datatype = "string" +o.optional = false +o.rmempty=false +o.validate=function(self, value) +if value=="" then return nil end +if fs.stat(value,"type")=="dir" then + fs.rmdir(value) +end +if fs.stat(value,"type")=="dir" then + if (m.message) then + m.message =m.message.."\nerror!bin path is a dir" + else + m.message ="error!bin path is a dir" + end + return nil +end +return value +end +--- upx +o = s:option(ListValue, "upxflag", translate("use upx to compress bin after download")) +o:value("", translate("none")) +o:value("-1", translate("compress faster")) +o:value("-9", translate("compress better")) +o:value("--best", translate("compress best(can be slow for big files)")) +o:value("--brute", translate("try all available compression methods & filters [slow]")) +o:value("--ultra-brute", translate("try even more compression variants [very slow]")) +o.default = "" +o.description=translate("bin use less space,but may have compatibility issues") +o.rmempty = true +---- config path +o = s:option(Value, "configpath", translate("Config Path"), translate("AdGuardHome config path")) +o.default = "/etc/AdGuardHome.yaml" +o.datatype = "string" +o.optional = false +o.rmempty=false +o.validate=function(self, value) +if value==nil then return nil end +if fs.stat(value,"type")=="dir" then + fs.rmdir(value) +end +if fs.stat(value,"type")=="dir" then + if m.message then + m.message =m.message.."\nerror!config path is a dir" + else + m.message ="error!config path is a dir" + end + return nil +end +return value +end +---- work dir +o = s:option(Value, "workdir", translate("Work dir"), translate("AdGuardHome work dir include rules,audit log and database")) +o.default = "/etc/AdGuardHome" +o.datatype = "string" +o.optional = false +o.rmempty=false +o.validate=function(self, value) +if value=="" then return nil end +if fs.stat(value,"type")=="reg" then + if m.message then + m.message =m.message.."\nerror!work dir is a file" + else + m.message ="error!work dir is a file" + end + return nil +end +if string.sub(value, -1)=="/" then + return string.sub(value, 1, -2) +else + return value +end +end +---- log file +o = s:option(Value, "logfile", translate("Runtime log file"), translate("AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log")) +o.datatype = "string" +o.rmempty = true +o.validate=function(self, value) +if fs.stat(value,"type")=="dir" then + fs.rmdir(value) +end +if fs.stat(value,"type")=="dir" then + if m.message then + m.message =m.message.."\nerror!log file is a dir" + else + m.message ="error!log file is a dir" + end + return nil +end +return value +end +---- debug +o = s:option(Flag, "verbose", translate("Verbose log")) +o.default = 0 +o.optional = true +---- gfwlist +local a=luci.sys.call("grep -m 1 -q programadd "..configpath) +if (a==0) then +a="Added" +else +a="Not added" +end +o=s:option(Button,"gfwdel",translate("Del gfwlist"),translate(a)) +o.optional = true +o.inputtitle=translate("Del") +o.write=function() + luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh del 2>&1") + luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) +end +o=s:option(Button,"gfwadd",translate("Add gfwlist"),translate(a)) +o.optional = true +o.inputtitle=translate("Add") +o.write=function() + luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh 2>&1") + luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) +end +o = s:option(Value, "gfwupstream", translate("Gfwlist upstream dns server"), translate("Gfwlist domain upstream dns service")..translate(a)) +o.default = "tcp://208.67.220.220:5353" +o.datatype = "string" +o.optional = true +---- chpass +o = s:option(Value, "hashpass", translate("Change browser management password"), translate("Press load culculate model and culculate finally save/apply")) +o.default = "" +o.datatype = "string" +o.template = "AdGuardHome/AdGuardHome_chpass" +o.optional = true +---- upgrade protect +o = s:option(MultiValue, "upprotect", translate("Keep files when system upgrade")) +o:value("$binpath",translate("core bin")) +o:value("$configpath",translate("config file")) +o:value("$logfile",translate("log file")) +o:value("$workdir/data/sessions.db",translate("sessions.db")) +o:value("$workdir/data/stats.db",translate("stats.db")) +o:value("$workdir/data/querylog.json",translate("querylog.json")) +o:value("$workdir/data/filters",translate("filters")) +o.widget = "checkbox" +o.default = nil +o.optional=true +---- wait net on boot +o = s:option(Flag, "waitonboot", translate("On boot when network ok restart")) +o.default = 1 +o.optional = true +---- backup workdir on shutdown +local workdir=uci:get("AdGuardHome","AdGuardHome","workdir") or "/etc/AdGuardHome" +o = s:option(MultiValue, "backupfile", translate("Backup workdir files when shutdown")) +o1 = s:option(Value, "backupwdpath", translate("Backup workdir path")) +local name +o:value("filters","filters") +o:value("stats.db","stats.db") +o:value("querylog.json","querylog.json") +o:value("sessions.db","sessions.db") +o1:depends ("backupfile", "filters") +o1:depends ("backupfile", "stats.db") +o1:depends ("backupfile", "querylog.json") +o1:depends ("backupfile", "sessions.db") +for name in fs.glob(workdir.."/data/*") +do + name=fs.basename (name) + if name~="filters" and name~="stats.db" and name~="querylog.json" and name~="sessions.db" then + o:value(name,name) + o1:depends ("backupfile", name) + end +end +o.widget = "checkbox" +o.default = nil +o.optional=false +o.description=translate("Will be restore when workdir/data is empty") +----backup workdir path + +o1.default = "/etc/AdGuardHome" +o1.datatype = "string" +o1.optional = false +o1.validate=function(self, value) +if fs.stat(value,"type")=="reg" then + if m.message then + m.message =m.message.."\nerror!backup dir is a file" + else + m.message ="error!backup dir is a file" + end + return nil +end +if string.sub(value,-1)=="/" then + return string.sub(value, 1, -2) +else + return value +end +end + +----Crontab +o = s:option(MultiValue, "crontab", translate("Crontab task"),translate("Please change time and args in crontab")) +o:value("autoupdate",translate("Auto update core")) +o:value("cutquerylog",translate("Auto tail querylog")) +o:value("cutruntimelog",translate("Auto tail runtime log")) +o:value("autohost",translate("Auto update ipv6 hosts and restart adh")) +o:value("autogfw",translate("Auto update gfwlist and restart adh")) +o.widget = "checkbox" +o.default = nil +o.optional=true + +----downloadpath +o = s:option(TextValue, "downloadlinks",translate("Download links for update")) +o.optional = false +o.rows = 4 +o.wrap = "soft" +o.cfgvalue = function(self, section) + return fs.readfile("/usr/share/AdGuardHome/links.txt") +end +o.write = function(self, section, value) + fs.writefile("/usr/share/AdGuardHome/links.txt", value:gsub("\r\n", "\n")) +end +fs.writefile("/var/run/lucilogpos","0") +function m.on_commit(map) + if (fs.access("/var/run/AdGserverdis")) then + io.popen("/etc/init.d/AdGuardHome reload &") + return + end + local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") + if ucitracktest=="1" then + return + elseif ucitracktest=="0" then + io.popen("/etc/init.d/AdGuardHome reload &") + else + if (fs.access("/var/run/AdGlucitest")) then + uci:set("AdGuardHome","AdGuardHome","ucitracktest","0") + io.popen("/etc/init.d/AdGuardHome reload &") + else + fs.writefile("/var/run/AdGlucitest","") + if (ucitracktest=="2") then + uci:set("AdGuardHome","AdGuardHome","ucitracktest","1") + else + uci:set("AdGuardHome","AdGuardHome","ucitracktest","2") + end + end + uci:save("AdGuardHome") + end +end +return m diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua new file mode 100755 index 000000000..5d18a88db --- /dev/null +++ b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua @@ -0,0 +1,16 @@ +local fs=require"nixio.fs" +local uci=require"luci.model.uci".cursor() +local f,t +f=SimpleForm("logview") +f.reset = false +f.submit = false +t=f:field(TextValue,"conf") +t.rmempty=true +t.rows=20 +t.template="AdGuardHome/log" +t.readonly="readonly" +local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") or "" +t.timereplace=(logfile~="syslog" and logfile~="" ) +t.pollcheck=logfile~="" +fs.writefile("/var/run/lucilogreload","") +return f diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua new file mode 100755 index 000000000..ecf072bbc --- /dev/null +++ b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua @@ -0,0 +1,97 @@ +local m, s, o +local fs = require "nixio.fs" +local uci=require"luci.model.uci".cursor() +local sys=require"luci.sys" +require("string") +require("io") +require("table") +function gen_template_config() + local b + local d="" + for cnt in io.lines("/tmp/resolv.conf.d/resolv.conf.auto") do + b=string.match (cnt,"^[^#]*nameserver%s+([^%s]+)$") + if (b~=nil) then + d=d.." - "..b.."\n" + end + end + local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") + local tbl = {} + local a="" + while (1) do + a=f:read("*l") + if (a=="#bootstrap_dns") then + a=d + elseif (a=="#upstream_dns") then + a=d + elseif (a==nil) then + break + end + table.insert(tbl, a) + end + f:close() + return table.concat(tbl, "\n") +end +m = Map("AdGuardHome") +local configpath = uci:get("AdGuardHome","AdGuardHome","configpath") +local binpath = uci:get("AdGuardHome","AdGuardHome","binpath") +s = m:section(TypedSection, "AdGuardHome") +s.anonymous=true +s.addremove=false +--- config +o = s:option(TextValue, "escconf") +o.rows = 66 +o.wrap = "off" +o.rmempty = true +o.cfgvalue = function(self, section) + return fs.readfile("/tmp/AdGuardHometmpconfig.yaml") or fs.readfile(configpath) or gen_template_config() or "" +end +o.validate=function(self, value) + fs.writefile("/tmp/AdGuardHometmpconfig.yaml", value:gsub("\r\n", "\n")) + if fs.access(binpath) then + if (sys.call(binpath.." -c /tmp/AdGuardHometmpconfig.yaml --check-config 2> /tmp/AdGuardHometest.log")==0) then + return value + end + else + return value + end + luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome","manual")) + return nil +end +o.write = function(self, section, value) + fs.move("/tmp/AdGuardHometmpconfig.yaml",configpath) +end +o.remove = function(self, section, value) + fs.writefile(configpath, "") +end +--- js and reload button +o = s:option(DummyValue, "") +o.anonymous=true +o.template = "AdGuardHome/yamleditor" +if not fs.access(binpath) then + o.description=translate("WARNING!!! no bin found apply config will not be test") +end +--- log +if (fs.access("/tmp/AdGuardHometmpconfig.yaml")) then +local c=fs.readfile("/tmp/AdGuardHometest.log") +if (c~="") then +o = s:option(TextValue, "") +o.readonly=true +o.rows = 5 +o.rmempty = true +o.name="" +o.cfgvalue = function(self, section) + return fs.readfile("/tmp/AdGuardHometest.log") +end +end +end +function m.on_commit(map) + local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") + if ucitracktest=="1" then + return + elseif ucitracktest=="0" then + io.popen("/etc/init.d/AdGuardHome reload &") + else + fs.writefile("/var/run/AdGlucitest","") + end +end +return m diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm new file mode 100755 index 000000000..832a1df46 --- /dev/null +++ b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm @@ -0,0 +1,78 @@ +<%+cbi/valueheader%> +<%local fs=require"nixio.fs"%> + + +<% if self.showfastconfig then %> + +<%end%> + + +<%+cbi/valuefooter%> diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm new file mode 100755 index 000000000..b6ff3ebb3 --- /dev/null +++ b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm @@ -0,0 +1,49 @@ +<%+cbi/valueheader%> + + 0, "data-choices", { self.keylist, self.vallist }) + %> /> + <% if self.password then %><% end %> + +<%+cbi/valuefooter%> diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm new file mode 100755 index 000000000..7e924d119 --- /dev/null +++ b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm @@ -0,0 +1,27 @@ + + +
+

+ <%:Collecting data...%> +

+
\ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm new file mode 100755 index 000000000..11a1f787a --- /dev/null +++ b/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm @@ -0,0 +1,111 @@ +<%+cbi/valueheader%> +<%:reverse%> +<%if self.timereplace then%> +<%:localtime%>
+<%end%> + + + + +<%+cbi/valuefooter%> diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm new file mode 100755 index 000000000..639cb9988 --- /dev/null +++ b/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm @@ -0,0 +1,39 @@ +<%+cbi/valueheader%> + + + + + + + + + +<%fs=require"nixio.fs"%> +<%if fs.access("/tmp/AdGuardHometmpconfig.yaml") then%> + +<%end%> + +<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh-cn b/luci-app-adguardhome/po/zh-cn new file mode 100755 index 000000000..8d69574dd --- /dev/null +++ b/luci-app-adguardhome/po/zh-cn @@ -0,0 +1 @@ +zh_Hans \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh_Hans/adguardhome.po b/luci-app-adguardhome/po/zh_Hans/adguardhome.po new file mode 100755 index 000000000..0ace89bae --- /dev/null +++ b/luci-app-adguardhome/po/zh_Hans/adguardhome.po @@ -0,0 +1,408 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: PACKAGE VERSION\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +#: /mnt/A/openwrt-latest/package/ctcgfw/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua:27 +msgid "" +"/dev/null 2>&1 + if [ $? -eq 0 ]; then + return + fi + uci delete dhcp.@dnsmasq[0].server 2>/dev/null + uci add_list dhcp.@dnsmasq[0].server=$addr + for server in $OLD_SERVER; do + if [ "$server" = "$addr" ]; then + continue + fi + # uci add_list dhcp.@dnsmasq[0].server=$server + done + uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null + uci set dhcp.@dnsmasq[0].noresolv=1 + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +stop_forward_dnsmasq() +{ + local OLD_PORT="$1" + addr="127.0.0.1#$OLD_PORT" + OLD_SERVER="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" + echo $OLD_SERVER | grep "^$addr" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + return + fi + + uci del_list dhcp.@dnsmasq[0].server=$addr 2>/dev/null + addrlist="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" + if [ -z "$addrlist" ] ; then + uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null + uci delete dhcp.@dnsmasq[0].noresolv 2>/dev/null + fi + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +set_iptable() +{ + local ipv6_server=$1 + local tcp_server=$2 + uci -q batch <<-EOF >/dev/null 2>&1 + delete firewall.AdGuardHome + set firewall.AdGuardHome=include + set firewall.AdGuardHome.type=script + set firewall.AdGuardHome.path=/usr/share/AdGuardHome/firewall.start + set firewall.AdGuardHome.reload=1 + commit firewall +EOF + + IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" + for IP in $IPS + do + if [ "$tcp_server" == "1" ]; then + iptables -t nat -A PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + fi + iptables -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + done + + if [ "$ipv6_server" == 0 ]; then + return + fi + + IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" + for IP in $IPS + do + if [ "$tcp_server" == "1" ]; then + ip6tables -t nat -A PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + fi + ip6tables -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + done +} + +clear_iptable() +{ + uci -q batch <<-EOF >/dev/null 2>&1 + delete firewall.AdGuardHome + commit firewall +EOF + local OLD_PORT="$1" + local ipv6_server=$2 + IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" + for IP in $IPS + do + iptables -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + iptables -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + done + + if [ "$ipv6_server" == 0 ]; then + return + fi + echo "warn ip6tables nat mod is needed" + IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" + for IP in $IPS + do + ip6tables -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + ip6tables -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + done +} + +service_triggers() { + procd_add_reload_trigger "$CONFIGURATION" + [ "$(uci get AdGuardHome.AdGuardHome.redirect)" == "redirect" ] && procd_add_reload_trigger firewall +} + +isrunning(){ + config_load "${CONFIGURATION}" + _isrunning + local r=$? + ([ "$r" == "0" ] && echo "running") || ([ "$r" == "1" ] && echo "not run" ) || echo "no bin" + return $r +} + +_isrunning(){ + config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + [ ! -f "$binpath" ] && return 2 + pgrep $binpath 2>&1 >/dev/null && return 0 + return 1 +} + +force_reload(){ + config_load "${CONFIGURATION}" + _isrunning && procd_send_signal "$CONFIGURATION" || start +} + +get_tz() +{ + SET_TZ="" + + if [ -e "/etc/localtime" ]; then + return + fi + + for tzfile in /etc/TZ /var/etc/TZ + do + if [ ! -e "$tzfile" ]; then + continue + fi + + tz="`cat $tzfile 2>/dev/null`" + done + + if [ -z "$tz" ]; then + return + fi + + SET_TZ=$tz +} + +rm_port53() +{ + local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") + dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) + if [ -z "$dnsmasq_port" ]; then + dnsmasq_port="53" + fi + if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then + if [ "$dnsmasq_port" == "53" ]; then + dnsmasq_port="1745" + fi + elif [ "$dnsmasq_port" == "53" ]; then + return + fi + config_editor "dns.port" "$dnsmasq_port" "$configpath" + uci set dhcp.@dnsmasq[0].port="53" + uci commit dhcp + config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + killall -9 $binpath + /etc/init.d/dnsmasq restart +} + +use_port53() +{ + local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") + dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) + if [ -z "$dnsmasq_port" ]; then + dnsmasq_port="53" + fi + if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then + if [ "$dnsmasq_port" == "53" ]; then + AdGuardHome_PORT="1745" + fi + elif [ "$AdGuardHome_PORT" == "53" ]; then + return + fi + config_editor "dns.port" "53" "$configpath" + uci set dhcp.@dnsmasq[0].port="$AdGuardHome_PORT" + uci commit dhcp + /etc/init.d/dnsmasq reload +} + +do_redirect() +{ + config_load "${CONFIGURATION}" + _do_redirect $1 +} + +_do_redirect() +{ + local section="$CONFIGURATION" + args="" + ipv6_server=1 + tcp_server=0 + enabled=$1 + if [ "$enabled" == "1" ]; then + echo -n "1">/var/run/AdGredir + else + echo -n "0">/var/run/AdGredir + fi + config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" + AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") + if [ ! -s "$configpath" ]; then + cp -f /usr/share/AdGuardHome/AdGuardHome_template.yaml $configpath + fi + if [ -z "$AdGuardHome_PORT" ]; then + AdGuardHome_PORT="0" + fi + config_get "redirect" "$section" "redirect" "none" + config_get "old_redirect" "$section" "old_redirect" "none" + config_get "old_port" "$section" "old_port" "0" + config_get "old_enabled" "$section" "old_enabled" "0" + uci get dhcp.@dnsmasq[0].port >/dev/null 2>&1 || uci set dhcp.@dnsmasq[0].port="53" >/dev/null 2>&1 + if [ "$old_enabled" = "1" -a "$old_redirect" == "exchange" ]; then + AdGuardHome_PORT=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) + fi + + if [ "$old_redirect" != "$redirect" ] || [ "$old_port" != "$AdGuardHome_PORT" ] || [ "$old_enabled" = "1" -a "$enabled" = "0" ]; then + if [ "$old_redirect" != "none" ]; then + if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then + clear_iptable "$old_port" "$ipv6_server" + elif [ "$old_redirect" == "dnsmasq-upstream" ]; then + stop_forward_dnsmasq "$old_port" + elif [ "$old_redirect" == "exchange" ]; then + rm_port53 + fi + fi + elif [ "$old_enabled" = "1" -a "$enabled" = "1" ]; then + if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then + clear_iptable "$old_port" "$ipv6_server" + fi + fi + uci delete AdGuardHome.@AdGuardHome[0].old_redirect 2>/dev/null + uci delete AdGuardHome.@AdGuardHome[0].old_port 2>/dev/null + uci delete AdGuardHome.@AdGuardHome[0].old_enabled 2>/dev/null + uci add_list AdGuardHome.@AdGuardHome[0].old_redirect="$redirect" 2>/dev/null + uci add_list AdGuardHome.@AdGuardHome[0].old_port="$AdGuardHome_PORT" 2>/dev/null + uci add_list AdGuardHome.@AdGuardHome[0].old_enabled="$enabled" 2>/dev/null + uci commit AdGuardHome + [ "$enabled" == "0" ] && return 1 + if [ "$AdGuardHome_PORT" == "0" ]; then + return 1 + fi + if [ "$redirect" = "redirect" ]; then + set_iptable $ipv6_server $tcp_server + elif [ "$redirect" = "dnsmasq-upstream" ]; then + set_forward_dnsmasq "$AdGuardHome_PORT" + elif [ "$redirect" == "exchange" -a "$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" == "53" ]; then + use_port53 + fi +} + +get_filesystem() +{ +# print out path filesystem + echo $1 | awk ' + BEGIN{ + while (("mount"| getline ret) > 0) + { + split(ret,d); + fs[d[3]]=d[5]; + m=index(d[1],":") + if (m==0) + { + pt[d[3]]=d[1] + }else{ + pt[d[3]]=substr(d[1],m+1) + }}}{ + split($0,d,"/"); + if ("/" in fs) + { + result1=fs["/"]; + } + if ("/" in pt) + { + result2=pt["/"]; + } + for (i=2;i<=length(d);i++) + { + p[i]=p[i-1]"/"d[i]; + if (p[i] in fs) + { + result1=fs[p[i]]; + result2=pt[p[i]]; + } + } + if (result2 in fs){ + result=fs[result2]} + else{ + result=result1} + print(result);}' +} + +config_editor() +{ + awk -v yaml="$1" -v value="$2" -v file="$3" -v ro="$4" ' + BEGIN{split(yaml,part,"\.");s="";i=1;l=length(part);} + { + if (match($0,s""part[i]":")) + { + if (i==l) + { + split($0,t,": "); + if (ro==""){ + system("sed -i '\''"FNR"c \\"t[1]": "value"'\'' "file); + }else{ + print(t[2]); + } + exit; + } + s=s"[- ]{2}"; + i++; + } + }' $3 +} + +boot_service() { + rm /var/run/AdGserverdis >/dev/null 2>&1 + config_load "${CONFIGURATION}" + config_get waitonboot $CONFIGURATION waitonboot "0" + config_get_bool enabled $CONFIGURATION enabled 0 + config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + [ -f "$binpath" ] && start_service + if [ "$enabled" == "1" ] && [ "$waitonboot" == "1" ]; then + procd_open_instance "waitnet" + procd_set_param command "/usr/share/AdGuardHome/waitnet.sh" + procd_close_instance + echo "no net start pinging" + fi +} + +testbackup(){ + config_load "${CONFIGURATION}" + if [ "$1" == "backup" ]; then + backup + elif [ "$1" == "restore" ]; then + restore + fi +} + +restore() +{ + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + config_get backupwdpath $CONFIGURATION backupwdpath "/etc/AdGuardHome" + cp -u -r -f $backupwdpath/data $workdir +} + +backup() { + config_get backupwdpath $CONFIGURATION backupwdpath "/etc/AdGuardHome" + mkdir -p $backupwdpath/data + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + config_get backupfile $CONFIGURATION backupfile "" + for one in $backupfile; + do + while : + do + if [ -d "$backupwdpath/data/$one" ]; then + cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data 2>&1) + else + cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data/$one 2>&1) + fi + echo "$cpret" + echo "$cpret" | grep "no space left on device" + if [ "$?" == "0" ]; then + echo "磁盘已满,删除log重试中" + del_querylog && continue + rm -f -r $backupwdpath/data/filters + rm -f -r $workdir/data/filters && continue + echo "backup failed" + fi + break + done + done +} + +start_service() { + # Reading config + rm /var/run/AdGserverdis >/dev/null 2>&1 + config_load "${CONFIGURATION}" + # update password + config_get hashpass $CONFIGURATION hashpass "" + config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" + if [ -n "$hashpass" ]; then + config_editor "users.password" "$hashpass" "$configpath" + uci set $CONFIGURATION.$CONFIGURATION.hashpass="" + fi + local enabled + config_get_bool enabled $CONFIGURATION enabled 0 + # update crontab + do_crontab + if [ "$enabled" == "0" ]; then + _do_redirect 0 + return + fi + #what need to do before reload + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + + config_get backupfile $CONFIGURATION backupfile "" + mkdir -p $workdir/data + if [ -n "$backupfile" ] && [ ! -d "$workdir/data" ]; then + restore + fi + # for overlay data-stk-oo not suppport + local cwdfs=$(get_filesystem $workdir) + echo "workdir is a $cwdfs filesystem" + if [ "$cwdfs" == "jffs2" ]; then + echo "fs error ln db to tmp $workdir $cwdfs" + logger "AdGuardHome" "warning db redirect to tmp" + touch $workdir/data/stats.db + if [ ! -L $workdir/data/stats.db ]; then + mv -f $workdir/data/stats.db /tmp/stats.db 2>/dev/null + ln -s /tmp/stats.db $workdir/data/stats.db 2>/dev/null + fi + touch $workdir/data/sessions.db + if [ ! -L $workdir/data/sessions.db ]; then + mv -f $workdir/data/sessions.db /tmp/sessions.db 2>/dev/null + ln -s /tmp/sessions.db $workdir/data/sessions.db 2>/dev/null + fi + fi + local ADDITIONAL_ARGS="" + config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + + mkdir -p ${binpath%/*} + ADDITIONAL_ARGS="$ADDITIONAL_ARGS -c $configpath" + ADDITIONAL_ARGS="$ADDITIONAL_ARGS -w $workdir" + config_get httpport $CONFIGURATION httpport 3000 + ADDITIONAL_ARGS="$ADDITIONAL_ARGS -p $httpport" + + # hack to save config file when upgrade system + config_get upprotect $CONFIGURATION upprotect "" + eval upprotect=${upprotect// /\\\\n} + echo -e "$upprotect">/lib/upgrade/keep.d/luci-app-adguardhome + + config_get logfile $CONFIGURATION logfile "" + if [ -n "$logfile" ]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS -l $logfile" + fi + + if [ ! -f "$binpath" ]; then + _do_redirect 0 + /usr/share/AdGuardHome/update_core.sh 2>&1 >/tmp/AdGuardHome_update.log & + exit 0 + fi + + config_get_bool verbose $CONFIGURATION verbose 0 + if [ "$verbose" -eq 1 ]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS -v" + fi + + procd_open_instance + get_tz + if [ -n "$SET_TZ" ]; then + procd_set_param env TZ="$SET_TZ" + fi + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + procd_set_param limits core="unlimited" nofile="65535 65535" + procd_set_param stderr 1 + procd_set_param command $binpath $ADDITIONAL_ARGS + procd_set_param file "$configpath" "/etc/hosts" "/etc/config/AdGuardHome" + procd_close_instance + if [ -f "$configpath" ]; then + _do_redirect 1 + else + _do_redirect 0 + config_get "redirect" "AdGuardHome" "redirect" "none" + if [ "$redirect" != "none" ]; then + procd_open_instance "waitconfig" + procd_set_param command "/usr/share/AdGuardHome/watchconfig.sh" + procd_close_instance + echo "no config start watching" + fi + fi + echo "AdGuardHome service enabled" + echo "luci enable switch=$enabled" + (sleep 10 && [ -z "$(pgrep $binpath)" ] && logger "AdGuardHome" "no process in 10s cancel redirect" && _do_redirect 0 )& + if [[ "`uci get bypass.@global[0].global_server 2>/dev/null`" && "`uci get bypass.@global[0].adguardhome 2>/dev/null`" == 1 && "$(uci get dhcp.@dnsmasq[0].port)" == "53" ]]; then + uci -q set AdGuardHome.AdGuardHome.redirect='exchange' + uci commit AdGuardHome + do_redirect 1 + fi +} + +reload_service() +{ + rm /var/run/AdGlucitest >/dev/null 2>&1 + echo "AdGuardHome reloading" + start +} + +del_querylog(){ + local btarget=$(ls $backupwdpath/data | grep -F "querylog.json" | sort -r | head -n 1) + local wtarget=$(ls $workdir/data | grep -F "querylog.json" | sort -r | head -n 1) + if [ "$btarget"x == "$wtarget"x ]; then + [ -z "$btarget" ] && return 1 + rm -f $workdir/data/$wtarget + rm -f $backupwdpath/data/$btarget + return 0 + fi + if [ "$btarget" \> "$wtarget" ]; then + rm -f $backupwdpath/data/$btarget + return 0 + else + rm -f $workdir/data/$wtarget + return 0 + fi +} + +stop_service() +{ + config_load "${CONFIGURATION}" + _do_redirect 0 + do_crontab + if [ "$1" != "nobackup" ]; then + config_get backupfile $CONFIGURATION backupfile "0" + if [ -n "$backupfile" ]; then + backup + fi + fi + echo "AdGuardHome service disabled" + touch /var/run/AdGserverdis +} + +boot() { + rc_procd boot_service "$@" + if eval "type service_started" 2>/dev/null >/dev/null; then + service_started + fi +} + +test_crontab(){ + config_load "${CONFIGURATION}" + do_crontab +} + +do_crontab(){ + config_get_bool enabled $CONFIGURATION enabled 0 + config_get crontab $CONFIGURATION crontab "" + local findstr default cronenable replace commit + local cronreload=0 + local commit=0 + findstr="/usr/share/AdGuardHome/update_core.sh" + default="30 3 * * * /usr/share/AdGuardHome/update_core.sh 2>&1" + [ "$enabled" == "0" ] || [ "${crontab//autoupdate/}" == "$crontab" ] && cronenable=0 || cronenable=1 + crontab_editor + + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + config_get lastworkdir $CONFIGURATION lastworkdir "/etc/AdGuardHome" + findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" + #[ -n "$lastworkdir" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastworkdir/data/querylog.json" && [ "$lastworkdir" != "$workdir" ] && replace="${lastworkdir//\//\\/}/${workdir//\//\\/}" + default="0 * * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" + [ "$enabled" == "0" ] || [ "${crontab//cutquerylog/}" == "$crontab" ] && cronenable=0 || cronenable=1 + crontab_editor + #[ "$lastworkdir" != "$workdir" ] && uci set AdGuardHome.AdGuardHome.lastworkdir="$workdir" && commit=1 + + config_get logfile $CONFIGURATION logfile "" + config_get lastlogfile $CONFIGURATION lastlogfile "" + findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.logfile)" + default="30 3 * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.logfile)" + #[ -n "$lastlogfile" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastlogfile" && [ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && replace="${lastlogfile//\//\\/}/${logfile//\//\\/}" + [ "$logfile" == "syslog" ] || [ "$logfile" == "" ] || [ "$enabled" == "0" ] || [ "${crontab//cutruntimelog/}" == "$crontab" ] && cronenable=0 || cronenable=1 + crontab_editor + #[ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && uci set AdGuardHome.AdGuardHome.lastlogfile="$logfile" && commit=1 + + findstr="/usr/share/AdGuardHome/addhost.sh" + default="0 * * * * /usr/share/AdGuardHome/addhost.sh" + [ "$enabled" == "0" ] || [ "${crontab//autohost/}" == "$crontab" ] && cronenable=0 || cronenable=1 + crontab_editor + [ "$cronenable" == "0" ] && /usr/share/AdGuardHome/addhost.sh "del" "noreload" || /usr/share/AdGuardHome/addhost.sh "" "noreload" + + findstr="/usr/share/AdGuardHome/gfw2adg.sh" + default="30 3 * * * /usr/share/AdGuardHome/gfw2adg.sh" + [ "$enabled" == "0" ] || [ "${crontab//autogfw/}" == "$crontab" ] && cronenable=0 || cronenable=1 + crontab_editor + [ "$cronreload" -gt 0 ] && /etc/init.d/cron restart + #[ "$commit" -gt 0 ] && uci commit AdGuardHome +} + +crontab_editor(){ + #usage input: + #findstr= + #default= + #cronenable= + #replace="${last//\//\\/}/${now//\//\\/}" + #output:cronreload:if >1 please /etc/init.d/cron restart manual + local testline reload + local line="$(grep "$findstr" $CRON_FILE)" + [ -n "$replace" ] && [ -n "$line" ] && eval testline="\${line//$replace}" && [ "$testline" != "$line" ] && line="$testline" && reload="1" && replace="" + if [ "${line:0:1}" != "#" ]; then + if [ $cronenable -eq 1 ]; then + [ -z "$line" ] && line="$default" && reload="1" + if [ -n "$reload" ]; then + sed -i "\,$findstr,d" $CRON_FILE + echo "$line" >> $CRON_FILE + cronreload=$((cronreload+1)) + fi + elif [ -n "$line" ]; then + sed -i "\,$findstr,d" $CRON_FILE + echo "#$line" >> $CRON_FILE + cronreload=$((cronreload+1)) + fi + else + if [ $cronenable -eq 1 ]; then + sed -i "\,$findstr,d" $CRON_FILE + echo "${line:1}" >> $CRON_FILE + cronreload=$((cronreload+1)) + elif [ -z "$reload" ]; then + sed -i "\,$findstr,d" $CRON_FILE + echo "$line" >> $CRON_FILE + fi + fi +} diff --git a/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome b/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome new file mode 100755 index 000000000..37e192cdd --- /dev/null +++ b/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome @@ -0,0 +1,15 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null 2>&1 + delete ucitrack.@AdGuardHome[-1] + add ucitrack AdGuardHome + set ucitrack.@AdGuardHome[-1].init=AdGuardHome + commit ucitrack + delete AdGuardHome.AdGuardHome.ucitracktest + /etc/init.d/AdGuardHome restart +EOF + +rm -f /tmp/luci-indexcache + +chmod +x /etc/init.d/AdGuardHome /usr/share/AdGuardHome/* +exit 0 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml b/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml new file mode 100755 index 000000000..612a57706 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml @@ -0,0 +1,131 @@ +bind_host: 0.0.0.0 +bind_port: 3000 +beta_bind_port: 0 +users: +- name: root + password: $2y$10$dwn0hTYoECQMZETBErGlzOId2VANOVsPHsuH13TM/8KnysM5Dh/ve +auth_attempts: 5 +block_auth_min: 15 +http_proxy: "" +language: zh-cn +debug_pprof: false +web_session_ttl: 720 +dns: + bind_hosts: + - 0.0.0.0 + port: 1745 + statistics_interval: 30 + querylog_enabled: true + querylog_file_enabled: true + querylog_interval: 6h + querylog_size_memory: 1000 + anonymize_client_ip: false + protection_enabled: true + blocking_mode: default + blocking_ipv4: "" + blocking_ipv6: "" + blocked_response_ttl: 60 + parental_block_host: family-block.dns.adguard.com + safebrowsing_block_host: standard-block.dns.adguard.com + ratelimit: 0 + ratelimit_whitelist: [] + refuse_any: false + upstream_dns: + - 223.5.5.5 + upstream_dns_file: "" + bootstrap_dns: + - 119.29.29.29 + - 223.5.5.5 + all_servers: false + fastest_addr: false + fastest_timeout: 1s + allowed_clients: [] + disallowed_clients: [] + blocked_hosts: + - version.bind + - id.server + - hostname.bind + trusted_proxies: + - 127.0.0.0/8 + - ::1/128 + cache_size: 4194304 + cache_ttl_min: 0 + cache_ttl_max: 0 + cache_optimistic: true + bogus_nxdomain: [] + aaaa_disabled: false + enable_dnssec: false + edns_client_subnet: false + max_goroutines: 300 + ipset: [] + filtering_enabled: true + filters_update_interval: 24 + parental_enabled: false + safesearch_enabled: false + safebrowsing_enabled: false + safebrowsing_cache_size: 1048576 + safesearch_cache_size: 1048576 + parental_cache_size: 1048576 + cache_time: 30 + rewrites: [] + blocked_services: [] + upstream_timeout: 10s + local_domain_name: lan + resolve_clients: true + use_private_ptr_resolvers: true + local_ptr_upstreams: [] +tls: + enabled: false + server_name: "" + force_https: false + port_https: 443 + port_dns_over_tls: 853 + port_dns_over_quic: 784 + port_dnscrypt: 0 + dnscrypt_config_file: "" + allow_unencrypted_doh: false + strict_sni_check: false + certificate_chain: "" + private_key: "" + certificate_path: "" + private_key_path: "" +filters: +- enabled: true + url: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt + name: AdGuard DNS filter + id: 1628750870 +- enabled: true + url: https://anti-ad.net/easylist.txt + name: 'CHN: anti-AD' + id: 1628750871 +whitelist_filters: [] +user_rules: [] +dhcp: + enabled: false + interface_name: "" + dhcpv4: + gateway_ip: "" + subnet_mask: "" + range_start: "" + range_end: "" + lease_duration: 86400 + icmp_timeout_msec: 1000 + options: [] + dhcpv6: + range_start: "" + lease_duration: 86400 + ra_slaac_only: false + ra_allow_slaac: false +clients: [] +log_compress: false +log_localtime: false +log_max_backups: 0 +log_max_size: 100 +log_max_age: 3 +log_file: "" +verbose: false +os: + group: "" + user: "" + rlimit_nofile: 0 +schema_version: 12 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh new file mode 100755 index 000000000..6c6b7b769 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +checkmd5(){ +local nowmd5=$(md5sum /etc/hosts) +nowmd5=${nowmd5%% *} +local lastmd5=$(uci get AdGuardHome.AdGuardHome.hostsmd5 2>/dev/null) +if [ "$nowmd5" != "$lastmd5" ]; then + uci set AdGuardHome.AdGuardHome.hostsmd5="$nowmd5" + uci commit AdGuardHome + [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload +fi +} + +[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' /etc/hosts && checkmd5 "$2" && exit 0 +/usr/bin/awk 'BEGIN{ +while ((getline < "/tmp/dhcp.leases") > 0) +{ + a[$2]=$4; +} +while (("ip -6 neighbor show | grep -v fe80" | getline) > 0) +{ + if (a[$5]) {print $1" "a[$5] >"/tmp/tmphost"; } +} +print "#programaddend" >"/tmp/tmphost"; +}' +grep programaddstart /etc/hosts >/dev/null 2>&1 +if [ "$?" == "0" ]; then + sed -i '/programaddstart/,/programaddend/c\#programaddstart' /etc/hosts + sed -i '/programaddstart/'r/tmp/tmphost /etc/hosts +else + echo "#programaddstart" >>/etc/hosts + cat /tmp/tmphost >> /etc/hosts +fi +rm /tmp/tmphost +checkmd5 "$2" diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start b/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start new file mode 100755 index 000000000..562117e52 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start @@ -0,0 +1,8 @@ +#!/bin/sh + +AdGuardHome_enable=$(uci get AdGuardHome.AdGuardHome.enabled) +redirect=$(uci get AdGuardHome.AdGuardHome.redirect) + +if [ $AdGuardHome_enable -eq 1 -a "$redirect" == "redirect" ]; then + /etc/init.d/AdGuardHome do_redirect 1 +fi diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh new file mode 100755 index 000000000..908bdf631 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +PATH="/usr/sbin:/usr/bin:/sbin:/bin" +logread -e AdGuardHome > /tmp/AdGuardHometmp.log +logread -e AdGuardHome -f >> /tmp/AdGuardHometmp.log & +pid=$! +echo "1">/var/run/AdGuardHomesyslog +while true +do + sleep 12 + watchdog=$(cat /var/run/AdGuardHomesyslog) + if [ "$watchdog"x == "0"x ]; then + kill $pid + rm /tmp/AdGuardHometmp.log + rm /var/run/AdGuardHomesyslog + exit 0 + else + echo "0">/var/run/AdGuardHomesyslog + fi +done diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh new file mode 100755 index 000000000..a3add84e8 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +PATH="/usr/sbin:/usr/bin:/sbin:/bin" + +checkmd5(){ +local nowmd5=$(md5sum /tmp/adguard.list 2>/dev/null) +nowmd5=${nowmd5%% *} +local lastmd5=$(uci get AdGuardHome.AdGuardHome.gfwlistmd5 2>/dev/null) +if [ "$nowmd5" != "$lastmd5" ]; then + uci set AdGuardHome.AdGuardHome.gfwlistmd5="$nowmd5" + uci commit AdGuardHome + [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload +fi +} + +configpath=$(uci get AdGuardHome.AdGuardHome.configpath 2>/dev/null) +[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' $configpath && checkmd5 "$2" && exit 0 +gfwupstream=$(uci get AdGuardHome.AdGuardHome.gfwupstream 2>/dev/null) +if [ -z $gfwupstream ]; then +gfwupstream="tcp://208.67.220.220:5353" +fi +if [ ! -f "$configpath" ]; then + echo "please make a config first" + exit 1 +fi +wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O- | base64 -d > /tmp/gfwlist.txt +cat /tmp/gfwlist.txt | awk -v upst="$gfwupstream" 'BEGIN{getline;}{ +s1=substr($0,1,1); +if (s1=="!") +{next;} +if (s1=="@"){ + $0=substr($0,3); + s1=substr($0,1,1); + white=1;} +else{ + white=0; +} + +if (s1=="|") + {s2=substr($0,2,1); + if (s2=="|") + { + $0=substr($0,3); + split($0,d,"/"); + $0=d[1]; + }else{ + split($0,d,"/"); + $0=d[3]; + }} +else{ + split($0,d,"/"); + $0=d[1]; +} +star=index($0,"*"); +if (star!=0) +{ + $0=substr($0,star+1); + dot=index($0,"."); + if (dot!=0) + $0=substr($0,dot+1); + else + next; + s1=substr($0,1,1); +} +if (s1==".") +{fin=substr($0,2);} +else{fin=$0;} +if (index(fin,".")==0) next; +if (index(fin,"%")!=0) next; +if (index(fin,":")!=0) next; +match(fin,"^[0-9\.]+") +if (RSTART==1 && RLENGTH==length(fin)) {print "ipset add gfwlist "fin>"/tmp/doipset.sh";next;} +if (fin=="" || finl==fin) next; +finl=fin; +if (white==0) + {print(" - '\''[/"fin"/]"upst"'\''");} +else{ + print(" - '\''[/"fin"/]#'\''");} +}END{print(" - '\''[/programaddend/]#'\''")}' > /tmp/adguard.list +grep programaddstart $configpath +if [ "$?" == "0" ]; then + sed -i '/programaddstart/,/programaddend/c\ - '\''\[\/programaddstart\/\]#'\''' $configpath + sed -i '/programaddstart/'r/tmp/adguard.list $configpath +else + sed -i '1i\ - '\''[/programaddstart/]#'\''' /tmp/adguard.list + sed -i '/upstream_dns:/'r/tmp/adguard.list $configpath +fi +checkmd5 "$2" +rm -f /tmp/gfwlist.txt /tmp/adguard.list diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt b/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt new file mode 100755 index 000000000..e4f1c8fa7 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt @@ -0,0 +1,3 @@ +https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_${Arch}.tar.gz +https://github.com/AdguardTeam/AdGuardHome/releases/download/${latest_ver}/AdGuardHome_linux_${Arch}.tar.gz +https://static.adguard.com/adguardhome/release/AdGuardHome_linux_${Arch}.tar.gz diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh new file mode 100755 index 000000000..9ccc21903 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +tail -n $1 "$2" > /var/run/tailtmp +cat /var/run/tailtmp > "$2" +rm /var/run/tailtmp diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh new file mode 100755 index 000000000..74ba7268d --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh @@ -0,0 +1,236 @@ +#!/bin/bash + +PATH="/usr/sbin:/usr/bin:/sbin:/bin" +binpath=$(uci get AdGuardHome.AdGuardHome.binpath) +if [ -z "$binpath" ]; then +uci set AdGuardHome.AdGuardHome.binpath="/tmp/AdGuardHome/AdGuardHome" +binpath="/tmp/AdGuardHome/AdGuardHome" +fi +mkdir -p ${binpath%/*} +upxflag=$(uci get AdGuardHome.AdGuardHome.upxflag 2>/dev/null) + +check_if_already_running(){ + running_tasks="$(ps |grep "AdGuardHome" |grep "update_core" |grep -v "grep" |awk '{print $1}' |wc -l)" + [ "${running_tasks}" -gt "2" ] && echo -e "\nA task is already running." && EXIT 2 +} + +check_wgetcurl(){ + which curl && downloader="curl -L -k --retry 2 --connect-timeout 20 -o" && return + which wget-ssl && downloader="wget-ssl --no-check-certificate -t 2 -T 20 -O" && return + [ -z "$1" ] && opkg update || (echo error opkg && EXIT 1) + [ -z "$1" ] && (opkg remove wget wget-nossl --force-depends ; opkg install wget ; check_wgetcurl 1 ;return) + [ "$1" == "1" ] && (opkg install curl ; check_wgetcurl 2 ; return) + echo error curl and wget && EXIT 1 +} + +check_latest_version(){ + check_wgetcurl + latest_ver="$($downloader - https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest 2>/dev/null|grep -E 'tag_name' |grep -E 'v[0-9.]+' -o 2>/dev/null)" + if [ -z "${latest_ver}" ]; then + echo -e "\nFailed to check latest version, please try again later." && EXIT 1 + fi + now_ver="$($binpath -c /dev/null --check-config 2>&1| grep -m 1 -E 'v[0-9.]+' -o)" + if [ "${latest_ver}"x != "${now_ver}"x ] || [ "$1" == "force" ]; then + echo -e "Local version: ${now_ver}., cloud version: ${latest_ver}." + doupdate_core + else + echo -e "\nLocal version: ${now_ver}, cloud version: ${latest_ver}." + echo -e "You're already using the latest version." + if [ ! -z "$upxflag" ]; then + filesize=$(ls -l $binpath | awk '{ print $5 }') + if [ $filesize -gt 8000000 ]; then + echo -e "start upx may take a long time" + doupx + mkdir -p "/tmp/AdGuardHomeupdate/AdGuardHome" >/dev/null 2>&1 + rm -fr /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} + /tmp/upx-${upx_latest_ver}-${Arch}_linux/upx $upxflag $binpath -o /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} + rm -rf /tmp/upx-${upx_latest_ver}-${Arch}_linux + /etc/init.d/AdGuardHome stop nobackup + rm $binpath + mv -f /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} $binpath + /etc/init.d/AdGuardHome start + echo -e "finished" + fi + fi + EXIT 0 + fi +} + +doupx(){ + Archt="$(opkg info kernel | grep Architecture | awk -F "[ _]" '{print($2)}')" + case $Archt in + "i386") + Arch="i386" + ;; + "i686") + Arch="i386" + echo -e "i686 use $Arch may have bug" + ;; + "x86") + Arch="amd64" + ;; + "mipsel") + Arch="mipsel" + ;; + "mips64el") + Arch="mips64el" + Arch="mipsel" + echo -e "mips64el use $Arch may have bug" + ;; + "mips") + Arch="mips" + ;; + "mips64") + Arch="mips64" + Arch="mips" + echo -e "mips64 use $Arch may have bug" + ;; + "arm") + Arch="arm" + ;; + "armeb") + Arch="armeb" + ;; + "aarch64") + Arch="arm64" + ;; + "powerpc") + Arch="powerpc" + ;; + "powerpc64") + Arch="powerpc64" + ;; + *) + echo -e "error not support $Archt if you can use offical release please issue a bug" + EXIT 1 + ;; + esac + upx_latest_ver="$($downloader - https://api.github.com/repos/upx/upx/releases/latest 2>/dev/null|grep -E 'tag_name' |grep -E '[0-9.]+' -o 2>/dev/null)" + $downloader /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz "https://github.com/upx/upx/releases/download/v${upx_latest_ver}/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" 2>&1 + #tar xvJf + which xz || (opkg list | grep ^xz || opkg update && opkg install xz) || (echo "xz download fail" && EXIT 1) + mkdir -p /tmp/upx-${upx_latest_ver}-${Arch}_linux + xz -d -c /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz| tar -x -C "/tmp" >/dev/null 2>&1 + if [ ! -e "/tmp/upx-${upx_latest_ver}-${Arch}_linux/upx" ]; then + echo -e "Failed to download upx." + EXIT 1 + fi + rm /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz +} + +doupdate_core(){ + echo -e "Updating core..." + mkdir -p "/tmp/AdGuardHomeupdate" + rm -rf /tmp/AdGuardHomeupdate/* >/dev/null 2>&1 + Archt="$(opkg info kernel | grep Architecture | awk -F "[ _]" '{print($2)}')" + case $Archt in + "i386") + Arch="386" + ;; + "i686") + Arch="386" + ;; + "x86") + Arch="amd64" + ;; + "mipsel") + Arch="mipsle" + ;; + "mips64el") + Arch="mips64le" + Arch="mipsle" + echo -e "mips64el use $Arch may have bug" + ;; + "mips") + Arch="mips" + ;; + "mips64") + Arch="mips64" + Arch="mips" + echo -e "mips64 use $Arch may have bug" + ;; + "arm") + Arch="arm" + ;; + "aarch64") + Arch="arm64" + ;; + "powerpc") + Arch="ppc" + echo -e "error not support $Archt" + EXIT 1 + ;; + "powerpc64") + Arch="ppc64" + echo -e "error not support $Archt" + EXIT 1 + ;; + *) + echo -e "error not support $Archt if you can use offical release please issue a bug" + EXIT 1 + ;; + esac + echo -e "start download" + grep -v "^#" /usr/share/AdGuardHome/links.txt >/tmp/run/AdHlinks.txt + while read link + do + eval link="$link" + $downloader /tmp/AdGuardHomeupdate/${link##*/} "$link" 2>&1 + if [ "$?" != "0" ]; then + echo "download failed try another download" + rm -f /tmp/AdGuardHomeupdate/${link##*/} + else + local success="1" + break + fi + done < "/tmp/run/AdHlinks.txt" + rm /tmp/run/AdHlinks.txt + [ -z "$success" ] && echo "no download success" && EXIT 1 + if [ "${link##*.}" == "gz" ]; then + tar -zxf "/tmp/AdGuardHomeupdate/${link##*/}" -C "/tmp/AdGuardHomeupdate/" + if [ ! -e "/tmp/AdGuardHomeupdate/AdGuardHome" ]; then + echo -e "Failed to download core." + rm -rf "/tmp/AdGuardHomeupdate" >/dev/null 2>&1 + EXIT 1 + fi + downloadbin="/tmp/AdGuardHomeupdate/AdGuardHome/AdGuardHome" + else + downloadbin="/tmp/AdGuardHomeupdate/${link##*/}" + fi + chmod 755 $downloadbin + echo -e "download success start copy" + if [ -n "$upxflag" ]; then + echo -e "start upx may take a long time" + doupx + /tmp/upx-${upx_latest_ver}-${Arch}_linux/upx $upxflag $downloadbin + rm -rf /tmp/upx-${upx_latest_ver}-${Arch}_linux + fi + echo -e "start copy" + /etc/init.d/AdGuardHome stop nobackup + rm "$binpath" + mv -f "$downloadbin" "$binpath" + if [ "$?" == "1" ]; then + echo "mv failed maybe not enough space please use upx or change bin to /tmp/AdGuardHome" + EXIT 1 + fi + /etc/init.d/AdGuardHome start + rm -rf "/tmp/AdGuardHomeupdate" >/dev/null 2>&1 + echo -e "Succeeded in updating core." + echo -e "Local version: ${latest_ver}, cloud version: ${latest_ver}.\n" + EXIT 0 +} + +EXIT(){ + rm /var/run/update_core 2>/dev/null + [ "$1" != "0" ] && touch /var/run/update_core_error + exit $1 +} + +main(){ + check_if_already_running + check_latest_version $1 +} + trap "EXIT 1" SIGTERM SIGINT + touch /var/run/update_core + rm /var/run/update_core_error 2>/dev/null + main $1 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh new file mode 100755 index 000000000..c7745e101 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +PATH="/usr/sbin:/usr/bin:/sbin:/bin" +count=0 +while : +do + ping -c 1 -W 1 -q www.baidu.com 1>/dev/null 2>&1 + if [ "$?" == "0" ]; then + /etc/init.d/AdGuardHome force_reload + break + fi + ping -c 1 -W 1 -q 202.108.22.5 1>/dev/null 2>&1 + if [ "$?" == "0" ]; then + /etc/init.d/AdGuardHome force_reload + break + fi + sleep 5 + ping -c 1 -W 1 -q www.google.com 1>/dev/null 2>&1 + if [ "$?" == "0" ]; then + /etc/init.d/AdGuardHome force_reload + break + fi + ping -c 1 -W 1 -q 8.8.8.8 1>/dev/null 2>&1 + if [ "$?" == "0" ]; then + /etc/init.d/AdGuardHome force_reload + break + fi + sleep 5 + count=$((count+1)) + if [ $count -gt 18 ]; then + /etc/init.d/AdGuardHome force_reload + break + fi +done +return 0 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh new file mode 100755 index 000000000..61ba09de7 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +PATH="/usr/sbin:/usr/bin:/sbin:/bin" +configpath=$(uci get AdGuardHome.AdGuardHome.configpath) +while : +do + sleep 10 + if [ -f "$configpath" ]; then + /etc/init.d/AdGuardHome do_redirect 1 + break + fi +done +return 0 diff --git a/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json b/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json new file mode 100755 index 000000000..485aa6205 --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json @@ -0,0 +1,11 @@ +{ + "luci-app-adguardhome": { + "description": "Grant UCI access for luci-app-adguardhome", + "read": { + "uci": [ "AdGuardHome" ] + }, + "write": { + "uci": [ "AdGuardHome" ] + } + } +} diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js new file mode 100755 index 000000000..f93d42b7f --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js @@ -0,0 +1 @@ +!function(n){"object"==typeof exports&&"object"==typeof module?n(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function e(e,o,i,t){if(i&&i.call){var l=i;i=null}else l=r(e,i,"rangeFinder");"number"==typeof o&&(o=n.Pos(o,0));var f=r(e,i,"minFoldSize");function d(n){var r=l(e,o);if(!r||r.to.line-r.from.linee.firstLine();)o=n.Pos(o.line-1,0),u=d(!1);if(u&&!u.cleared&&"unfold"!==t){var a=function(n,e){var o=r(n,e,"widget");if("string"==typeof o){var i=document.createTextNode(o);(o=document.createElement("span")).appendChild(i),o.className="CodeMirror-foldmarker"}else o&&(o=o.cloneNode(!0));return o}(e,i);n.on(a,"mousedown",function(e){c.clear(),n.e_preventDefault(e)});var c=e.markText(u.from,u.to,{replacedWith:a,clearOnEnter:r(e,i,"clearOnEnter"),__isFold:!0});c.on("clear",function(o,r){n.signal(e,"unfold",e,o,r)}),n.signal(e,"fold",e,u.from,u.to)}}n.newFoldFunction=function(n,o){return function(r,i){e(r,i,{rangeFinder:n,widget:o})}},n.defineExtension("foldCode",function(n,o,r){e(this,n,o,r)}),n.defineExtension("isFolded",function(n){for(var e=this.findMarksAt(n),o=0;o=u){if(s&&f&&s.test(f.className))return;i=r(a.indicatorOpen)}}(i||f)&&t.setGutterMarker(n,a.gutter,i)})}function i(t){return new RegExp("(^|\\s)"+t+"(?:$|\\s)\\s*")}function f(t){var o=t.getViewport(),e=t.state.foldGutter;e&&(t.operation(function(){n(t,o.from,o.to)}),e.from=o.from,e.to=o.to)}function a(t,r,n){var i=t.state.foldGutter;if(i){var f=i.options;if(n==f.gutter){var a=e(t,r);a?a.clear():t.foldCode(o(r,0),f)}}}function d(t){var o=t.state.foldGutter;if(o){var e=o.options;o.from=o.to=0,clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){f(t)},e.foldOnChangeTimeSpan||600)}}function u(t){var o=t.state.foldGutter;if(o){var e=o.options;clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){var e=t.getViewport();o.from==o.to||e.from-o.to>20||o.from-e.to>20?f(t):t.operation(function(){e.fromo.to&&(n(t,o.to,e.to),o.to=e.to)})},e.updateViewportTimeSpan||400)}}function l(t,o){var e=t.state.foldGutter;if(e){var r=o.line;r>=e.from&&ro))break;r=l}}return r?{from:e.Pos(i.line,t.getLine(i.line).length),to:e.Pos(r,t.getLine(r).length)}:void 0}})}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css new file mode 100755 index 000000000..43ac1a9fa --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css @@ -0,0 +1 @@ +.CodeMirror{font-family:monospace;height:500px;color:black;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:0;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0 !important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor-mark{background-color:rgba(20,255,20,0.5);-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:red}.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:white}.CodeMirror-scroll{overflow:scroll !important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none !important;border:none !important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0} diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js new file mode 100755 index 000000000..d01f072ee --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,r=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),l=n||i||o,s=l&&(n?document.documentMode||6:+(o||i)[1]),a=!o&&/WebKit\//.test(e),u=a&&/Qt\/\d+\.\d+/.test(e),c=!o&&/Chrome\//.test(e),h=/Opera\//.test(e),f=/Apple Computer/.test(navigator.vendor),d=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),g=!o&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),v=/Android/.test(e),m=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=g||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),x=h&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(h=!1,a=!0);var C=y&&(u||h&&(null==x||x<12.11)),S=r||l&&s>=9;function L(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var r=e.className,n=L(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}};function M(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}}g?P=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:l&&(P=function(e){try{e.select()}catch(e){}});var R=function(){this.id=null,this.f=null,this.time=0,this.handler=E(this.onTimeout,this)};function B(e,t){for(var r=0;r=t)return n+Math.min(l,t-i);if(i+=o-n,n=o+1,(i+=r-i%r)>=t)return n}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var r=[],n=0;n"€"&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var ne=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return e.charCodeAt(0)>=768&&ne.test(e)}function oe(e,t,r){for(;(r<0?t>0:tr?-1:1;;){if(t==r)return t;var i=(t+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:r;e(o)?r=o:t=o+n}}var se=null;function ae(e,t,r){var n;se=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==r?n=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=r?n=i:se=i)}return null!=n?n:se}var ue=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";var r=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,n=/[stwN]/,i=/[LRr]/,o=/[Lb1n]/,l=/[1n]/;function s(e,t,r){this.level=e,this.from=t,this.to=r}return function(a,u){var c="ltr"==u?"L":"R";if(0==a.length||"ltr"==u&&!r.test(a))return!1;for(var h,f=a.length,d=[],p=0;p-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ge(e,t){var r=de(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i0}function be(e){e.prototype.on=function(e,t){fe(this,e,t)},e.prototype.off=function(e,t){pe(this,e,t)}}function we(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function xe(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Ce(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Se(e){we(e),xe(e)}function Le(e){return e.target||e.srcElement}function ke(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Te,Me,Ne=function(){if(l&&s<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function Oe(e){if(null==Te){var t=O("span","​");N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Te=t.offsetWidth<=1&&t.offsetHeight>2&&!(l&&s<8))}var r=Te?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Ae(e){if(null!=Me)return Me;var t=N(e,document.createTextNode("AخA")),r=k(t,0,1).getBoundingClientRect(),n=k(t,1,2).getBoundingClientRect();return M(e),!(!r||r.left==r.right)&&(Me=n.right-r.right<3)}var De,We=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},He=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Fe="oncopy"in(De=O("div"))||(De.setAttribute("oncopy","return;"),"function"==typeof De.oncopy),Pe=null;var Ee={},Ie={};function ze(e){if("string"==typeof e&&Ie.hasOwnProperty(e))e=Ie[e];else if(e&&"string"==typeof e.name&&Ie.hasOwnProperty(e.name)){var t=Ie[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return ze("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return ze("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Re(e,t){t=ze(t);var r=Ee[t.name];if(!r)return Re(e,"text/plain");var n=r(e,t);if(Be.hasOwnProperty(t.name)){var i=Be[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)n[l]=t.modeProps[l];return n}var Be={};function Ge(e,t){I(t,Be.hasOwnProperty(e)?Be[e]:Be[e]={})}function Ue(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Ve(e,t){for(var r;e.innerMode&&(r=e.innerMode(t))&&r.mode!=e;)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Ke(e,t,r){return!e.startState||e.startState(t,r)}var je=function(e,t,r){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r};function Xe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t=e.first&&tr?et(r,Xe(e,r).text.length):function(e,t){var r=e.ch;return null==r||r>t?et(e.line,t):r<0?et(e.line,0):e}(t,Xe(e,t.line).text.length)}function at(e,t){for(var r=[],n=0;n=this.string.length},je.prototype.sol=function(){return this.pos==this.lineStart},je.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},je.prototype.next=function(){if(this.post},je.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},je.prototype.skipToEnd=function(){this.pos=this.string.length},je.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},je.prototype.backUp=function(e){this.pos-=e},je.prototype.column=function(){return this.lastColumnPos0?null:(n&&!1!==t&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},je.prototype.current=function(){return this.string.slice(this.start,this.pos)},je.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},je.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},je.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ut=function(e,t){this.state=e,this.lookAhead=t},ct=function(e,t,r,n){this.state=t,this.doc=e,this.line=r,this.maxLookAhead=n||0,this.baseTokens=null,this.baseTokenPos=1};function ht(e,t,r,n){var i=[e.state.modeGen],o={};wt(e,t.text,e.doc.mode,r,function(e,t){return i.push(e,t)},o,n);for(var l=r.state,s=function(n){r.baseTokens=i;var s=e.state.overlays[n],a=1,u=0;r.state=!0,wt(e,t.text,s.mode,r,function(e,t){for(var r=a;ue&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"overlay "+t),a=r+2;else for(;re.options.maxHighlightLength&&Ue(e.doc.mode,n.state),o=ht(e,t,n);i&&(n.state=i),t.stateAfter=n.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function dt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return new ct(n,!0,t);var o=function(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Xe(o,s-1),u=a.stateAfter;if(u&&(!r||s+(u instanceof ut?u.lookAhead:0)<=o.modeFrontier))return s;var c=z(a.text,null,e.options.tabSize);(null==i||n>c)&&(i=s-1,n=c)}return i}(e,t,r),l=o>n.first&&Xe(n,o-1).stateAfter,s=l?ct.fromSaved(n,l,o):new ct(n,Ke(n.mode),o);return n.iter(o,t,function(r){pt(e,r.text,s);var n=s.line;r.stateAfter=n==t-1||n%5==0||n>=i.viewFrom&&nt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ct.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ct.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ct.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ct.fromSaved=function(e,t,r){return t instanceof ut?new ct(e,Ue(e.mode,t.state),r,t.lookAhead):new ct(e,Ue(e.mode,t),r)},ct.prototype.save=function(e){var t=!1!==e?Ue(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ut(t,this.maxLookAhead):t};var mt=function(e,t,r){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=r};function yt(e,t,r,n){var i,o,l=e.doc,s=l.mode,a=Xe(l,(t=st(l,t)).line),u=dt(e,t.line,r),c=new je(a.text,e.options.tabSize,u);for(n&&(o=[]);(n||c.pose.options.maxHighlightLength?(s=!1,l&&pt(e,t,n,h.pos),h.pos=t.length,a=null):a=bt(vt(r,h,n.state,f),o),f){var d=f[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u=t:o.to>t);(n||(n=[])).push(new St(l,o.from,s?null:o.to))}}return n}(r,i,l),a=function(e,t,r){var n;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from0&&s)for(var b=0;bt)&&(!r||Wt(r,o.marker)<0)&&(r=o.marker)}return r}function It(e,t,r,n,i){var o=Xe(e,t),l=Ct&&o.markedSpans;if(l)for(var s=0;s=0&&h<=0||c<=0&&h>=0)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.to,r)>=0:tt(u.to,r)>0)||c>=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.from,n)<=0:tt(u.from,n)<0)))return!0}}}function zt(e){for(var t;t=Ft(e);)e=t.find(-1,!0).line;return e}function Rt(e,t){var r=Xe(e,t),n=zt(r);return r==n?t:qe(n)}function Bt(e,t){if(t>e.lastLine())return t;var r,n=Xe(e,t);if(!Gt(e,n))return t;for(;r=Pt(n);)n=r.find(1,!0).line;return qe(n)+1}function Gt(e,t){var r=Ct&&t.markedSpans;if(r)for(var n=void 0,i=0;it.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}var Xt=function(e,t,r){this.text=e,Ot(this,t),this.height=r?r(this):1};function Yt(e){e.parent=null,Nt(e)}Xt.prototype.lineNo=function(){return qe(this)},be(Xt);var _t={},$t={};function qt(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?$t:_t;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Zt(e,t){var r=A("span",null,null,a?"padding-right: .1px":null),n={pre:A("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,l=void 0;n.pos=0,n.addToken=Jt,Ae(e.display.measure)&&(l=ce(o,e.doc.direction))&&(n.addToken=er(n.addToken,l)),n.map=[],rr(o,n,ft(e,o,t!=e.display.externalMeasured&&qe(o))),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=F(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=F(o.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Oe(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(a){var s=n.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return ge(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=F(n.pre.className,n.textClass||"")),n}function Qt(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Jt(e,t,r,n,i,o,a){if(t){var u,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;iu&&h.from<=u);f++);if(h.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,h.to-u),i,o,null,s,a),o=null,n=n.slice(h.to-u),u=h.to}}}function tr(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rr(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,h,f,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=s="",f=null,h=null,m=1/0;for(var y=[],b=void 0,w=0;wp||C.collapsed&&x.to==p&&x.from==p)){if(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(b||(b=[])).push(C.endStyle,x.to),C.title&&((f||(f={})).title=C.title),C.attributes)for(var S in C.attributes)(f||(f={}))[S]=C.attributes[S];C.collapsed&&(!h||Wt(h.marker,C)<0)&&(h=x)}else x.from>p&&m>x.from&&(m=x.from)}if(b)for(var L=0;L=d)break;for(var T=Math.min(d,m);;){if(v){var M=p+v.length;if(!h){var N=M>T?v.slice(0,T-p):v;t.addToken(t,N,l?l+a:a,c,p+N.length==m?u:"",s,f)}if(M>=T){v=v.slice(T-p),p=T;break}p=M,c=""}v=i.slice(o,o=r[g++]),l=qt(r[g++],t.cm.options)}}else for(var O=1;Or)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Or(e,t,r,n){return Wr(e,Dr(e,t),r,n)}function Ar(e,t){if(t>=e.display.viewFrom&&t=r.lineN&&t2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,r,n){var i,o=Pr(t.map,r,n),a=o.node,u=o.start,c=o.end,h=o.collapse;if(3==a.nodeType){for(var f=0;f<4;f++){for(;u&&ie(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c1}(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}(e.display.measure,i))}else{var d;u>0&&(h=n="right"),i=e.options.lineWrapping&&(d=a.getClientRects()).length>1?d["right"==n?d.length-1:0]:a.getBoundingClientRect()}if(l&&s<9&&!u&&(!i||!i.left&&!i.right)){var p=a.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+tn(e.display),top:p.top,bottom:p.bottom}:Fr}for(var g=i.top-t.rect.top,v=i.bottom-t.rect.top,m=(g+v)/2,y=t.view.measure.heights,b=0;bt)&&(i=(o=a-s)-1,t>=a&&(l="right")),null!=i){if(n=e[u+2],s==a&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)n=e[2+(u-=3)],l="left";if("right"==r&&i==a-s)for(;u=0&&(r=e[i]).left==r.right;i--);return r}function Ir(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=n.text.length?(a=n.text.length,u="before"):a<=0&&(a=0,u="after"),!s)return l("before"==u?a-1:a,"before"==u);function c(e,t,r){return l(r?e-1:e,1==s[t].level!=r)}var h=ae(s,a,u),f=se,d=c(a,h,"before"==u);return null!=f&&(d.other=c(a,f,"before"!=u)),d}function Yr(e,t){var r=0;t=st(e.doc,t),e.options.lineWrapping||(r=tn(e.display)*t.ch);var n=Xe(e.doc,t.line),i=Vt(n)+Cr(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function _r(e,t,r,n,i){var o=et(e,t,r);return o.xRel=i,n&&(o.outside=n),o}function $r(e,t,r){var n=e.doc;if((r+=e.display.viewOffset)<0)return _r(n.first,0,null,-1,-1);var i=Ze(n,r),o=n.first+n.size-1;if(i>o)return _r(n.first+n.size-1,Xe(n,o).text.length,null,1,1);t<0&&(t=0);for(var l=Xe(n,i);;){var s=Jr(e,l,i,t,r),a=Et(l,s.ch+(s.xRel>0||s.outside>0?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Xe(n,i=u.line)}}function qr(e,t,r,n){n-=Ur(t);var i=t.text.length,o=le(function(t){return Wr(e,r,t-1).bottom<=n},i,0);return{begin:o,end:i=le(function(t){return Wr(e,r,t).top>n},o,i)}}function Zr(e,t,r,n){return r||(r=Dr(e,t)),qr(e,t,r,Vr(e,t,Wr(e,r,n),"line").top)}function Qr(e,t,r,n){return!(e.bottom<=r)&&(e.top>r||(n?e.left:e.right)>t)}function Jr(e,t,r,n,i){i-=Vt(t);var o=Dr(e,t),l=Ur(t),s=0,a=t.text.length,u=!0,c=ce(t,e.doc.direction);if(c){var h=(e.options.lineWrapping?function(e,t,r,n,i,o,l){var s=qr(e,t,n,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,f=0;f=u||d.to<=a)){var p=1!=d.level,g=Wr(e,n,p?Math.min(u,d.to)-1:Math.max(a,d.from)).right,v=gv)&&(c=d,h=v)}}c||(c=i[i.length-1]);c.fromu&&(c={from:c.from,to:u,level:c.level});return c}:function(e,t,r,n,i,o,l){var s=le(function(s){var a=i[s],u=1!=a.level;return Qr(Xr(e,et(r,u?a.to:a.from,u?"before":"after"),"line",t,n),o,l,!0)},0,i.length-1),a=i[s];if(s>0){var u=1!=a.level,c=Xr(e,et(r,u?a.from:a.to,u?"after":"before"),"line",t,n);Qr(c,o,l,!0)&&c.top>l&&(a=i[s-1])}return a})(e,t,r,o,c,n,i);s=(u=1!=h.level)?h.from:h.to-1,a=u?h.to:h.from-1}var f,d,p=null,g=null,v=le(function(t){var r=Wr(e,o,t);return r.top+=l,r.bottom+=l,!!Qr(r,n,i,!1)&&(r.top<=i&&r.left<=n&&(p=t,g=r),!0)},s,a),m=!1;if(g){var y=n-g.left=w.bottom?1:0}return _r(r,v=oe(t.text,v,1),d,m,n-f)}function en(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Hr){Hr=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Hr.appendChild(document.createTextNode("x")),Hr.appendChild(O("br"));Hr.appendChild(document.createTextNode("x"))}N(e.measure,Hr);var r=Hr.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),M(e.measure),r||1}function tn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),r=O("pre",[t],"CodeMirror-line-like");N(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function rn(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;r[s]=o.offsetLeft+o.clientLeft+i,n[s]=o.clientWidth}return{fixedPos:nn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function nn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function on(e){var t=en(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/tn(e.display)-3);return function(i){if(Gt(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var r=e.display.view,n=0;nt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ct&&Rt(e.doc,t)i.viewFrom?hn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)hn(e);else if(t<=i.viewFrom){var o=fn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):hn(e)}else if(r>=i.viewTo){var l=fn(e,t,t,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):hn(e)}else{var s=fn(e,t,t,-1),a=fn(e,r,r+n,1);s&&a?(i.view=i.view.slice(0,s.index).concat(ir(e,s.lineN,a.lineN)).concat(i.view.slice(a.index)),i.viewTo+=n):hn(e)}var u=i.externalMeasured;u&&(r=i.lineN&&t=n.viewTo)){var o=n.view[an(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);-1==B(l,r)&&l.push(r)}}}function hn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function fn(e,t,r,n){var i,o=an(e,t),l=e.display.view;if(!Ct||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=e.display.viewFrom,a=0;a0){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,r+=i}for(;Rt(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function dn(e){for(var t=e.display.view,r=0,n=0;n=e.display.viewTo||s.to().linet||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr",o),i=!0)}i||n(t,r,"ltr")}(g,r||0,null==n?f:n,function(e,t,i,h){var v="ltr"==i,m=d(e,v?"left":"right"),y=d(t-1,v?"right":"left"),b=null==r&&0==e,w=null==n&&t==f,x=0==h,C=!g||h==g.length-1;if(y.top-m.top<=3){var S=(u?w:b)&&C,L=(u?b:w)&&x?s:(v?m:y).left,k=S?a:(v?y:m).right;c(L,m.top,k-L,m.bottom)}else{var T,M,N,O;v?(T=u&&b&&x?s:m.left,M=u?a:p(e,i,"before"),N=u?s:p(t,i,"after"),O=u&&w&&C?a:y.right):(T=u?p(e,i,"before"):s,M=!u&&b&&x?a:m.right,N=!u&&w&&C?s:y.left,O=u?p(t,i,"after"):a),c(T,m.top,M-T,m.bottom),m.bottom0?t.blinker=setInterval(function(){return t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function wn(e){e.state.focused||(e.display.input.focus(),Cn(e))}function xn(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,Sn(e))},100)}function Cn(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ge(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),a&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),bn(e))}function Sn(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ge(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function Ln(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n.005||f<-.005)&&($e(i.line,a),kn(i.line),i.rest))for(var d=0;de.display.sizerWidth){var p=Math.ceil(u/tn(e.display));p>e.display.maxLineLength&&(e.display.maxLineLength=p,e.display.maxLine=i.line,e.display.maxLineChanged=!0)}}}}function kn(e){if(e.widgets)for(var t=0;t=l&&(o=Ze(t,Vt(Xe(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function Mn(e,t){var r=e.display,n=en(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:r.scroller.scrollTop,o=Mr(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Sr(r),a=t.tops-n;if(t.topi+o){var c=Math.min(t.top,(u?s:t.bottom)-o);c!=i&&(l.scrollTop=c)}var h=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:r.scroller.scrollLeft,f=Tr(e)-(e.options.fixedGutter?r.gutters.offsetWidth:0),d=t.right-t.left>f;return d&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.leftf+h-3&&(l.scrollLeft=t.right+(d?0:10)-f),l}function Nn(e,t){null!=t&&(Dn(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function On(e){Dn(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function An(e,t,r){null==t&&null==r||Dn(e),null!=t&&(e.curOp.scrollLeft=t),null!=r&&(e.curOp.scrollTop=r)}function Dn(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Wn(e,Yr(e,t.from),Yr(e,t.to),t.margin))}function Wn(e,t,r,n){var i=Mn(e,{left:Math.min(t.left,r.left),top:Math.min(t.top,r.top)-n,right:Math.max(t.right,r.right),bottom:Math.max(t.bottom,r.bottom)+n});An(e,i.scrollLeft,i.scrollTop)}function Hn(e,t){Math.abs(e.doc.scrollTop-t)<2||(r||oi(e,{top:t}),Fn(e,t,!0),r&&oi(e),ei(e,100))}function Fn(e,t,r){t=Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t),(e.display.scroller.scrollTop!=t||r)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Pn(e,t,r,n){t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!n||(e.doc.scrollLeft=t,ai(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function En(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Sr(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+kr(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}var In=function(e,t,r){this.cm=r;var n=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,e(n),e(i),fe(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),fe(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,l&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};In.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},In.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},In.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},In.prototype.zeroWidthHack=function(){var e=y&&!d?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new R,this.disableVert=new R},In.prototype.enableZeroWidthBar=function(e,t,r){e.style.pointerEvents="auto",t.set(1e3,function n(){var i=e.getBoundingClientRect();("vert"==r?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,n)})},In.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var zn=function(){};function Rn(e,t){t||(t=En(e));var r=e.display.barWidth,n=e.display.barHeight;Bn(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&Ln(e),Bn(e,En(e)),r=e.display.barWidth,n=e.display.barHeight}function Bn(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}zn.prototype.update=function(){return{bottom:0,right:0}},zn.prototype.setScrollLeft=function(){},zn.prototype.setScrollTop=function(){},zn.prototype.clear=function(){};var Gn={native:In,null:zn};function Un(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&T(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Gn[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),fe(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,r){"horizontal"==r?Pn(e,t):Hn(e,t)},e),e.display.scrollbars.addClass&&H(e.display.wrapper,e.display.scrollbars.addClass)}var Vn=0;function Kn(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Vn},t=e.curOp,or?or.ops.push(t):t.ownsGroup=or={ops:[t],delayedCallbacks:[]}}function jn(e){var t=e.curOp;t&&function(e,t){var r=e.ownsGroup;if(r)try{!function(e){var t=e.delayedCallbacks,r=0;do{for(;r=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ri(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Yn(e){var t=e.cm,r=t.display;e.updatedDisplay&&Ln(t),e.barMeasure=En(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Or(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+kr(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Tr(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function _n(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Cr(e.display))+"px;\n height: "+(t.bottom-t.top+kr(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}(t,function(e,t,r,n){var i;null==n&&(n=0),e.options.lineWrapping||t!=r||(r="before"==(t=t.ch?et(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?et(t.line,t.ch+1,"before"):t);for(var o=0;o<5;o++){var l=!1,s=Xr(e,t),a=r&&r!=t?Xr(e,r):s,u=Mn(e,i={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-n,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+n}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Hn(e,u.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(l=!0)),null!=u.scrollLeft&&(Pn(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-h)>1&&(l=!0)),!l)break}return i}(t,st(n,e.scrollToPos.from),st(n,e.scrollToPos.to),e.scrollToPos.margin));var i=e.maybeHiddenMarkers,o=e.maybeUnhiddenMarkers;if(i)for(var l=0;l=e.display.viewTo)){var r=+new Date+e.options.workTime,n=dt(e,t.highlightFrontier),i=[];t.iter(n.line,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(n.line>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength?Ue(t.mode,n.state):null,a=ht(e,o,n,!0);s&&(n.state=s),o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var h=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!h&&fr)return ei(e,e.options.workDelay),!0}),t.highlightFrontier=n.line,t.modeFrontier=Math.max(t.modeFrontier,n.line),i.length&&qn(e,function(){for(var t=0;t=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==dn(e))return!1;ui(e)&&(hn(e),t.dims=rn(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFroml&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Ct&&(o=Rt(e.doc,o),l=Bt(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;!function(e,t,r){var n=e.display;0==n.view.length||t>=n.viewTo||r<=n.viewFrom?(n.view=ir(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=ir(e,t,n.viewFrom).concat(n.view):n.viewFromr&&(n.view=n.view.slice(0,an(e,r)))),n.viewTo=r}(e,o,l),r.viewOffset=Vt(Xe(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var u=dn(e);if(!s&&0==u&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var c=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var r={activeElt:t};if(window.getSelection){var n=window.getSelection();n.anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset)}return r}(e);return u>4&&(r.lineDiv.style.display="none"),function(e,t,r){var n=e.display,i=e.options.lineNumbers,o=n.lineDiv,l=o.firstChild;function s(t){var r=t.nextSibling;return a&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var u=n.view,c=n.viewFrom,h=0;h-1&&(d=!1),ur(e,f,c,r)),d&&(M(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(Je(e.options,c)))),l=f.node.nextSibling}else{var p=vr(e,f,c,r);o.insertBefore(p,l)}c+=f.size}for(;l;)l=s(l)}(e,r.updateLineNumbers,t.dims),u>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,function(e){if(e&&e.activeElt&&e.activeElt!=W()&&(e.activeElt.focus(),e.anchorNode&&D(document.body,e.anchorNode)&&D(document.body,e.focusNode))){var t=window.getSelection(),r=document.createRange();r.setEnd(e.anchorNode,e.anchorOffset),r.collapse(!1),t.removeAllRanges(),t.addRange(r),t.extend(e.focusNode,e.focusOffset)}}(c),M(r.cursorDiv),M(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,ei(e,400)),r.updateLineNumbers=null,!0}function ii(e,t){for(var r=t.viewport,n=!0;(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Tr(e)||(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Sr(e.display)-Mr(e),r.top)}),t.visible=Tn(e.display,e.doc,r),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&ni(e,t);n=!1){Ln(e);var i=En(e);pn(e),Rn(e,i),si(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function oi(e,t){var r=new ri(e,t);if(ni(e,r)){Ln(e),ii(e,r);var n=En(e);pn(e),Rn(e,n),si(e,n),r.finish()}}function li(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function si(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+kr(e)+"px"}function ai(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=nn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;ls.clientWidth,c=s.scrollHeight>s.clientHeight;if(i&&u||o&&c){if(o&&y&&a)e:for(var f=t.target,d=l.view;f!=s;f=f.parentNode)for(var p=0;p=0&&tt(e,n.to())<=0)return r}return-1};var bi=function(e,t){this.anchor=e,this.head=t};function wi(e,t,r){var n=e&&e.options.selectionsMayTouch,i=t[r];t.sort(function(e,t){return tt(e.from(),t.from())}),r=B(t,i);for(var o=1;o0:a>=0){var u=ot(s.from(),l.from()),c=it(s.to(),l.to()),h=s.empty()?l.from()==l.head:s.from()==s.head;o<=r&&--r,t.splice(--o,2,new bi(h?c:u,h?u:c))}}return new yi(t,r)}function xi(e,t){return new yi([new bi(e,t||e)],0)}function Ci(e){return e.text?et(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function Si(e,t){if(tt(e,t.from)<0)return e;if(tt(e,t.to)<=0)return Ci(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Ci(t).ch-t.to.ch),et(r,n)}function Li(e,t){for(var r=[],n=0;n1&&e.remove(s.line+1,p-1),e.insert(s.line+1,m)}sr(e,"change",e,t)}function Ai(e,t,r){!function e(n,i,o){if(n.linked)for(var l=0;ls-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(Pi(e.done),$(e.done)):e.done.length&&!$(e.done).ranges?$(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),$(e.done)):void 0}(i,i.lastOp==n)))l=$(o.changes),0==tt(t.from,t.to)&&0==tt(t.from,l.to)?l.to=Ci(t):o.changes.push(Fi(e,t));else{var a=$(i.done);for(a&&a.ranges||zi(e.sel,i.done),o={changes:[Fi(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,l||ge(e,"historyAdded")}function Ii(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||function(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,$(i.done),t))?i.done[i.done.length-1]=t:zi(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&!1!==n.clearRedo&&Pi(i.undone)}function zi(e,t){var r=$(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Ri(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function Bi(e){if(!e)return null;for(var t,r=0;r-1&&($(s)[h]=u[h],delete u[h])}}}return n}function Vi(e,t,r,n){if(n){var i=e.anchor;if(r){var o=tt(t,i)<0;o!=tt(r,i)<0?(i=t,t=r):o!=tt(t,r)<0&&(t=r)}return new bi(i,t)}return new bi(r||t,t)}function Ki(e,t,r,n,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),$i(e,new yi([Vi(e.sel.primary(),t,r,i)],0),n)}function ji(e,t,r){for(var n=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:s.to>t.ch))){if(i&&(ge(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var h=a.find(n<0?1:-1),f=void 0;if((n<0?c:u)&&(h=ro(e,h,-n,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(f=tt(h,r))&&(n<0?f<0:f>0))return eo(e,h,t,n,i)}var d=a.find(n<0?-1:1);return(n<0?u:c)&&(d=ro(e,d,n,d.line==t.line?o:null)),d?eo(e,d,t,n,i):null}}return t}function to(e,t,r,n,i){var o=n||1,l=eo(e,t,r,o,i)||!i&&eo(e,t,r,o,!0)||eo(e,t,r,-o,i)||!i&&eo(e,t,r,-o,!0);return l||(e.cantEdit=!0,et(e.first,0))}function ro(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?st(e,et(t.line-1)):null:r>0&&t.ch==(n||Xe(e,t.line)).text.length?t.line0)){var c=[a,1],h=tt(u.from,s.from),f=tt(u.to,s.to);(h<0||!l.inclusiveLeft&&!h)&&c.push({from:u.from,to:s.from}),(f>0||!l.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-3}}return i}(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)lo(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text,origin:t.origin});else lo(e,t)}}function lo(e,t){if(1!=t.text.length||""!=t.text[0]||0!=tt(t.from,t.to)){var r=Li(e,t);Ei(e,t,r,e.cm?e.cm.curOp.id:NaN),uo(e,t,r,Tt(e,t));var n=[];Ai(e,function(e,r){r||-1!=B(n,e.history)||(po(e.history,t),n.push(e.history)),uo(e,t,null,Tt(e,t))})}}function so(e,t,r){var n=e.cm&&e.cm.state.suppressEdits;if(!n||r){for(var i,o=e.history,l=e.sel,s="undo"==t?o.done:o.undone,a="undo"==t?o.undone:o.done,u=0;u=0;--d){var p=f(d);if(p)return p.v}}}}function ao(e,t){if(0!=t&&(e.first+=t,e.sel=new yi(q(e.sel.ranges,function(e){return new bi(et(e.anchor.line+t,e.anchor.ch),et(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){un(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;ne.lastLine())){if(t.from.lineo&&(t={from:t.from,to:et(o,Xe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ye(e,t.from,t.to),r||(r=Li(e,t)),e.cm?function(e,t,r){var n=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=qe(zt(Xe(n,o.line))),n.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0,!0}));n.sel.contains(t.from,t.to)>-1&&me(e);Oi(n,t,r,on(e)),e.options.lineWrapping||(n.iter(a,o.line+t.text.length,function(e){var t=Kt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontierr;n--){var i=Xe(e,n).stateAfter;if(i&&(!(i instanceof ut)||n+i.lookAhead1||!(this.children[0]instanceof vo))){var s=[];this.collapse(s),this.children=[new vo(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var l=i.lines.length%25+25,s=l;s10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n0||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(It(e,t.line,t,r,o)||t.line!=r.line&&It(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Ct=!0}o.addToHistory&&Ei(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&zt(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&$e(e,0),function(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}(e,new St(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){Gt(e,t)&&$e(t,0)}),o.clearOnEnter&&fe(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(xt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++wo,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)un(u,t.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=r.line;c++)cn(u,c,"text");o.atomic&&Qi(u.doc),sr(u,"markerAdded",u,o)}return o}xo.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Kn(e),ye(this,"clear")){var r=this.find();r&&sr(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&un(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Qi(e.doc)),e&&sr(e,"markerCleared",e,this,n,i),t&&jn(e),this.parent&&this.parent.clear()}},xo.prototype.find=function(e,t){var r,n;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;a--)oo(this,n[a]);s?_i(this,s):this.cm&&On(this.cm)}),undo:Jn(function(){so(this,"undo")}),redo:Jn(function(){so(this,"redo")}),undoSelection:Jn(function(){so(this,"undo",!0)}),redoSelection:Jn(function(){so(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=st(this,e),t=st(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s=a.to||null==a.from&&i!=e.line||null!=a.from&&i==t.line&&a.from>=t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;ne)return t=e,!0;e-=o,++r}),st(this,et(r,t))},indexFromPos:function(e){var t=(e=st(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var c=e.dataTransfer.getData("Text");if(c){var h;if(t.state.draggingText&&!t.state.draggingText.copy&&(h=t.listSelections()),qi(t.doc,xi(r,r)),h)for(var f=0;f=0;t--)co(e.doc,"",n[t].from,n[t].to,"+delete");On(e)})}function _o(e,t,r){var n=oe(e.text,t+r,r);return n<0||n>e.text.length?null:n}function $o(e,t,r){var n=_o(e,t.ch,r);return null==n?null:new et(t.line,n,r<0?"after":"before")}function qo(e,t,r,n,i){if(e){var o=ce(r,t.doc.direction);if(o){var l,s=i<0?$(o):o[0],a=i<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var u=Dr(t,r);l=i<0?r.text.length-1:0;var c=Wr(t,u,l).top;l=le(function(e){return Wr(t,u,e).top==c},i<0==(1==s.level)?s.from:s.to-1,l),"before"==a&&(l=_o(r,l,1))}else l=i<0?s.to:s.from;return new et(n,l,a)}}return new et(n,i<0?r.text.length:0,i<0?"before":"after")}Ro.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ro.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ro.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ro.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ro.default=y?Ro.macDefault:Ro.pcDefault;var Zo={selectAll:no,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(e){return Yo(e,function(t){if(t.empty()){var r=Xe(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line0)i=new et(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),et(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var l=Xe(e.doc,i.line-1).text;l&&(i=new et(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+l.charAt(l.length-1),et(i.line-1,l.length-1),i,"+transpose"))}r.push(new bi(i,i))}e.setSelections(r)})},newlineAndIndent:function(e){return qn(e,function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange(e.doc.lineSeparator(),t[r].anchor,t[r].head,"+input");t=e.listSelections();for(var n=0;n-1&&(tt((i=u.ranges[i]).from(),t)<0||t.xRel>0)&&(tt(i.to(),t)>0||t.xRel<0)?function(e,t,r,n){var i=e.display,o=!1,u=Zn(e,function(t){a&&(i.scroller.draggable=!1),e.state.draggingText=!1,pe(i.wrapper.ownerDocument,"mouseup",u),pe(i.wrapper.ownerDocument,"mousemove",c),pe(i.scroller,"dragstart",h),pe(i.scroller,"drop",u),o||(we(t),n.addNew||Ki(e.doc,r,null,null,n.extend),a||l&&9==s?setTimeout(function(){i.wrapper.ownerDocument.body.focus(),i.input.focus()},20):i.input.focus())}),c=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},h=function(){return o=!0};a&&(i.scroller.draggable=!0);e.state.draggingText=u,u.copy=!n.moveOnDrag,i.scroller.dragDrop&&i.scroller.dragDrop();fe(i.wrapper.ownerDocument,"mouseup",u),fe(i.wrapper.ownerDocument,"mousemove",c),fe(i.scroller,"dragstart",h),fe(i.scroller,"drop",u),xn(e),setTimeout(function(){return i.input.focus()},20)}(e,n,t,o):function(e,t,r,n){var i=e.display,o=e.doc;we(t);var l,s,a=o.sel,u=a.ranges;n.addNew&&!n.extend?(s=o.sel.contains(r),l=s>-1?u[s]:new bi(r,r)):(l=o.sel.primary(),s=o.sel.primIndex);if("rectangle"==n.unit)n.addNew||(l=new bi(r,r)),r=sn(e,t,!0,!0),s=-1;else{var c=dl(e,r,n.unit);l=n.extend?Vi(l,c.anchor,c.head,n.extend):c}n.addNew?-1==s?(s=u.length,$i(o,wi(e,u.concat([l]),s),{scroll:!1,origin:"*mouse"})):u.length>1&&u[s].empty()&&"char"==n.unit&&!n.extend?($i(o,wi(e,u.slice(0,s).concat(u.slice(s+1)),0),{scroll:!1,origin:"*mouse"}),a=o.sel):Xi(o,s,l,K):(s=0,$i(o,new yi([l],0),K),a=o.sel);var h=r;function f(t){if(0!=tt(h,t))if(h=t,"rectangle"==n.unit){for(var i=[],u=e.options.tabSize,c=z(Xe(o,r.line).text,r.ch,u),f=z(Xe(o,t.line).text,t.ch,u),d=Math.min(c,f),p=Math.max(c,f),g=Math.min(r.line,t.line),v=Math.min(e.lastLine(),Math.max(r.line,t.line));g<=v;g++){var m=Xe(o,g).text,y=X(m,d,u);d==p?i.push(new bi(et(g,y),et(g,y))):m.length>y&&i.push(new bi(et(g,y),et(g,X(m,p,u))))}i.length||i.push(new bi(r,r)),$i(o,wi(e,a.ranges.slice(0,s).concat(i),s),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=l,x=dl(e,t,n.unit),C=w.anchor;tt(x.anchor,C)>0?(b=x.head,C=ot(w.from(),x.anchor)):(b=x.anchor,C=it(w.to(),x.head));var S=a.ranges.slice(0);S[s]=function(e,t){var r=t.anchor,n=t.head,i=Xe(e.doc,r.line);if(0==tt(r,n)&&r.sticky==n.sticky)return t;var o=ce(i);if(!o)return t;var l=ae(o,r.ch,r.sticky),s=o[l];if(s.from!=r.ch&&s.to!=r.ch)return t;var a,u=l+(s.from==r.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;if(n.line!=r.line)a=(n.line-r.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ae(o,n.ch,n.sticky),h=c-l||(n.ch-r.ch)*(1==s.level?-1:1);a=c==u-1||c==u?h<0:h>0}var f=o[u+(a?-1:0)],d=a==(1==f.level),p=d?f.from:f.to,g=d?"after":"before";return r.ch==p&&r.sticky==g?t:new bi(new et(r.line,p,g),n)}(e,new bi(st(o,C),b)),$i(o,wi(e,S,s),K)}}var d=i.wrapper.getBoundingClientRect(),p=0;function g(t){e.state.selectingText=!1,p=1/0,t&&(we(t),i.input.focus()),pe(i.wrapper.ownerDocument,"mousemove",v),pe(i.wrapper.ownerDocument,"mouseup",m),o.history.lastSelOrigin=null}var v=Zn(e,function(t){0!==t.buttons&&ke(t)?function t(r){var l=++p;var s=sn(e,r,!0,"rectangle"==n.unit);if(!s)return;if(0!=tt(s,h)){e.curOp.focus=W(),f(s);var a=Tn(i,o);(s.line>=a.to||s.lined.bottom?20:0;u&&setTimeout(Zn(e,function(){p==l&&(i.scroller.scrollTop+=u,t(r))}),50)}}(t):g(t)}),m=Zn(e,g);e.state.selectingText=m,fe(i.wrapper.ownerDocument,"mousemove",v),fe(i.wrapper.ownerDocument,"mouseup",m)}(e,n,t,o)}(t,n,o,e):Le(e)==r.scroller&&we(e):2==i?(n&&Ki(t.doc,n),setTimeout(function(){return r.input.focus()},20)):3==i&&(S?t.display.input.onContextMenu(e):xn(t)))}}function dl(e,t,r){if("char"==r)return new bi(t,t);if("word"==r)return e.findWordAt(t);if("line"==r)return new bi(et(t.line,0),st(e.doc,et(t.line+1,0)));var n=r(e,t);return new bi(n.from,n.to)}function pl(e,t,r,n){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&we(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!ye(e,r))return Ce(t);o-=s.top-l.viewOffset;for(var a=0;a=i)return ge(e,r,e,Ze(e.doc,o),e.display.gutterSpecs[a].className,t),Ce(t)}}function gl(e,t){return pl(e,t,"gutterClick",!0)}function vl(e,t){xr(e.display,t)||function(e,t){if(!ye(e,"gutterContextMenu"))return!1;return pl(e,t,"gutterContextMenu",!1)}(e,t)||ve(e,t,"contextmenu")||S||e.display.input.onContextMenu(t)}function ml(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Rr(e)}hl.prototype.compare=function(e,t,r){return this.time+400>e&&0==tt(t,this.pos)&&r==this.button};var yl={toString:function(){return"CodeMirror.Init"}},bl={},wl={};function xl(e,t,r){if(!t!=!(r&&r!=yl)){var n=e.display.dragFunctions,i=t?fe:pe;i(e.display.scroller,"dragstart",n.start),i(e.display.scroller,"dragenter",n.enter),i(e.display.scroller,"dragover",n.over),i(e.display.scroller,"dragleave",n.leave),i(e.display.scroller,"drop",n.drop)}}function Cl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),jt(e)),ln(e),un(e),Rr(e),setTimeout(function(){return Rn(e)},100)}function Sl(e,t){var n=this;if(!(this instanceof Sl))return new Sl(e,t);this.options=t=t?I(t):{},I(bl,t,!1);var i=t.value;"string"==typeof i?i=new Mo(i,t.mode,null,t.lineSeparator,t.direction):t.mode&&(i.modeOption=t.mode),this.doc=i;var o=new Sl.inputStyles[t.inputStyle](this),u=this.display=new function(e,t,n,i){var o=this;this.input=n,o.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),o.scrollbarFiller.setAttribute("cm-not-content","true"),o.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),o.gutterFiller.setAttribute("cm-not-content","true"),o.lineDiv=A("div",null,"CodeMirror-code"),o.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),o.cursorDiv=O("div",null,"CodeMirror-cursors"),o.measure=O("div",null,"CodeMirror-measure"),o.lineMeasure=O("div",null,"CodeMirror-measure"),o.lineSpace=A("div",[o.measure,o.lineMeasure,o.selectionDiv,o.cursorDiv,o.lineDiv],null,"position: relative; outline: none");var u=A("div",[o.lineSpace],"CodeMirror-lines");o.mover=O("div",[u],null,"position: relative"),o.sizer=O("div",[o.mover],"CodeMirror-sizer"),o.sizerWidth=null,o.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),o.gutters=O("div",null,"CodeMirror-gutters"),o.lineGutter=null,o.scroller=O("div",[o.sizer,o.heightForcer,o.gutters],"CodeMirror-scroll"),o.scroller.setAttribute("tabIndex","-1"),o.wrapper=O("div",[o.scrollbarFiller,o.gutterFiller,o.scroller],"CodeMirror"),l&&s<8&&(o.gutters.style.zIndex=-1,o.scroller.style.paddingRight=0),a||r&&m||(o.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(o.wrapper):e(o.wrapper)),o.viewFrom=o.viewTo=t.first,o.reportedViewFrom=o.reportedViewTo=t.first,o.view=[],o.renderedView=null,o.externalMeasured=null,o.viewOffset=0,o.lastWrapHeight=o.lastWrapWidth=0,o.updateLineNumbers=null,o.nativeBarWidth=o.barHeight=o.barWidth=0,o.scrollbarsClipped=!1,o.lineNumWidth=o.lineNumInnerWidth=o.lineNumChars=null,o.alignWidgets=!1,o.cachedCharWidth=o.cachedTextHeight=o.cachedPaddingH=null,o.maxLine=null,o.maxLineLength=0,o.maxLineChanged=!1,o.wheelDX=o.wheelDY=o.wheelStartX=o.wheelStartY=null,o.shift=!1,o.selForContextMenu=null,o.activeTouch=null,o.gutterSpecs=ci(i.gutters,i.lineNumbers),hi(o),n.init(o)}(e,i,o,t);for(var c in u.wrapper.CodeMirror=this,ml(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Un(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new R,keySeq:null,specialChars:null},t.autofocus&&!m&&u.input.focus(),l&&s<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(e){var t=e.display;fe(t.scroller,"mousedown",Zn(e,fl)),fe(t.scroller,"dblclick",l&&s<11?Zn(e,function(t){if(!ve(e,t)){var r=sn(e,t);if(r&&!gl(e,t)&&!xr(e.display,t)){we(t);var n=e.findWordAt(r);Ki(e.doc,n.anchor,n.head)}}}):function(t){return ve(e,t)||we(t)});fe(t.scroller,"contextmenu",function(t){return vl(e,t)});var r,n={end:0};function i(){t.activeTouch&&(r=setTimeout(function(){return t.activeTouch=null},1e3),(n=t.activeTouch).end=+new Date)}function o(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}fe(t.scroller,"touchstart",function(i){if(!ve(e,i)&&!function(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}(i)&&!gl(e,i)){t.input.ensurePolled(),clearTimeout(r);var o=+new Date;t.activeTouch={start:o,moved:!1,prev:o-n.end<=300?n:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}}),fe(t.scroller,"touchmove",function(){t.activeTouch&&(t.activeTouch.moved=!0)}),fe(t.scroller,"touchend",function(r){var n=t.activeTouch;if(n&&!xr(t,r)&&null!=n.left&&!n.moved&&new Date-n.start<300){var l,s=e.coordsChar(t.activeTouch,"page");l=!n.prev||o(n,n.prev)?new bi(s,s):!n.prev.prev||o(n,n.prev.prev)?e.findWordAt(s):new bi(et(s.line,0),st(e.doc,et(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),we(r)}i()}),fe(t.scroller,"touchcancel",i),fe(t.scroller,"scroll",function(){t.scroller.clientHeight&&(Hn(e,t.scroller.scrollTop),Pn(e,t.scroller.scrollLeft,!0),ge(e,"scroll",e))}),fe(t.scroller,"mousewheel",function(t){return mi(e,t)}),fe(t.scroller,"DOMMouseScroll",function(t){return mi(e,t)}),fe(t.wrapper,"scroll",function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0}),t.dragFunctions={enter:function(t){ve(e,t)||Se(t)},over:function(t){ve(e,t)||(!function(e,t){var r=sn(e,t);if(r){var n=document.createDocumentFragment();vn(e,r,n),e.display.dragCursor||(e.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),N(e.display.dragCursor,n)}}(e,t),Se(t))},start:function(t){return function(e,t){if(l&&(!e.state.draggingText||+new Date-No<100))Se(t);else if(!ve(e,t)&&!xr(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!f)){var r=O("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",h&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),h&&r.parentNode.removeChild(r)}}(e,t)},drop:Zn(e,Oo),leave:function(t){ve(e,t)||Ao(e)}};var a=t.input.getField();fe(a,"keyup",function(t){return sl.call(e,t)}),fe(a,"keydown",Zn(e,ll)),fe(a,"keypress",Zn(e,al)),fe(a,"focus",function(t){return Cn(e,t)}),fe(a,"blur",function(t){return Sn(e,t)})}(this),Ho(),Kn(this),this.curOp.forceUpdate=!0,Di(this,i),t.autofocus&&!m||this.hasFocus()?setTimeout(E(Cn,this),20):Sn(this),wl)wl.hasOwnProperty(c)&&wl[c](n,t[c],yl);ui(this),t.finishInit&&t.finishInit(this);for(var d=0;d150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?z(Xe(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var h="",f=0;if(e.options.indentWithTabs)for(var d=Math.floor(u/l);d;--d)f+=l,h+="\t";if(fl,a=We(t),u=null;if(s&&n.ranges.length>1)if(Tl&&Tl.text.join("\n")==t){if(n.ranges.length%Tl.text.length==0){u=[];for(var c=0;c=0;f--){var d=n.ranges[f],p=d.from(),g=d.to();d.empty()&&(r&&r>0?p=et(p.line,p.ch-r):e.state.overwrite&&!s?g=et(g.line,Math.min(Xe(o,g.line).text.length,g.ch+$(a).length)):s&&Tl&&Tl.lineWise&&Tl.text.join("\n")==t&&(p=g=et(p.line,0)));var v={from:p,to:g,text:u?u[f%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};oo(e.doc,v),sr(e,"inputRead",e,v)}t&&!s&&Al(e,t),On(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Ol(e,t){var r=e.clipboardData&&e.clipboardData.getData("Text");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||qn(t,function(){return Nl(t,r,0,null,"paste")}),!0}function Al(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s-1){l=kl(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Xe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=kl(e,i.head.line,"smart"));l&&sr(e,"electricInput",e,i.head.line)}}}function Dl(e){for(var t=[],r=[],n=0;n=t.text.length?(r.ch=t.text.length,r.sticky="before"):r.ch<=0&&(r.ch=0,r.sticky="after");var o=ae(i,r.ch,r.sticky),l=i[o];if("ltr"==e.doc.direction&&l.level%2==0&&(n>0?l.to>r.ch:l.from=l.from&&f>=c.begin)){var d=h?"before":"after";return new et(r.line,f,d)}}var p=function(e,t,n){for(var o=function(e,t){return t?new et(r.line,a(e,1),"before"):new et(r.line,e,"after")};e>=0&&e0==(1!=l.level),u=s?n.begin:a(n.end,-1);if(l.from<=u&&u0?c.end:a(c.begin,-1);return null==v||n>0&&v==t.text.length||!(g=p(n>0?0:i.length-1,n,u(v)))?null:g}(e.cm,s,t,r):$o(s,t,r))){if(n||(l=t.line+r)=e.first+e.size||(t=new et(l,t.ch,t.sticky),!(s=Xe(e,l))))return!1;t=qo(i,e.cm,s,t.line,r)}else t=o;return!0}if("char"==n)a();else if("column"==n)a(!0);else if("word"==n||"group"==n)for(var u=null,c="group"==n,h=e.cm&&e.cm.getHelper(t,"wordChars"),f=!0;!(r<0)||a(!f);f=!1){var d=s.text.charAt(t.ch)||"\n",p=te(d,h)?"w":c&&"\n"==d?"n":!c||/\s/.test(d)?null:"p";if(!c||f||p||(p="s"),u&&u!=p){r<0&&(r=1,a(),t.sticky="after");break}if(p&&(u=p),r>0&&!a(!f))break}var g=to(e,t,o,l,!0);return rt(o,g)&&(g.hitSide=!0),g}function Pl(e,t,r,n){var i,o,l=e.doc,s=t.left;if("page"==n){var a=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),u=Math.max(a-.5*en(e.display),3);i=(r>0?t.bottom:t.top)+r*u}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;(o=$r(e,s,i)).outside;){if(r<0?i<=0:i>=l.height){o.hitSide=!0;break}i+=5*r}return o}var El=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new R,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Il(e,t){var r=Ar(e,t.line);if(!r||r.hidden)return null;var n=Xe(e.doc,t.line),i=Nr(r,n,t.line),o=ce(n,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Pr(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function zl(e,t){return t&&(e.bad=!0),e}function Rl(e,t,r){var n;if(t==e.display.lineDiv){if(!(n=e.display.lineDiv.childNodes[r]))return zl(e.clipPos(et(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i=t.display.viewTo||o.line=t.display.viewFrom&&Il(t,i)||{node:a[0].measure.map[2],offset:0},c=o.linen.firstLine()&&(l=et(l.line-1,Xe(n.doc,l.line-1).length)),s.ch==Xe(n.doc,s.line).text.length&&s.linei.viewTo-1)return!1;l.line==i.viewFrom||0==(e=an(n,l.line))?(t=qe(i.view[0].line),r=i.view[0].node):(t=qe(i.view[e].line),r=i.view[e-1].node.nextSibling);var a,u,c=an(n,s.line);if(c==i.view.length-1?(a=i.viewTo-1,u=i.lineDiv.lastChild):(a=qe(i.view[c+1].line)-1,u=i.view[c+1].node.previousSibling),!r)return!1;for(var h=n.doc.splitLines(function(e,t,r,n,i){var o="",l=!1,s=e.doc.lineSeparator(),a=!1;function u(){l&&(o+=s,a&&(o+=s),l=a=!1)}function c(e){e&&(u(),o+=e)}function h(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(r)return void c(r);var o,f=t.getAttribute("cm-marker");if(f){var d=e.findMarks(et(n,0),et(i+1,0),(v=+f,function(e){return e.id==v}));return void(d.length&&(o=d[0].find(0))&&c(Ye(e.doc,o.from,o.to).join(s)))}if("false"==t.getAttribute("contenteditable"))return;var p=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;p&&u();for(var g=0;g1&&f.length>1;)if($(h)==$(f))h.pop(),f.pop(),a--;else{if(h[0]!=f[0])break;h.shift(),f.shift(),t++}for(var d=0,p=0,g=h[0],v=f[0],m=Math.min(g.length,v.length);dl.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)d--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(d).replace(/\u200b+$/,"");var x=et(t,d),C=et(a,f.length?$(f).length-p:0);return h.length>1||h[0]||tt(x,C)?(co(n.doc,h,x,C,"+input"),!0):void 0},El.prototype.ensurePolled=function(){this.forceCompositionEnd()},El.prototype.reset=function(){this.forceCompositionEnd()},El.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},El.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},El.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||qn(this.cm,function(){return un(e.cm)})},El.prototype.setUneditable=function(e){e.contentEditable="false"},El.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Zn(this.cm,Nl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},El.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},El.prototype.onContextMenu=function(){},El.prototype.resetPosition=function(){},El.prototype.needsContentAttribute=!0;var Gl=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new R,this.hasSelection=!1,this.composing=null};Gl.prototype.init=function(e){var t=this,r=this,n=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!ve(n,e)){if(n.somethingSelected())Ml({lineWise:!1,text:n.getSelections()});else{if(!n.options.lineWiseCopyCut)return;var t=Dl(n);Ml({lineWise:!0,text:t.text}),"cut"==e.type?n.setSelections(t.ranges,null,V):(r.prevInput="",i.value=t.text.join("\n"),P(i))}"cut"==e.type&&(n.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(i.style.width="0px"),fe(i,"input",function(){l&&s>=9&&t.hasSelection&&(t.hasSelection=null),r.poll()}),fe(i,"paste",function(e){ve(n,e)||Ol(e,n)||(n.state.pasteIncoming=+new Date,r.fastPoll())}),fe(i,"cut",o),fe(i,"copy",o),fe(e.scroller,"paste",function(t){if(!xr(e,t)&&!ve(n,t)){if(!i.dispatchEvent)return n.state.pasteIncoming=+new Date,void r.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,i.dispatchEvent(o)}}),fe(e.lineSpace,"selectstart",function(t){xr(e,t)||we(t)}),fe(i,"compositionstart",function(){var e=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:n.markText(e,n.getCursor("to"),{className:"CodeMirror-composing"})}}),fe(i,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Gl.prototype.createField=function(e){this.wrapper=Hl(),this.textarea=this.wrapper.firstChild},Gl.prototype.prepareSelection=function(){var e=this.cm,t=e.display,r=e.doc,n=gn(e);if(e.options.moveInputWithCursor){var i=Xr(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),l=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},Gl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Gl.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var r=t.getSelection();this.textarea.value=r,t.state.focused&&P(this.textarea),l&&s>=9&&(this.hasSelection=r)}else e||(this.prevInput=this.textarea.value="",l&&s>=9&&(this.hasSelection=null))}},Gl.prototype.getField=function(){return this.textarea},Gl.prototype.supportsTouch=function(){return!1},Gl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!m||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Gl.prototype.blur=function(){this.textarea.blur()},Gl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Gl.prototype.receivedFocus=function(){this.slowPoll()},Gl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Gl.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,function r(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,r))})},Gl.prototype.poll=function(){var e=this,t=this.cm,r=this.textarea,n=this.prevInput;if(this.contextMenuPending||!t.state.focused||He(r)&&!n&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=r.value;if(i==n&&!t.somethingSelected())return!1;if(l&&s>=9&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||n||(n="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var a=0,u=Math.min(n.length,i.length);a1e3||i.indexOf("\n")>-1?r.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Gl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Gl.prototype.onKeyPress=function(){l&&s>=9&&(this.hasSelection=null),this.fastPoll()},Gl.prototype.onContextMenu=function(e){var t=this,r=t.cm,n=r.display,i=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=sn(r,e),u=n.scroller.scrollTop;if(o&&!h){r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(o)&&Zn(r,$i)(r.doc,xi(o),V);var c,f=i.style.cssText,d=t.wrapper.style.cssText,p=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-p.top-5)+"px; left: "+(e.clientX-p.left-5)+"px;\n z-index: 1000; background: "+(l?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",a&&(c=window.scrollY),n.input.focus(),a&&window.scrollTo(null,c),n.input.reset(),r.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=m,n.selForContextMenu=r.doc.sel,clearTimeout(n.detectingSelectAll),l&&s>=9&&v(),S){Se(e);var g=function(){pe(window,"mouseup",g),setTimeout(m,20)};fe(window,"mouseup",g)}else setTimeout(m,50)}function v(){if(null!=i.selectionStart){var e=r.somethingSelected(),o="​"+(e?i.value:"");i.value="⇚",i.value=o,t.prevInput=e?"":"​",i.selectionStart=1,i.selectionEnd=o.length,n.selForContextMenu=r.doc.sel}}function m(){if(t.contextMenuPending==m&&(t.contextMenuPending=!1,t.wrapper.style.cssText=d,i.style.cssText=f,l&&s<9&&n.scrollbars.setScrollTop(n.scroller.scrollTop=u),null!=i.selectionStart)){(!l||l&&s<9)&&v();var e=0,o=function(){n.selForContextMenu==r.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"​"==t.prevInput?Zn(r,no)(r):e++<10?n.detectingSelectAll=setTimeout(o,500):(n.selForContextMenu=null,n.input.reset())};n.detectingSelectAll=setTimeout(o,200)}}},Gl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e},Gl.prototype.setUneditable=function(){},Gl.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function r(r,n,i,o){e.defaults[r]=n,i&&(t[r]=o?function(e,t,r){r!=yl&&i(e,t,r)}:i)}e.defineOption=r,e.Init=yl,r("value","",function(e,t){return e.setValue(t)},!0),r("mode",null,function(e,t){e.doc.modeOption=t,Ti(e)},!0),r("indentUnit",2,Ti,!0),r("indentWithTabs",!1),r("smartIndent",!0),r("tabSize",4,function(e){Mi(e),Rr(e),un(e)},!0),r("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,r.push(et(n,o))}n++});for(var i=r.length-1;i>=0;i--)co(e.doc,t,r[i],et(r[i].line,r[i].ch+t.length))}}),r("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,r){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),r!=yl&&e.refresh()}),r("specialCharPlaceholder",Qt,function(e){return e.refresh()},!0),r("electricChars",!0),r("inputStyle",m?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),r("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),r("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),r("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),r("rtlMoveVisually",!w),r("wholeLineUpdateBefore",!0),r("theme","default",function(e){ml(e),fi(e)},!0),r("keyMap","default",function(e,t,r){var n=Xo(t),i=r!=yl&&Xo(r);i&&i.detach&&i.detach(e,n),n.attach&&n.attach(e,i||null)}),r("extraKeys",null),r("configureMouse",null),r("lineWrapping",!1,Cl,!0),r("gutters",[],function(e,t){e.display.gutterSpecs=ci(t,e.options.lineNumbers),fi(e)},!0),r("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?nn(e.display)+"px":"0",e.refresh()},!0),r("coverGutterNextToScrollbar",!1,function(e){return Rn(e)},!0),r("scrollbarStyle","native",function(e){Un(e),Rn(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),r("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ci(e.options.gutters,t),fi(e)},!0),r("firstLineNumber",1,fi,!0),r("lineNumberFormatter",function(e){return e},fi,!0),r("showCursorWhenSelecting",!1,pn,!0),r("resetSelectionOnContextMenu",!0),r("lineWiseCopyCut",!0),r("pasteLinesPerSelection",!0),r("selectionsMayTouch",!1),r("readOnly",!1,function(e,t){"nocursor"==t&&(Sn(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),r("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),r("dragDrop",!0,xl),r("allowDropFileTypes",null),r("cursorBlinkRate",530),r("cursorScrollMargin",0),r("cursorHeight",1,pn,!0),r("singleCursorHeightPerLine",!0,pn,!0),r("workTime",100),r("workDelay",100),r("flattenSpans",!0,Mi,!0),r("addModeClass",!1,Mi,!0),r("pollInterval",100),r("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),r("historyEventDelay",1250),r("viewportMargin",10,function(e){return e.refresh()},!0),r("maxHighlightLength",1e4,Mi,!0),r("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),r("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),r("autofocus",null),r("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),r("phrases",null)}(Sl),function(e){var t=e.optionHandlers,r=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,r){var n=this.options,i=n[e];n[e]==r&&"mode"!=e||(n[e]=r,t.hasOwnProperty(e)&&Zn(this,t[e])(this,r,i),ge(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Xo(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;rr&&(kl(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&On(this));else{var o=i.from(),l=i.to(),s=Math.max(r,o.line);r=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1;for(var a=s;a0&&Xi(this.doc,n,new bi(o,u[n].to()),V)}}}),getTokenAt:function(e,t){return yt(this,e,t)},getLineTokens:function(e,t){return yt(this,et(e),t,!0)},getTokenTypeAt:function(e){e=st(this.doc,e);var t,r=ft(this,Xe(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]o&&(e=o,i=!0),n=Xe(this.doc,e)}else n=e;return Vr(this,n,{top:0,left:0},t||"page",r||i).top+(i?this.doc.height-Vt(n):0)},defaultTextHeight:function(){return en(this.display)},defaultCharWidth:function(){return tn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o,l,s,a=this.display,u=(e=Xr(this,st(this.doc,e))).bottom,c=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),a.sizer.appendChild(t),"over"==n)u=e.top;else if("above"==n||"near"==n){var h=Math.max(a.wrapper.clientHeight,this.doc.height),f=Math.max(a.sizer.clientWidth,a.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>h)&&e.top>t.offsetHeight?u=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=h&&(u=e.bottom),c+t.offsetWidth>f&&(c=f-t.offsetWidth)}t.style.top=u+"px",t.style.left=t.style.right="","right"==i?(c=a.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?c=0:"middle"==i&&(c=(a.sizer.clientWidth-t.offsetWidth)/2),t.style.left=c+"px"),r&&(o=this,l={left:c,top:u,right:c+t.offsetWidth,bottom:u+t.offsetHeight},null!=(s=Mn(o,l)).scrollTop&&Hn(o,s.scrollTop),null!=s.scrollLeft&&Pn(o,s.scrollLeft))},triggerOnKeyDown:Qn(ll),triggerOnKeyPress:Qn(al),triggerOnKeyUp:sl,triggerOnMouseDown:Qn(fl),execCommand:function(e){if(Zo.hasOwnProperty(e))return Zo[e].call(null,this)},triggerElectric:Qn(function(e){Al(this,e)}),findPosH:function(e,t,r,n){var i=1;t<0&&(i=-1,t=-t);for(var o=st(this.doc,e),l=0;l0&&l(t.charAt(r-1));)--r;for(;n.5)&&ln(this),ge(this,"refresh",this)}),swapDoc:Qn(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Di(this,e),Rr(this),this.display.input.reset(),An(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,sr(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},be(e),e.registerHelper=function(t,n,i){r.hasOwnProperty(t)||(r[t]=e[t]={_global:[]}),r[t][n]=i},e.registerGlobalHelper=function(t,n,i,o){e.registerHelper(t,n,o),r[t]._global.push({pred:i,val:o})}}(Sl);var Ul="iter insert remove copy getEditor constructor".split(" ");for(var Vl in Mo.prototype)Mo.prototype.hasOwnProperty(Vl)&&B(Ul,Vl)<0&&(Sl.prototype[Vl]=function(e){return function(){return e.apply(this.doc,arguments)}}(Mo.prototype[Vl]));return be(Mo),Sl.inputStyles={textarea:Gl,contenteditable:El},Sl.defineMode=function(e){Sl.defaults.mode||"null"==e||(Sl.defaults.mode=e),function(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ee[e]=t}.apply(this,arguments)},Sl.defineMIME=function(e,t){Ie[e]=t},Sl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),Sl.defineMIME("text/plain","null"),Sl.defineExtension=function(e,t){Sl.prototype[e]=t},Sl.defineDocExtension=function(e,t){Mo.prototype[e]=t},Sl.fromTextArea=function(e,t){if((t=t?I(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var r=W();t.autofocus=r==e||null!=e.getAttribute("autofocus")&&r==document.body}function n(){e.value=s.getValue()}var i;if(e.form&&(fe(e.form,"submit",n),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var l=o.submit=function(){n(),o.submit=i,o.submit(),o.submit=l}}catch(e){}}t.finishInit=function(r){r.save=n,r.getTextArea=function(){return e},r.toTextArea=function(){r.toTextArea=isNaN,n(),e.parentNode.removeChild(r.getWrapperElement()),e.style.display="",e.form&&(pe(e.form,"submit",n),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=i))}},e.style.display="none";var s=Sl(function(t){return e.parentNode.insertBefore(t,e.nextSibling)},t);return s},function(e){e.off=pe,e.on=fe,e.wheelEventPixels=vi,e.Doc=Mo,e.splitLines=We,e.countColumn=z,e.findColumn=X,e.isWordChar=ee,e.Pass=U,e.signal=ge,e.Line=Xt,e.changeEnd=Ci,e.scrollbarModel=Gn,e.Pos=et,e.cmpPos=tt,e.modes=Ee,e.mimeModes=Ie,e.resolveMode=ze,e.getMode=Re,e.modeExtensions=Be,e.extendMode=Ge,e.copyState=Ue,e.startState=Ke,e.innerMode=Ve,e.commands=Zo,e.keyMap=Ro,e.keyName=jo,e.isModifierKey=Vo,e.lookupKey=Uo,e.normalizeKeyMap=Go,e.StringStream=je,e.SharedTextMarker=So,e.TextMarker=xo,e.LineWidget=yo,e.e_preventDefault=we,e.e_stopPropagation=xe,e.e_stop=Se,e.addClass=H,e.contains=D,e.rmClass=T,e.keyNames=Po}(Sl),Sl.version="5.49.2",Sl}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js new file mode 100755 index 000000000..4a5e499bf --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js @@ -0,0 +1 @@ +!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("yaml",function(){var e=new RegExp("\\b(("+["true","false","on","off","yes","no"].join(")|(")+"))$","i");return{token:function(i,t){var r=i.peek(),n=t.escaped;if(t.escaped=!1,"#"==r&&(0==i.pos||/\s/.test(i.string.charAt(i.pos-1))))return i.skipToEnd(),"comment";if(i.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(t.literal&&i.indentation()>t.keyCol)return i.skipToEnd(),"string";if(t.literal&&(t.literal=!1),i.sol()){if(t.keyCol=0,t.pair=!1,t.pairStart=!1,i.match(/---/))return"def";if(i.match(/\.\.\./))return"def";if(i.match(/\s*-\s+/))return"meta"}if(i.match(/^(\{|\}|\[|\])/))return"{"==r?t.inlinePairs++:"}"==r?t.inlinePairs--:"["==r?t.inlineList++:t.inlineList--,"meta";if(t.inlineList>0&&!n&&","==r)return i.next(),"meta";if(t.inlinePairs>0&&!n&&","==r)return t.keyCol=0,t.pair=!1,t.pairStart=!1,i.next(),"meta";if(t.pairStart){if(i.match(/^\s*(\||\>)\s*/))return t.literal=!0,"meta";if(i.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2";if(0==t.inlinePairs&&i.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(t.inlinePairs>0&&i.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(i.match(e))return"keyword"}return!t.pair&&i.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(t.pair=!0,t.keyCol=i.indentation(),"atom"):t.pair&&i.match(/^:\s*/)?(t.pairStart=!0,"meta"):(t.pairStart=!1,t.escaped="\\"==r,i.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}},lineComment:"#",fold:"indent"}}),e.defineMIME("text/x-yaml","yaml"),e.defineMIME("text/yaml","yaml")}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css new file mode 100755 index 000000000..6c708c010 --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css @@ -0,0 +1 @@ +.cm-s-dracula.CodeMirror,.cm-s-dracula .CodeMirror-gutters{background-color:#282a36 !important;color:#f8f8f2 !important;border:0}.cm-s-dracula .CodeMirror-gutters{color:#282a36}.cm-s-dracula .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-dracula .CodeMirror-linenumber{color:#6d8a88}.cm-s-dracula .CodeMirror-selected{background:rgba(255,255,255,0.10)}.cm-s-dracula .CodeMirror-line::selection,.cm-s-dracula .CodeMirror-line>span::selection,.cm-s-dracula .CodeMirror-line>span>span::selection{background:rgba(255,255,255,0.10)}.cm-s-dracula .CodeMirror-line::-moz-selection,.cm-s-dracula .CodeMirror-line>span::-moz-selection,.cm-s-dracula .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,0.10)}.cm-s-dracula span.cm-comment{color:#6272a4}.cm-s-dracula span.cm-string,.cm-s-dracula span.cm-string-2{color:#f1fa8c}.cm-s-dracula span.cm-number{color:#bd93f9}.cm-s-dracula span.cm-variable{color:#50fa7b}.cm-s-dracula span.cm-variable-2{color:white}.cm-s-dracula span.cm-def{color:#50fa7b}.cm-s-dracula span.cm-operator{color:#ff79c6}.cm-s-dracula span.cm-keyword{color:#ff79c6}.cm-s-dracula span.cm-atom{color:#bd93f9}.cm-s-dracula span.cm-meta{color:#f8f8f2}.cm-s-dracula span.cm-tag{color:#ff79c6}.cm-s-dracula span.cm-attribute{color:#50fa7b}.cm-s-dracula span.cm-qualifier{color:#50fa7b}.cm-s-dracula span.cm-property{color:#66d9ef}.cm-s-dracula span.cm-builtin{color:#50fa7b}.cm-s-dracula span.cm-variable-3,.cm-s-dracula span.cm-type{color:#ffb86c}.cm-s-dracula .CodeMirror-activeline-background{background:rgba(255,255,255,0.1)}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:white !important} diff --git a/luci-app-adguardhome/root/www/luci-static/resources/twin-bcrypt.min.js b/luci-app-adguardhome/root/www/luci-static/resources/twin-bcrypt.min.js new file mode 100755 index 000000000..6284357c6 --- /dev/null +++ b/luci-app-adguardhome/root/www/luci-static/resources/twin-bcrypt.min.js @@ -0,0 +1,7 @@ +/* @license + * Twin-Bcrypt 2.2.0 + * https://github.com/fpirsch/twin-bcrypt + * Licence: BSD-3-Clause + */ +!function(r,n){"use strict";function e(r){return y[g]=t.apply(n,r),g++}function t(r){var e=[].slice.call(arguments,1);return function(){"function"==typeof r?r.apply(n,e):new Function(""+r)()}}function o(r){if(m)setTimeout(t(o,r),0);else{var n=y[r];if(n){m=!0;try{n()}finally{a(r),m=!1}}}}function a(r){delete y[r]}function i(){p=function(){var r=e(arguments);return process.nextTick(t(o,r)),r}}function u(){if(r.postMessage&&!r.importScripts){var n=!0,e=r.onmessage;return r.onmessage=function(){n=!1},r.postMessage("","*"),r.onmessage=e,n}}function f(){var n="setImmediate$"+Math.random()+"$",t=function(e){e.source===r&&"string"==typeof e.data&&0===e.data.indexOf(n)&&o(+e.data.slice(n.length))};r.addEventListener?r.addEventListener("message",t,!1):r.attachEvent("onmessage",t),p=function(){var t=e(arguments);return r.postMessage(n+t,"*"),t}}function c(){var r=new MessageChannel;r.port1.onmessage=function(r){var n=r.data;o(n)},p=function(){var n=e(arguments);return r.port2.postMessage(n),n}}function s(){var r=v.documentElement;p=function(){var n=e(arguments),t=v.createElement("script");return t.onreadystatechange=function(){o(n),t.onreadystatechange=null,r.removeChild(t),t=null},r.appendChild(t),n}}function l(){p=function(){var r=e(arguments);return setTimeout(t(o,r),0),r}}if(!r.setImmediate){var p,g=1,y={},m=!1,v=r.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(r);d=d&&d.setTimeout?d:r,"[object process]"==={}.toString.call(r.process)?i():u()?f():r.MessageChannel?c():v&&"onreadystatechange"in v.createElement("script")?s():l(),d.setImmediate=p,d.clearImmediate=a}}(new Function("return this")()),function(r){"object"==typeof exports?r(exports,require("crypto")):r(self.TwinBcrypt={},self.crypto||self.msCrypto)}(function(r,n){"use strict";function e(r){for(var n=unescape(encodeURIComponent(r)),e=n.length,t=new Array(e),o=0;e>o;o++)t[o]=n.charCodeAt(o);return t}function t(r){for(var n=r.length,e=new Array(n),t=0;n>t;t++)e[t]=r.charCodeAt(t);return e}function o(r,n){for(var e,t,o=0,a="";n>o;){if(e=255&r[o++],a+=B[e>>2],e=(3&e)<<4,o>=n){a+=B[e];break}if(t=255&r[o++],e|=t>>4,a+=B[e],e=(15&t)<<2,o>=n){a+=B[e];break}t=255&r[o++],e|=t>>6,a+=B[e],a+=B[63&t]}return a}function a(r){for(var n,e,t=new Array(16),o=0,a=0;;){if(n=D[r.charCodeAt(o++)-46],e=D[r.charCodeAt(o++)-46],t[a++]=255&(n<<2|e>>4),22===o)break;n=e<<4,e=D[r.charCodeAt(o++)-46],t[a++]=255&(n|e>>2),n=e<<6,e=D[r.charCodeAt(o++)-46],t[a++]=255&(n|e)}return t}function i(r){for(var n=r.length,e=new Array(72),t=0,o=0;72>o;)e[o++]=r[t++],t===n&&(t=0);return e}function u(r,n,e){for(var t=0,o=e>>2;tt;)r[n++]=e[t++]<<24|e[t++]<<16|e[t++]<<8|e[t++]}function c(r){function n(n){for(var e=r,t=G>>2,o=t|O,f=n>>2,c=e[f]^e[t],s=e[1|f];o>t;)s^=(e[c>>>24]+e[a|c>>>16&255]^e[i|c>>>8&255])+e[u|255&c]^e[++t],c^=(e[s>>>24]+e[a|s>>>16&255]^e[i|s>>>8&255])+e[u|255&s]^e[++t];e[f]=s^e[S>>2],e[1|f]=c}function e(n){var e;for(r[L>>2]=0,r[L+4>>2]=0,e=0;M>e;e++)r[G>>2|e]^=r[(n>>2)+e];var t,o,f,c,s,l=r;for(e=0;M>e;e+=2){for(t=G>>2,o=t|O,f=L>>2,c=l[f]^l[t],s=l[1|f];o>t;)s^=(l[c>>>24]+l[a|c>>>16&255]^l[i|c>>>8&255])+l[u|255&c]^l[++t],c^=(l[s>>>24]+l[a|s>>>16&255]^l[i|s>>>8&255])+l[u|255&s]^l[++t];l[f]=s^l[S>>2],l[1|f]=c,r[G>>2|e]=l[f],r[G>>2|e+1]=c}for(e=0;T>e;e+=2){for(t=G>>2,o=t|O,f=L>>2,c=l[f]^l[t],s=l[1|f];o>t;)s^=(l[c>>>24]+l[a|c>>>16&255]^l[i|c>>>8&255])+l[u|255&c]^l[++t],c^=(l[s>>>24]+l[a|s>>>16&255]^l[i|s>>>8&255])+l[u|255&s]^l[++t];l[f]=s^l[S>>2],l[1|f]=c,r[e]=l[f],r[1|e]=c}}function t(r,n,t){for(var o=0;t>=o&&!(r>n);o++)e(R),e(j),r++;return r}var o=k>>2,a=o+256|0,i=a+256|0,u=i+256|0;return{encrypt:n,expandLoop:t}}function s(stdlib, foreign, heap) {"use asm";var HEAP32=new stdlib.Uint32Array(heap);var BLOWFISH_NUM_ROUNDS=16;var S_offset=0x0000;var S1_offset=0x0400;var S2_offset=0x0800;var S3_offset=0x0C00;var P_offset=0x1000;var P_last_offset=0x1044;var crypt_ciphertext_offset=0x1048;var LR_offset=0x01060;var password_offset=0x1068;var salt_offset=0x10b0;var P_LEN=18;var S_LEN=1024;function encrypt(offset) {offset=offset|0;var i=0;var n=0;var L=0;var R=0;var imax=0;imax=P_offset|BLOWFISH_NUM_ROUNDS<<2;L=HEAP32[offset>>2]|0;R=HEAP32[offset+4>>2]|0;L=L^HEAP32[P_offset>>2];for (i=P_offset; (i|0)<(imax|0);) {i=(i+4)>>>0;R=R^(((HEAP32[(L>>>22)>>2]>>>0) +(HEAP32[(S1_offset|(L>>>14&0x3ff))>>2]>>>0) ^(HEAP32[(S2_offset|(L>>>6&0x3ff))>>2])) +(HEAP32[(S3_offset|(L<<2&0x3ff))>>2]>>>0))^HEAP32[i>>2];i=(i+4)>>>0;L=L^(((HEAP32[(R>>>22)>>2]>>>0) +(HEAP32[(S1_offset|(R>>>14&0x3ff))>>2]>>>0) ^(HEAP32[(S2_offset|(R>>>6&0x3ff))>>2])) +(HEAP32[(S3_offset|(R<<2&0x3ff))>>2]>>>0))^HEAP32[i>>2];}HEAP32[offset>>2]=R^HEAP32[P_last_offset>>2];HEAP32[(offset+4)>>2]=L;}function expandKey(offset) {offset=offset|0;var i=0;var off=0;off=P_offset|0;for (i=0; (i|0)<(P_LEN|0); i=(i+1)|0) {HEAP32[off>>2]=HEAP32[off>>2]^HEAP32[offset>>2];offset=(offset+4)|0;off=(off+4)|0;}HEAP32[LR_offset>>2]=0;HEAP32[LR_offset+4>>2]=0;off=P_offset;for (i=0; (i|0)<(P_LEN|0); i=(i+2)|0) {encrypt(LR_offset);HEAP32[off>>2]=HEAP32[LR_offset>>2];HEAP32[off+4>>2]=HEAP32[LR_offset+4>>2];off=(off+8)|0;}off=S_offset;for (i=0; (i|0)<(S_LEN|0); i=(i+2)|0) {encrypt(LR_offset);HEAP32[off>>2]=HEAP32[LR_offset>>2];HEAP32[off+4>>2]=HEAP32[LR_offset+4>>2];off=(off+8)|0;}}function expandLoop(i, counterEnd, maxIterations) {i=i|0;counterEnd=counterEnd|0;maxIterations=maxIterations|0;var j=0;for (j=0; (j|0) <= (maxIterations|0); j=(j+1)|0) {if ((i>>>0)>(counterEnd>>>0)) break;expandKey(password_offset);expandKey(salt_offset);i=(i+1)>>>0;}return i|0;}return {encrypt: encrypt,expandLoop: expandLoop};} +function l(r,n,e,t){var o,a,i,u=L>>2,f=u+1;for(t[u]=0,t[f]=0,a=0,o=0;M>o;o++)i=n[a++]<<24|n[a++]<<16|n[a++]<<8|n[a++],t[G>>2|o]^=i;for(a=0,o=0;M>o;o+=2)i=r[a++]<<24|r[a++]<<16|r[a++]<<8|r[a++],a&=65295,t[u]^=i,i=r[a++]<<24|r[a++]<<16|r[a++]<<8|r[a++],a&=65295,t[f]^=i,e.encrypt(L),t[G>>2|o]=t[u],t[G>>2|o+1]=t[f];var c=k>>2;for(o=0;T>o;o+=2)i=r[a++]<<24|r[a++]<<16|r[a++]<<8|r[a++],a&=65295,t[u]^=i,i=r[a++]<<24|r[a++]<<16|r[a++]<<8|r[a++],a&=65295,t[f]^=i,e.encrypt(L),t[c|o]=t[u],t[c|o+1]=t[f]}function p(r,n,e,t,o,a,i){for(var u=e;t>=u;){if(u=r.expandLoop(u,t,o),a){var f=a(u/(t+1));if(f===!1)return}if(u>t){if(i)return void setImmediate(g.bind(null,r,n,i));return}if(i)return void setImmediate(p.bind(null,r,n,u,t,o,a,i))}}function g(r,n,e){u(n,x,F);var t;for(t=0;64>t;t++)r.encrypt(F+0),r.encrypt(F+8),r.encrypt(F+16);var o,a=0,i=x.length,f=new Array(4*i);for(t=0;i>t;t++)o=n[(F>>2)+t],f[a++]=o>>24,f[a++]=o>>16&255,f[a++]=o>>8&255,f[a++]=255&o;return e&&e(f),f}function y(r,n){return r+o(n,23)}function m(n,o,m,v){var d,h=o.substr(0,29),w=+o.substr(4,2),A=o.substr(7,22);if("string"==typeof n)d=r.encodingMode===r.ENCODING_UTF8?e(n):t(n);else if(Array.isArray(n))d=n.map(function(r){return 255&r});else{if(!(n instanceof Uint8Array))throw new Error("Incorrect arguments");d=Array.prototype.slice.call(n)}d.push(0);var b,E,N=a(A,C),O=31>w?1<>2,N),f(b,R>>2,d),l(N,d,E,b),v?void p(E,b,0,M,T,m,function(r){v(y(h,r))}):(p(E,b,0,M,T,m),y(h,g(E,b)))}function v(r){if(!b)throw new Error("No cryptographically secure pseudorandom number generator available.");if(null==r&&(r=N),r=0|+r,isNaN(r)||4>r||r>31)throw new Error("Invalid cost parameter.");var n="$2y$";return 10>r&&(n+="0"),n+=r+"$",n+=o(b(C),C)}function d(r,n,e){if(n&&"number"!=typeof n){if("string"!=typeof n||!z.test(n))throw new Error("Invalid salt")}else n=v(n);return m(r,n,e)}function h(r,n,e,t){if(arguments.length<2)throw new Error("Incorrect arguments");if(2===arguments.length?(t=n,n=e=null):3===arguments.length&&(t=e,e=null,"function"==typeof n&&(e=n,n=null)),n&&"number"!=typeof n){if("string"!=typeof n||!z.test(n))throw new Error("Invalid salt")}else n=v(n);if(!t||"function"!=typeof t)throw new Error("No callback function was given.");m(r,n,e,t)}function w(r,n){if("string"!=typeof n||!Z.test(n))throw new Error("Incorrect arguments");var e=n.substr(0,n.length-31),t=d(r,e);return t===n}function A(r,n,e,t){if("string"!=typeof n||!Z.test(n))throw new Error("Incorrect arguments");if(t||(t=e,e=null),!t||"function"!=typeof t)throw new Error("No callback function was given.");var o=n.substr(0,n.length-31);h(r,o,e,function(r){t(r===n)})}var b,E="undefined"!=typeof InstallTrigger,I=E;n&&(b=n.randomBytes,n.getRandomValues&&(b=function(r){var e=new Uint8Array(r);return n.getRandomValues(e)}));var C=16,N=10,O=16,$=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731],U=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946,1266315497,3048417604,3681880366,3289982499,290971e4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168,2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409e3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],M=$.length,T=U.length,x=[1332899944,1700884034,1701343084,1684370003,1668446532,1869963892],k=0,G=4096,S=4164,F=4168,L=4192,R=4200,j=4272,B="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",D=[0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,-1,-1,-1,-1,-1],z=/^\$2[ay]\$(0[4-9]|[12][0-9]|3[01])\$[.\/A-Za-z0-9]{21}[.Oeu]/,Z=/^\$2[ay]\$(0[4-9]|[12][0-9]|3[01])\$[.\/A-Za-z0-9]{21}[.Oeu][.\/A-Za-z0-9]{30}[.CGKOSWaeimquy26]$/;r.genSalt=v,r.hashSync=d,r.hash=h,r.compareSync=w,r.compare=A,r.ENCODING_UTF8=0,r.ENCODING_RAW=1,r.encodingMode=r.ENCODING_UTF8,r.cryptoRNG=!!b,r.randomBytes=b,r.defaultCost=N,r.version="2.2.0"}); \ No newline at end of file diff --git a/luci-app-cpufreq/Makefile b/luci-app-cpufreq/Makefile new file mode 100755 index 000000000..b85e91d22 --- /dev/null +++ b/luci-app-cpufreq/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI for CPU Freq Setting +LUCI_DEPENDS:=@(arm||aarch64) + +PKG_NAME:=luci-app-cpufreq +PKG_VERSION:=1 +PKG_RELEASE:=$(COMMITCOUNT) + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-cpufreq/luasrc/controller/cpufreq.lua b/luci-app-cpufreq/luasrc/controller/cpufreq.lua new file mode 100755 index 000000000..2bf7a5686 --- /dev/null +++ b/luci-app-cpufreq/luasrc/controller/cpufreq.lua @@ -0,0 +1,11 @@ +module("luci.controller.cpufreq", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/cpufreq") then + return + end + + local page = entry({"admin", "system", "cpufreq"}, cbi("cpufreq"), _("CPU Freq"), 90) + page.dependent = false + page.acl_depends = { "luci-app-cpufreq" } +end diff --git a/luci-app-cpufreq/luasrc/model/cbi/cpufreq.lua b/luci-app-cpufreq/luasrc/model/cbi/cpufreq.lua new file mode 100755 index 000000000..febb7ad90 --- /dev/null +++ b/luci-app-cpufreq/luasrc/model/cbi/cpufreq.lua @@ -0,0 +1,68 @@ +local fs = require "nixio.fs" + +function string.split(input, delimiter) + input = tostring(input) + delimiter = tostring(delimiter) + if (delimiter=='') then return false end + local pos,arr = 0, {} + for st,sp in function() return string.find(input, delimiter, pos, true) end do + table.insert(arr, string.sub(input, pos, st - 1)) + pos = sp + 1 + end + table.insert(arr, string.sub(input, pos)) + return arr +end + +mp = Map("cpufreq", translate("CPU Freq Settings")) +mp.description = translate("Set CPU Scaling Governor to Max Performance or Balance Mode") + +s = mp:section(NamedSection, "cpufreq", "settings") +s.anonymouse = true + +local policy_nums = luci.sys.exec("echo -n $(find /sys/devices/system/cpu/cpufreq/policy* -maxdepth 0 | grep -Eo '[0-9]+')") +for _, policy_num in ipairs(string.split(policy_nums, " ")) do + if not fs.access("/sys/devices/system/cpu/cpufreq/policy" .. policy_num .. "/scaling_available_frequencies") then return end + + cpu_freqs = fs.readfile("/sys/devices/system/cpu/cpufreq/policy" .. policy_num .. "/scaling_available_frequencies") + cpu_freqs = string.sub(cpu_freqs, 1, -3) + + cpu_governors = fs.readfile("/sys/devices/system/cpu/cpufreq/policy" .. policy_num .. "/scaling_available_governors") + cpu_governors = string.sub(cpu_governors, 1, -3) + + + freq_array = string.split(cpu_freqs, " ") + governor_array = string.split(cpu_governors, " ") + + s:tab(policy_num, translate("Policy " .. policy_num)) + + governor = s:taboption(policy_num, ListValue, "governor" .. policy_num, translate("CPU Scaling Governor")) + for _, e in ipairs(governor_array) do + if e ~= "" then governor:value(e, translate(e, string.upper(e))) end + end + + minfreq = s:taboption(policy_num, ListValue, "minfreq" .. policy_num, translate("Min Idle CPU Freq")) + for _, e in ipairs(freq_array) do + if e ~= "" then minfreq:value(e) end + end + + maxfreq = s:taboption(policy_num, ListValue, "maxfreq" .. policy_num, translate("Max Turbo Boost CPU Freq")) + for _, e in ipairs(freq_array) do + if e ~= "" then maxfreq:value(e) end + end + + sdfactor = s:taboption(policy_num, Value, "sdfactor" .. policy_num, translate("CPU Switching Sampling rate")) + sdfactor.datatype="range(1,100000)" + sdfactor.description = translate("The sampling rate determines how frequently the governor checks to tune the CPU (ms)") + sdfactor.placeholder = 10 + sdfactor.default = 10 + sdfactor:depends("governor" .. policy_num, "ondemand") + + upthreshold = s:taboption(policy_num, Value, "upthreshold" .. policy_num, translate("CPU Switching Threshold")) + upthreshold.datatype="range(1,99)" + upthreshold.description = translate("Kernel make a decision on whether it should increase the frequency (%)") + upthreshold.placeholder = 50 + upthreshold.default = 50 + upthreshold:depends("governor" .. policy_num, "ondemand") +end + +return mp diff --git a/luci-app-cpufreq/po/zh-cn/cpufreq.po b/luci-app-cpufreq/po/zh-cn/cpufreq.po new file mode 100755 index 000000000..bd818d774 --- /dev/null +++ b/luci-app-cpufreq/po/zh-cn/cpufreq.po @@ -0,0 +1,32 @@ +msgid "CPU Freq" +msgstr "CPU 性能优化调节" + +msgid "CPU Freq Settings" +msgstr "CPU 性能优化调节设置" + +msgid "Set CPU Scaling Governor to Max Performance or Balance Mode" +msgstr "设置路由器的 CPU 性能模式(高性能/均衡省电)" + +msgid "CPU Scaling Governor" +msgstr "CPU 工作模式" + +msgid "CPU Freq from 48000 to 716000 (Khz)" +msgstr "CPU 频率范围为 48000 到 716000 (Khz)" + +msgid "Min Idle CPU Freq" +msgstr "待机 CPU 最小频率" + +msgid "Max Turbo Boost CPU Freq" +msgstr "最大 Turbo Boost CPU 频率" + +msgid "CPU Switching Sampling rate" +msgstr "CPU 切换周期" + +msgid "The sampling rate determines how frequently the governor checks to tune the CPU (ms)" +msgstr "CPU 检查切换的周期 (ms)。注意:过于频繁的切换频率会引起网络延迟抖动" + +msgid "CPU Switching Threshold" +msgstr "CPU 切换频率触发阈值" + +msgid "Kernel make a decision on whether it should increase the frequency (%)" +msgstr "当 CPU 占用率超过 (%) 的情况下触发内核切换频率" diff --git a/luci-app-cpufreq/root/etc/config/cpufreq b/luci-app-cpufreq/root/etc/config/cpufreq new file mode 100755 index 000000000..5c2c070e9 --- /dev/null +++ b/luci-app-cpufreq/root/etc/config/cpufreq @@ -0,0 +1,3 @@ + +config settings 'cpufreq' + diff --git a/luci-app-cpufreq/root/etc/init.d/cpufreq b/luci-app-cpufreq/root/etc/init.d/cpufreq new file mode 100755 index 000000000..4dda93bc7 --- /dev/null +++ b/luci-app-cpufreq/root/etc/init.d/cpufreq @@ -0,0 +1,27 @@ +#!/bin/sh /etc/rc.common +START=15 + +NAME="cpufreq" + +config_get_cpufreq() +{ + config_get "$NAME" "$1" +} + +start() +{ + config_load "$NAME" + + for i in $(find /sys/devices/system/cpu/cpufreq/policy* -maxdepth 0 | grep -Eo '[0-9]+') + do + [ -z "$(config_get_cpufreq "governor$i")" ] && return + + config_get_cpufreq "governor$i" > "/sys/devices/system/cpu/cpufreq/policy$i/scaling_governor" + config_get_cpufreq "minfreq$i" > "/sys/devices/system/cpu/cpufreq/policy$i/scaling_min_freq" + config_get_cpufreq "maxfreq$i" > "/sys/devices/system/cpu/cpufreq/policy$i/scaling_max_freq" + if [ "$(config_get_cpufreq "governor$i")" = "ondemand" ]; then + config_get_cpufreq "sdfactor$i" > "/sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor" + config_get_cpufreq "upthreshold$i" > "/sys/devices/system/cpu/cpufreq/ondemand/up_threshold" + fi + done +} diff --git a/luci-app-cpufreq/root/etc/uci-defaults/10-cpufreq b/luci-app-cpufreq/root/etc/uci-defaults/10-cpufreq new file mode 100755 index 000000000..4ad31dd5f --- /dev/null +++ b/luci-app-cpufreq/root/etc/uci-defaults/10-cpufreq @@ -0,0 +1,104 @@ +#!/bin/sh + +uci_write_config() { + uci -q set cpufreq.cpufreq.governor$1="$2" + uci -q set cpufreq.cpufreq.minfreq$1="$3" + uci -q set cpufreq.cpufreq.maxfreq$1="$4" + [ -n "$5" ] && uci -q set cpufreq.cpufreq.sdfactor$1="$5" + [ -n "$6" ] && uci -q set cpufreq.cpufreq.upthreshold$1="$6" + uci -q commit cpufreq +} + +CPU_FREQS="$(cat '/sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies')" +CPU_POLICYS="$(find '/sys/devices/system/cpu/cpufreq/policy'* -maxdepth 0 | grep -Eo '[0-9]+')" +source "/etc/openwrt_release" +case "$DISTRIB_TARGET" in + "bcm27xx/bcm2710") + uci_write_config 0 ondemand 600000 1200000 10 50 + ;; + "bcm27xx/bcm2711") + uci_write_config 0 ondemand 600000 1500000 10 50 + ;; + "ipq40xx/generic") + uci_write_config 0 ondemand 200000 716000 10 50 + ;; + "ipq60xx/generic") + if echo "$CPU_FREQS" | grep -q "1800000"; then + # IPQ6010/18/28 + CPU_MAX_FREQ="1800000" + else + # IPQ6000 + CPU_MAX_FREQ="1200000" + fi + uci_write_config 0 ondemand 864000 $CPU_MAX_FREQ 10 50 + ;; + "ipq806x/generic") + if echo "$CPU_FREQS" | grep -q "1725000"; then + # IPQ8065 + CPU_MAX_FREQ="1725000" + elif echo "$CPU_FREQS" | grep -q "1400000"; then + # IPQ8064 + CPU_MAX_FREQ="1400000" + else + # IPQ8062 + CPU_MAX_FREQ="1000000" + fi + uci_write_config 0 ondemand 600000 $CPU_MAX_FREQ 10 50 + # IPQ8064/5 + echo "$CPU_POLICYS" | grep -q "1" && uci_write_config 1 ondemand 600000 1200000 10 50 + ;; + "ipq807x/generic") + if echo "$CPU_FREQS" | grep -q "2208000"; then + # IPQ8072/4/6/8A + CPU_MAX_FREQ="2208000" + else + # IPQ8071A + CPU_MAX_FREQ="1382400" + fi + uci_write_config 0 ondemand 1017600 $CPU_MAX_FREQ 10 50 + ;; + "mediatek/mt7622") + uci_write_config 0 ondemand 600000 1350000 10 50 + ;; + "meson/meson8b") + uci_write_config 0 schedutil 816000 1536000 + ;; + "rockchip/armv8") + if echo "$CPU_POLICYS" | grep -q "4"; then + # RK3399 + uci_write_config 0 schedutil 600000 1608000 + uci_write_config 4 schedutil 600000 2016000 + else + if echo "$CPU_FREQS" | grep -q "1992000"; then + # RK3568 + CPU_MAX_FREQ="1992000" + elif echo "$CPU_FREQS" | grep -q "1800000"; then + # RK3566 + CPU_MAX_FREQ="1800000" + else + # RK3328 + CPU_MAX_FREQ="1512000" + fi + uci_write_config 0 schedutil 816000 $CPU_MAX_FREQ + fi + ;; + "sunxi/cortexa53") + if echo "$CPU_FREQS" | grep -q "1800000"; then + # H6 + uci_write_config 0 schedutil 816000 1800000 + else + # H5 + uci_write_config 0 ondemand 648000 1200000 10 50 + fi + ;; +esac + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@cpufreq[-1] + add ucitrack cpufreq + set ucitrack.@cpufreq[-1].init=cpufreq + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/luci-app-cpufreq/root/usr/share/rpcd/acl.d/luci-app-cpufreq.json b/luci-app-cpufreq/root/usr/share/rpcd/acl.d/luci-app-cpufreq.json new file mode 100755 index 000000000..fae58ae40 --- /dev/null +++ b/luci-app-cpufreq/root/usr/share/rpcd/acl.d/luci-app-cpufreq.json @@ -0,0 +1,11 @@ +{ + "luci-app-cpufreq": { + "description": "Grant UCI access for luci-app-cpufreq", + "read": { + "uci": [ "cpufreq" ] + }, + "write": { + "uci": [ "cpufreq" ] + } + } +} diff --git a/luci-app-diskman/Makefile b/luci-app-diskman/Makefile new file mode 100755 index 000000000..fa6c46357 --- /dev/null +++ b/luci-app-diskman/Makefile @@ -0,0 +1,51 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-diskman + +PKG_MAINTAINER:=lisaac +PKG_LICENSE:=AGPL-3.0 + +LUCI_TITLE:=Disk Manager interface for LuCI +LUCI_DEPENDS:=+blkid +e2fsprogs +parted +smartmontools \ + +PACKAGE_$(PKG_NAME)_INCLUDE_btrfs_progs:btrfs-progs \ + +PACKAGE_$(PKG_NAME)_INCLUDE_lsblk:lsblk \ + +PACKAGE_$(PKG_NAME)_INCLUDE_mdadm:mdadm \ + +PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_raid456:mdadm \ + +PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_raid456:kmod-md-raid456 \ + +PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_linears:mdadm \ + +PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_linears:kmod-md-linear + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME)/config +config PACKAGE_$(PKG_NAME)_INCLUDE_btrfs_progs + bool "Include btrfs-progs" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_lsblk + bool "Include lsblk" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_mdadm + bool "Include mdadm" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_raid456 + depends on PACKAGE_$(PKG_NAME)_INCLUDE_mdadm + bool "Include kmod-md-raid456" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_kmod_md_linear + depends on PACKAGE_$(PKG_NAME)_INCLUDE_mdadm + bool "Include kmod-md-linear" + default n +endef + +define Package/$(PKG_NAME)/postinst +#!/bin/sh +rm -fr /tmp/luci-indexcache /tmp/luci-modulecache +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-diskman/luasrc/controller/diskman.lua b/luci-app-diskman/luasrc/controller/diskman.lua new file mode 100755 index 000000000..258120430 --- /dev/null +++ b/luci-app-diskman/luasrc/controller/diskman.lua @@ -0,0 +1,155 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" +module("luci.controller.diskman",package.seeall) + +function index() + -- check all used executables in disk management are existed + local CMD = {"parted", "blkid", "smartctl"} + local executables_all_existed = true + for _, cmd in ipairs(CMD) do + local command = luci.sys.exec("/usr/bin/which " .. cmd) + if not command:match(cmd) then + executables_all_existed = false + break + end + end + + if not executables_all_existed then return end + -- entry(path, target, title, order) + -- set leaf attr to true to pass argument throughe url (e.g. admin/system/disk/partition/sda) + entry({"admin", "system", "diskman"}, alias("admin", "system", "diskman", "disks"), _("Disk Man"), 55) + entry({"admin", "system", "diskman", "disks"}, form("diskman/disks"), nil).leaf = true + entry({"admin", "system", "diskman", "partition"}, form("diskman/partition"), nil).leaf = true + entry({"admin", "system", "diskman", "btrfs"}, form("diskman/btrfs"), nil).leaf = true + entry({"admin", "system", "diskman", "format_partition"}, call("format_partition"), nil).leaf = true + entry({"admin", "system", "diskman", "get_disk_info"}, call("get_disk_info"), nil).leaf = true + entry({"admin", "system", "diskman", "mk_p_table"}, call("mk_p_table"), nil).leaf = true + entry({"admin", "system", "diskman", "smartdetail"}, call("smart_detail"), nil).leaf = true + entry({"admin", "system", "diskman", "smartattr"}, call("smart_attr"), nil).leaf = true +end + +function format_partition() + local partation_name = luci.http.formvalue("partation_name") + local fs = luci.http.formvalue("file_system") + if not partation_name then + luci.http.status(500, "Partition NOT found!") + luci.http.write_json("Partition NOT found!") + return + elseif not nixio.fs.access("/dev/"..partation_name) then + luci.http.status(500, "Partition NOT found!") + luci.http.write_json("Partition NOT found!") + return + elseif not fs then + luci.http.status(500, "no file system") + luci.http.write_json("no file system") + return + end + local dm = require "luci.model.diskman" + code, msg = dm.format_partition(partation_name, fs) + luci.http.status(code, msg) + luci.http.write_json(msg) +end + +function get_disk_info(dev) + if not dev then + luci.http.status(500, "no device") + luci.http.write_json("no device") + return + elseif not nixio.fs.access("/dev/"..dev) then + luci.http.status(500, "no device") + luci.http.write_json("no device") + return + end + local dm = require "luci.model.diskman" + local device_info = dm.get_disk_info(dev) + luci.http.status(200, "ok") + luci.http.prepare_content("application/json") + luci.http.write_json(device_info) +end + +function mk_p_table() + local p_table = luci.http.formvalue("p_table") + local dev = luci.http.formvalue("dev") + if not dev then + luci.http.status(500, "no device") + luci.http.write_json("no device") + return + elseif not nixio.fs.access("/dev/"..dev) then + luci.http.status(500, "no device") + luci.http.write_json("no device") + return + end + local dm = require "luci.model.diskman" + if p_table == "GPT" or p_table == "MBR" then + p_table = p_table == "MBR" and "msdos" or "gpt" + local res = luci.sys.call(dm.command.parted .. " -s /dev/" .. dev .. " mktable ".. p_table) + if res == 0 then + luci.http.status(200, "ok") + else + luci.http.status(500, "command exec error") + end + luci.http.prepare_content("application/json") + luci.http.write_json({code=res}) + else + luci.http.status(404, "not support") + luci.http.prepare_content("application/json") + luci.http.write_json({code="1"}) + end +end + +function smart_detail(dev) + luci.template.render("diskman/smart_detail", {dev=dev}) +end + +function smart_attr(dev) + local dm = require "luci.model.diskman" + local cmd = io.popen(dm.command.smartctl .. " -H -A -i /dev/%s" % dev) + if cmd then + local attr = { } + if cmd:match("NVMe Version:")then + while true do + local ln = cmd:read("*l") + if not ln then + break + elseif ln:match("^(.-):%s+(.+)") then + local key, value = ln:match("^(.-):%s+(.+)") + attr[#attr+1]= { + key = key, + value = value + } + end + end + else + while true do + local ln = cmd:read("*l") + if not ln then + break + elseif ln:match("^.*%d+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+%s+.+") then + local id,attrbute,flag,value,worst,thresh,type,updated,raw = ln:match("^%s*(%d+)%s+([%a%p]+)%s+(%w+)%s+(%d+)%s+(%d+)%s+(%d+)%s+([%a%p]+)%s+(%a+)%s+[%w%p]+%s+(.+)") + id= "%x" % id + if not id:match("^%w%w") then + id = "0%s" % id + end + attr[#attr+1]= { + id = id:upper(), + attrbute = attrbute, + flag = flag, + value = value, + worst = worst, + thresh = thresh, + type = type, + updated = updated, + raw = raw + } + end + end + end + cmd:close() + luci.http.prepare_content("application/json") + luci.http.write_json(attr) + end +end diff --git a/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua b/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua new file mode 100755 index 000000000..006007853 --- /dev/null +++ b/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua @@ -0,0 +1,210 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" +require("luci.tools.webadmin") +local dm = require "luci.model.diskman" +local uuid = arg[1] + +if not uuid then luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) end + +-- mount subv=/ to tempfs +mount_point = "/tmp/.btrfs_tmp" +nixio.fs.mkdirr(mount_point) +luci.util.exec(dm.command.umount .. " "..mount_point .. " >/dev/null 2>&1") +luci.util.exec(dm.command.mount .. " -t btrfs -o subvol=/ UUID="..uuid.." "..mount_point) + +m = SimpleForm("btrfs", translate("Btrfs"), translate("Manage Btrfs")) +m.template = "diskman/cbi/xsimpleform" +m.redirect = luci.dispatcher.build_url("admin/system/diskman") +m.submit = false +m.reset = false + +-- info +local btrfs_info = dm.get_btrfs_info(mount_point) +local table_btrfs_info = m:section(Table, {btrfs_info}, translate("Btrfs Info")) +table_btrfs_info:option(DummyValue, "uuid", translate("UUID")) +table_btrfs_info:option(DummyValue, "members", translate("Members")) +table_btrfs_info:option(DummyValue, "data_raid_level", translate("Data")) +table_btrfs_info:option(DummyValue, "metadata_raid_lavel", translate("Metadata")) +table_btrfs_info:option(DummyValue, "size_formated", translate("Size")) +table_btrfs_info:option(DummyValue, "used_formated", translate("Used")) +table_btrfs_info:option(DummyValue, "free_formated", translate("Free Space")) +table_btrfs_info:option(DummyValue, "usage", translate("Usage")) +local v_btrfs_label = table_btrfs_info:option(Value, "label", translate("Label")) +local value_btrfs_label = "" +v_btrfs_label.write = function(self, section, value) + value_btrfs_label = value or "" +end +local btn_update_label = table_btrfs_info:option(Button, "_update_label") +btn_update_label.inputtitle = translate("Update") +btn_update_label.inputstyle = "edit" +btn_update_label.write = function(self, section, value) + local cmd = dm.command.btrfs .. " filesystem label " .. mount_point .. " " .. value_btrfs_label + local res = luci.util.exec(cmd) + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid)) +end +-- subvolume +local subvolume_list = dm.get_btrfs_subv(mount_point) +subvolume_list["_"] = { ID = 0 } +table_subvolume = m:section(Table, subvolume_list, translate("SubVolumes")) +table_subvolume:option(DummyValue, "id", translate("ID")) +table_subvolume:option(DummyValue, "top_level", translate("Top Level")) +table_subvolume:option(DummyValue, "uuid", translate("UUID")) +table_subvolume:option(DummyValue, "otime", translate("Otime")) +table_subvolume:option(DummyValue, "snapshots", translate("Snapshots")) +local v_path = table_subvolume:option(Value, "path", translate("Path")) +v_path.forcewrite = true +v_path.render = function(self, section, scope) + if subvolume_list[section].ID == 0 then + self.template = "cbi/value" + self.placeholder = "/my_subvolume" + self.forcewrite = true + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end +end +local value_path +v_path.write = function(self, section, value) + value_path = value +end +local btn_set_default = table_subvolume:option(Button, "_subv_set_default", translate("Set Default")) +btn_set_default.forcewrite = true +btn_set_default.inputstyle = "edit" +btn_set_default.template = "diskman/cbi/disabled_button" +btn_set_default.render = function(self, section, scope) + if subvolume_list[section].default_subvolume then + self.view_disabled = true + self.inputtitle = translate("Set Default") + elseif subvolume_list[section].ID == 0 then + self.template = "cbi/dvalue" + else + self.inputtitle = translate("Set Default") + self.view_disabled = false + end + Button.render(self, section, scope) +end +btn_set_default.write = function(self, section, value) + local cmd + if value == translate("Set Default") then + cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point..subvolume_list[section].path + else + cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point.."/" + end + local res = luci.util.exec(cmd.. " 2>&1") + if res and (res:match("ERR") or res:match("not enough arguments")) then + m.errmessage = res + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid)) + end +end +local btn_remove = table_subvolume:option(Button, "_subv_remove") +btn_remove.template = "diskman/cbi/disabled_button" +btn_remove.forcewrite = true +btn_remove.render = function(self, section, scope) + if subvolume_list[section].ID == 0 then + btn_remove.inputtitle = translate("Create") + btn_remove.inputstyle = "add" + self.view_disabled = false + elseif subvolume_list[section].path == "/" or subvolume_list[section].default_subvolume then + btn_remove.inputtitle = translate("Delete") + btn_remove.inputstyle = "remove" + self.view_disabled = true + else + btn_remove.inputtitle = translate("Delete") + btn_remove.inputstyle = "remove" + self.view_disabled = false + end + Button.render(self, section, scope) +end + +btn_remove.write = function(self, section, value) + local cmd + if value == translate("Delete") then + cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. subvolume_list[section].path + elseif value == translate("Create") then + if value_path and value_path:match("^/") then + cmd = dm.command.btrfs .. " subvolume create " .. mount_point .. value_path + else + m.errmessage = translate("Please input Subvolume Path, Subvolume must start with '/'") + return + end + end + local res = luci.util.exec(cmd.. " 2>&1") + if res and (res:match("ERR") or res:match("not enough arguments")) then + m.errmessage = luci.util.pcdata(res) + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid)) + end +end +-- snapshot +-- local snapshot_list = dm.get_btrfs_subv(mount_point, 1) +-- table_snapshot = m:section(Table, snapshot_list, translate("Snapshots")) +-- table_snapshot:option(DummyValue, "id", translate("ID")) +-- table_snapshot:option(DummyValue, "top_level", translate("Top Level")) +-- table_snapshot:option(DummyValue, "uuid", translate("UUID")) +-- table_snapshot:option(DummyValue, "otime", translate("Otime")) +-- table_snapshot:option(DummyValue, "path", translate("Path")) +-- local snp_remove = table_snapshot:option(Button, "_snp_remove") +-- snp_remove.inputtitle = translate("Delete") +-- snp_remove.inputstyle = "remove" +-- snp_remove.write = function(self, section, value) +-- local cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. snapshot_list[section].path +-- local res = luci.util.exec(cmd.. " 2>&1") +-- if res and (res:match("ERR") or res:match("not enough arguments")) then +-- m.errmessage = luci.util.pcdata(res) +-- else +-- luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid)) +-- end +-- end + +-- new snapshots +local s_snapshot = m:section(SimpleSection, translate("New Snapshot")) +local value_sorce, value_dest, value_readonly +local v_sorce = s_snapshot:option(Value, "_source", translate("Source Path"), translate("The source path for create the snapshot")) +v_sorce.placeholder = "/data" +v_sorce.forcewrite = true +v_sorce.write = function(self, section, value) + value_sorce = value +end + +local v_readonly = s_snapshot:option(Flag, "_readonly", translate("Readonly"), translate("The path where you want to store the snapshot")) +v_readonly.forcewrite = true +v_readonly.rmempty = false +v_readonly.disabled = 0 +v_readonly.enabled = 1 +v_readonly.default = 1 +v_readonly.write = function(self, section, value) + value_readonly = value +end +local v_dest = s_snapshot:option(Value, "_dest", translate("Destination Path (optional)")) +v_dest.forcewrite = true +v_dest.placeholder = "/.snapshot/202002051538" +v_dest.write = function(self, section, value) + value_dest = value +end +local btn_snp_create = s_snapshot:option(Button, "_snp_create") +btn_snp_create.title = " " +btn_snp_create.inputtitle = translate("New Snapshot") +btn_snp_create.inputstyle = "add" +btn_snp_create.write = function(self, section, value) + if value_sorce and value_sorce:match("^/") then + if not value_dest then value_dest = "/.snapshot"..value_sorce.."/"..os.date("%Y%m%d%H%M%S") end + nixio.fs.mkdirr(mount_point..value_dest:match("(.-)[^/]+$")) + local cmd = dm.command.btrfs .. " subvolume snapshot" .. (value_readonly == 1 and " -r " or " ") .. mount_point..value_sorce .. " " .. mount_point..value_dest + local res = luci.util.exec(cmd .. " 2>&1") + if res and (res:match("ERR") or res:match("not enough arguments")) then + m.errmessage = luci.util.pcdata(res) + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid)) + end + else + m.errmessage = translate("Please input Source Path of snapshot, Source Path must start with '/'") + end +end + +return m diff --git a/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua b/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua new file mode 100755 index 000000000..c209df0aa --- /dev/null +++ b/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua @@ -0,0 +1,327 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" +require("luci.tools.webadmin") +local dm = require "luci.model.diskman" + +-- Use (non-UCI) SimpleForm since we have no related config file +m = SimpleForm("diskman", translate("DiskMan"), translate("Manage Disks over LuCI.")) +m.template = "diskman/cbi/xsimpleform" +m:append(Template("diskman/disk_info")) +-- disable submit and reset button +m.submit = false +m.reset = false +-- rescan disks +rescan = m:section(SimpleSection) +rescan_button = rescan:option(Button, "_rescan") +rescan_button.inputtitle= translate("Rescan Disks") +rescan_button.template = "diskman/cbi/inlinebutton" +rescan_button.inputstyle = "add" +rescan_button.forcewrite = true +rescan_button.write = function(self, section, value) + luci.util.exec("echo '- - -' | tee /sys/class/scsi_host/host*/scan > /dev/null") + if dm.command.mdadm then + luci.util.exec(dm.command.mdadm .. " --assemble --scan") + end + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) +end + +-- disks +local disks = dm.list_devices() +d = m:section(Table, disks, translate("Disks")) +d.config = "disk" +-- option(type, id(key of table), text) +d:option(DummyValue, "path", translate("Path")) +d:option(DummyValue, "model", translate("Model")) +d:option(DummyValue, "sn", translate("Serial Number")) +d:option(DummyValue, "size_formated", translate("Size")) +d:option(DummyValue, "temp", translate("Temp")) +-- d:option(DummyValue, "sec_size", translate("Sector Size ")) +d:option(DummyValue, "p_table", translate("Partition Table")) +d:option(DummyValue, "sata_ver", translate("SATA Version")) +-- d:option(DummyValue, "rota_rate", translate("Rotation Rate")) +d:option(DummyValue, "health", translate("Health")) +d:option(DummyValue, "status", translate("Status")) + +d.extedit = luci.dispatcher.build_url("admin/system/diskman/partition/%s") + +-- raid devices +if dm.command.mdadm then + local raid_devices = dm.list_raid_devices() + -- raid_devices = diskmanager.getRAIDdevices() + if next(raid_devices) ~= nil then + local r = m:section(Table, raid_devices, translate("RAID Devices")) + r.config = "_raid" + r:option(DummyValue, "path", translate("Path")) + r:option(DummyValue, "level", translate("RAID mode")) + r:option(DummyValue, "size_formated", translate("Size")) + r:option(DummyValue, "p_table", translate("Partition Table")) + r:option(DummyValue, "status", translate("Status")) + r:option(DummyValue, "members_str", translate("Members")) + r:option(DummyValue, "active", translate("Active")) + r.extedit = luci.dispatcher.build_url("admin/system/diskman/partition/%s") + end +end + +-- btrfs devices +if dm.command.btrfs then + btrfs_devices = dm.list_btrfs_devices() + if next(btrfs_devices) ~= nil then + local table_btrfs = m:section(Table, btrfs_devices, translate("Btrfs")) + table_btrfs:option(DummyValue, "uuid", translate("UUID")) + table_btrfs:option(DummyValue, "label", translate("Label")) + table_btrfs:option(DummyValue, "members", translate("Members")) + -- sieze is error, since there is RAID + -- table_btrfs:option(DummyValue, "size_formated", translate("Size")) + table_btrfs:option(DummyValue, "used_formated", translate("Usage")) + table_btrfs.extedit = luci.dispatcher.build_url("admin/system/diskman/btrfs/%s") + end +end + +-- mount point +local mount_point = dm.get_mount_points() +local _mount_point = {} +table.insert( mount_point, { device = 0 } ) +local table_mp = m:section(Table, mount_point, translate("Mount Point")) +local v_device = table_mp:option(Value, "device", translate("Device")) +v_device.render = function(self, section, scope) + if mount_point[section].device == 0 then + self.template = "cbi/value" + self.forcewrite = true + for dev, info in pairs(disks) do + for i, v in ipairs(info.partitions) do + self:value("/dev/".. v.name, "/dev/".. v.name .. " ".. v.size_formated) + end + end + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end +end +v_device.write = function(self, section, value) + _mount_point.device = value and value:gsub("%s+", "") or "" +end +local v_fs = table_mp:option(Value, "fs", translate("File System")) +v_fs.render = function(self, section, scope) + if mount_point[section].device == 0 then + self.template = "cbi/value" + self:value("auto", "auto") + self.default = "auto" + self.forcewrite = true + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end +end +v_fs.write = function(self, section, value) + _mount_point.fs = value and value:gsub("%s+", "") or "" +end +local v_mount_option = table_mp:option(Value, "mount_options", translate("Mount Options")) +v_mount_option.render = function(self, section, scope) + if mount_point[section].device == 0 then + self.template = "cbi/value" + self.placeholder = "rw,noauto" + self.forcewrite = true + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + local mp = mount_point[section].mount_options + mount_point[section].mount_options = nil + local length = 0 + for k in mp:gmatch("([^,]+)") do + mount_point[section].mount_options = mount_point[section].mount_options and (mount_point[section].mount_options .. ",") or "" + if length > 20 then + mount_point[section].mount_options = mount_point[section].mount_options.. "
" + length = 0 + end + mount_point[section].mount_options = mount_point[section].mount_options .. k + length = length + #k + end + self.rawhtml = true + -- mount_point[section].mount_options = #mount_point[section].mount_options > 50 and mount_point[section].mount_options:sub(1,50) .. "..." or mount_point[section].mount_options + DummyValue.render(self, section, scope) + end +end +v_mount_option.write = function(self, section, value) + _mount_point.mount_options = value and value:gsub("%s+", "") or "" +end +local v_mount_point = table_mp:option(Value, "mount_point", translate("Mount Point")) +v_mount_point.render = function(self, section, scope) + if mount_point[section].device == 0 then + self.template = "cbi/value" + self.placeholder = "/media/diskX" + self.forcewrite = true + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + local new_mp = "" + local v_mp_d + for v_mp_d in self["section"]["data"][section]["mount_point"]:gmatch('[^/]+') do + if #v_mp_d > 12 then + new_mp = new_mp .. "/" .. v_mp_d:sub(1,7) .. ".." .. v_mp_d:sub(-4) + else + new_mp = new_mp .."/".. v_mp_d + end + end + self["section"]["data"][section]["mount_point"] = ''..new_mp..'' + self.rawhtml = true + DummyValue.render(self, section, scope) + end +end +v_mount_point.write = function(self, section, value) + _mount_point.mount_point = value +end +local btn_umount = table_mp:option(Button, "_mount", translate("Mount")) +btn_umount.forcewrite = true +btn_umount.render = function(self, section, scope) + if mount_point[section].device == 0 then + self.inputtitle = translate("Mount") + btn_umount.inputstyle = "add" + else + self.inputtitle = translate("Umount") + btn_umount.inputstyle = "remove" + end + Button.render(self, section, scope) +end +btn_umount.write = function(self, section, value) + local res + if value == translate("Mount") then + if not _mount_point.mount_point or not _mount_point.device then return end + luci.util.exec("mkdir -p ".. _mount_point.mount_point) + res = luci.util.exec(dm.command.mount .. " ".. _mount_point.device .. (_mount_point.fs and (" -t ".. _mount_point.fs )or "") .. (_mount_point.mount_options and (" -o " .. _mount_point.mount_options.. " ") or " ").._mount_point.mount_point .. " 2>&1") + elseif value == translate("Umount") then + res = luci.util.exec(dm.command.umount .. " "..mount_point[section].mount_point .. " 2>&1") + end + if res:match("^mount:") or res:match("^umount:") then + m.errmessage = luci.util.pcdata(res) + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) + end +end + +if dm.command.mdadm or dm.command.btrfs then +local creation_section = m:section(TypedSection, "_creation") +creation_section.cfgsections=function() + return {translate("Creation")} +end +creation_section:tab("raid", translate("RAID"), translate("RAID Creation")) +creation_section:tab("btrfs", translate("Btrfs"), translate("Multiple Devices Btrfs Creation")) + +-- raid functions +if dm.command.mdadm then + + local rname, rmembers, rlevel + local r_name = creation_section:taboption("raid", Value, "_rname", translate("Raid Name")) + r_name.placeholder = "/dev/md0" + r_name.write = function(self, section, value) + rname = value + end + local r_level = creation_section:taboption("raid", ListValue, "_rlevel", translate("Raid Level")) + local valid_raid = luci.util.exec("lsmod | grep md_mod") + if valid_raid:match("linear") then + r_level:value("linear", "Linear") + end + if valid_raid:match("raid456") then + r_level:value("5", "Raid 5") + r_level:value("6", "Raid 6") + end + if valid_raid:match("raid1") then + r_level:value("1", "Raid 1") + end + if valid_raid:match("raid0") then + r_level:value("0", "Raid 0") + end + if valid_raid:match("raid10") then + r_level:value("10", "Raid 10") + end + r_level.write = function(self, section, value) + rlevel = value + end + local r_member = creation_section:taboption("raid", DynamicList, "_rmember", translate("Raid Member")) + for dev, info in pairs(disks) do + if not info.inuse and #info.partitions == 0 then + r_member:value(info.path, info.path.. " ".. info.size_formated) + end + for i, v in ipairs(info.partitions) do + if not v.inuse then + r_member:value("/dev/".. v.name, "/dev/".. v.name .. " ".. v.size_formated) + end + end + end + r_member.write = function(self, section, value) + rmembers = value + end + local r_create = creation_section:taboption("raid", Button, "_rcreate") + r_create.render = function(self, section, scope) + self.title = " " + self.inputtitle = translate("Create Raid") + self.inputstyle = "add" + Button.render(self, section, scope) + end + r_create.write = function(self, section, value) + -- mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 /dev/sdb6 /dev/sdc5 + local res = dm.create_raid(rname, rlevel, rmembers) + if res and res:match("^ERR") then + m.errmessage = luci.util.pcdata(res) + return + end + dm.gen_mdadm_config() + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) + end +end + +-- btrfs +if dm.command.btrfs then + local blabel, bmembers, blevel + local btrfs_label = creation_section:taboption("btrfs", Value, "_blabel", translate("Btrfs Label")) + btrfs_label.write = function(self, section, value) + blabel = value + end + local btrfs_level = creation_section:taboption("btrfs", ListValue, "_blevel", translate("Btrfs Raid Level")) + btrfs_level:value("single", "Single") + btrfs_level:value("raid0", "Raid 0") + btrfs_level:value("raid1", "Raid 1") + btrfs_level:value("raid10", "Raid 10") + btrfs_level.write = function(self, section, value) + blevel = value + end + + local btrfs_member = creation_section:taboption("btrfs", DynamicList, "_bmember", translate("Btrfs Member")) + for dev, info in pairs(disks) do + if not info.inuse and #info.partitions == 0 then + btrfs_member:value(info.path, info.path.. " ".. info.size_formated) + end + for i, v in ipairs(info.partitions) do + if not v.inuse then + btrfs_member:value("/dev/".. v.name, "/dev/".. v.name .. " ".. v.size_formated) + end + end + end + btrfs_member.write = function(self, section, value) + bmembers = value + end + local btrfs_create = creation_section:taboption("btrfs", Button, "_bcreate") + btrfs_create.render = function(self, section, scope) + self.title = " " + self.inputtitle = translate("Create Btrfs") + self.inputstyle = "add" + Button.render(self, section, scope) + end + btrfs_create.write = function(self, section, value) + -- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb + local res = dm.create_btrfs(blabel, blevel, bmembers) + if res and res:match("^ERR") then + m.errmessage = luci.util.pcdata(res) + return + end + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) + end +end +end + +return m diff --git a/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua b/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua new file mode 100755 index 000000000..1428eb6b2 --- /dev/null +++ b/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua @@ -0,0 +1,366 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" +require("luci.tools.webadmin") +local dm = require "luci.model.diskman" +local dev = arg[1] + +if not dev then + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) +elseif not nixio.fs.access("/dev/"..dev) then + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) +end + +m = SimpleForm("partition", translate("Partition Management"), translate("Partition Disk over LuCI.")) +m.template = "diskman/cbi/xsimpleform" +m.redirect = luci.dispatcher.build_url("admin/system/diskman") +m:append(Template("diskman/partition_info")) +-- disable submit and reset button +m.submit = false +m.reset = false + +local disk_info = dm.get_disk_info(dev, true) +local format_cmd = dm.get_format_cmd() + +s = m:section(Table, {disk_info}, translate("Device Info")) +-- s:option(DummyValue, "key") +-- s:option(DummyValue, "value") +s:option(DummyValue, "path", translate("Path")) +s:option(DummyValue, "model", translate("Model")) +s:option(DummyValue, "sn", translate("Serial Number")) +s:option(DummyValue, "size_formated", translate("Size")) +s:option(DummyValue, "sec_size", translate("Sector Size")) +local dv_p_table = s:option(ListValue, "p_table", translate("Partition Table")) +dv_p_table.render = function(self, section, scope) + -- create table only if not used by raid and no partitions on disk + if not disk_info.p_table:match("Raid") and (#disk_info.partitions == 0 or (#disk_info.partitions == 1 and disk_info.partitions[1].number == -1) or (disk_info.p_table:match("LOOP") and not disk_info.partitions[1].inuse)) then + self:value(disk_info.p_table, disk_info.p_table) + self:value("GPT", "GPT") + self:value("MBR", "MBR") + self.default = disk_info.p_table + ListValue.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end +end +if disk_info.type:match("md") then + s:option(DummyValue, "level", translate("Level")) + s:option(DummyValue, "members_str", translate("Members")) +else + s:option(DummyValue, "temp", translate("Temp")) + s:option(DummyValue, "sata_ver", translate("SATA Version")) + s:option(DummyValue, "rota_rate", translate("Rotation Rate")) +end +s:option(DummyValue, "status", translate("Status")) +local btn_health = s:option(Button, "health", translate("Health")) +btn_health.render = function(self, section, scope) + if disk_info.health then + self.inputtitle = disk_info.health + if disk_info.health == "PASSED" then + self.inputstyle = "add" + else + self.inputstyle = "remove" + end + Button.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end +end + +local btn_eject = s:option(Button, "_eject") +btn_eject.template = "diskman/cbi/disabled_button" +btn_eject.inputstyle = "remove" +btn_eject.render = function(self, section, scope) + for i, p in ipairs(disk_info.partitions) do + if p.mount_point ~= "-" then + self.view_disabled = true + break + end + end + if disk_info.p_table:match("Raid") then + self.view_disabled = true + end + if disk_info.type:match("md") then + btn_eject.inputtitle = translate("Remove") + else + btn_eject.inputtitle = translate("Eject") + end + Button.render(self, section, scope) +end +btn_eject.forcewrite = true +btn_eject.write = function(self, section, value) + for i, p in ipairs(disk_info.partitions) do + if p.mount_point ~= "-" then + m.errmessage = p.name .. translate("is in use! please unmount it first!") + return + end + end + if disk_info.type:match("md") then + luci.util.exec(dm.command.mdadm .. " --stop /dev/" .. dev) + luci.util.exec(dm.command.mdadm .. " --remove /dev/" .. dev) + for _, disk in ipairs(disk_info.members) do + luci.util.exec(dm.command.mdadm .. " --zero-superblock " .. disk) + end + dm.gen_mdadm_config() + else + luci.util.exec("echo 1 > /sys/block/" .. dev .. "/device/delete") + end + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) +end +-- eject: echo 1 > /sys/block/(device)/device/delete +-- rescan: echo '- - -' | tee /sys/class/scsi_host/host*/scan > /dev/null + + +-- partitions info +if not disk_info.p_table:match("Raid") then + s_partition_table = m:section(Table, disk_info.partitions, translate("Partitions Info"), translate("Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector")) + + -- s_partition_table:option(DummyValue, "number", translate("Number")) + s_partition_table:option(DummyValue, "name", translate("Name")) + local val_sec_start = s_partition_table:option(Value, "sec_start", translate("Start Sector")) + val_sec_start.render = function(self, section, scope) + -- could create new partition + if disk_info.partitions[section].number == -1 and disk_info.partitions[section].size > 1 * 1024 * 1024 then + self.template = "cbi/value" + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end + end + local val_sec_end = s_partition_table:option(Value, "sec_end", translate("End Sector")) + val_sec_end.render = function(self, section, scope) + -- could create new partition + if disk_info.partitions[section].number == -1 and disk_info.partitions[section].size > 1 * 1024 * 1024 then + self.template = "cbi/value" + Value.render(self, section, scope) + else + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end + end + val_sec_start.forcewrite = true + val_sec_start.write = function(self, section, value) + disk_info.partitions[section]._sec_start = value + end + val_sec_end.forcewrite = true + val_sec_end.write = function(self, section, value) + disk_info.partitions[section]._sec_end = value + end + s_partition_table:option(DummyValue, "size_formated", translate("Size")) + if disk_info.p_table == "MBR" then + s_partition_table:option(DummyValue, "type", translate("Type")) + end + s_partition_table:option(DummyValue, "used_formated", translate("Used")) + s_partition_table:option(DummyValue, "free_formated", translate("Free Space")) + s_partition_table:option(DummyValue, "usage", translate("Usage")) + local dv_mount_point = s_partition_table:option(DummyValue, "mount_point", translate("Mount Point")) + dv_mount_point.rawhtml = true + dv_mount_point.render = function(self, section, scope) + local new_mp = "" + local v_mp_d + for line in self["section"]["data"][section]["mount_point"]:gmatch("[^%s]+") do + if line == '-' then + new_mp = line + break + end + for v_mp_d in line:gmatch('[^/]+') do + if #v_mp_d > 12 then + new_mp = new_mp .. "/" .. v_mp_d:sub(1,7) .. ".." .. v_mp_d:sub(-4) + else + new_mp = new_mp .."/".. v_mp_d + end + end + new_mp = '' ..new_mp ..'' .. "
" + end + self["section"]["data"][section]["mount_point"] = new_mp + DummyValue.render(self, section, scope) + end + local val_fs = s_partition_table:option(Value, "fs", translate("File System")) + val_fs.forcewrite = true + val_fs.partitions = disk_info.partitions + for k, v in pairs(format_cmd) do + val_fs.format_cmd = val_fs.format_cmd and (val_fs.format_cmd .. "," .. k) or k + end + + val_fs.write = function(self, section, value) + disk_info.partitions[section]._fs = value + end + val_fs.render = function(self, section, scope) + -- use listvalue when partition not mounted + if disk_info.partitions[section].mount_point == "-" and disk_info.partitions[section].number ~= -1 and disk_info.partitions[section].type ~= "extended" then + self.template = "diskman/cbi/format_button" + self.inputstyle = "reset" + self.inputtitle = disk_info.partitions[section].fs == "raw" and translate("Format") or disk_info.partitions[section].fs + Button.render(self, section, scope) + -- self:reset_values() + -- self.keylist = {} + -- self.vallist = {} + -- for k, v in pairs(format_cmd) do + -- self:value(k,k) + -- end + -- self.default = disk_info.partitions[section].fs + else + -- self:reset_values() + -- self.keylist = {} + -- self.vallist = {} + self.template = "cbi/dvalue" + DummyValue.render(self, section, scope) + end + end + -- btn_format = s_partition_table:option(Button, "_format") + -- btn_format.template = "diskman/cbi/format_button" + -- btn_format.partitions = disk_info.partitions + -- btn_format.render = function(self, section, scope) + -- if disk_info.partitions[section].mount_point == "-" and disk_info.partitions[section].number ~= -1 and disk_info.partitions[section].type ~= "extended" then + -- self.inputtitle = translate("Format") + -- self.template = "diskman/cbi/disabled_button" + -- self.view_disabled = false + -- self.inputstyle = "reset" + -- for k, v in pairs(format_cmd) do + -- self:depends("val_fs", "k") + -- end + -- -- elseif disk_info.partitions[section].mount_point ~= "-" and disk_info.partitions[section].number ~= -1 then + -- -- self.inputtitle = "Format" + -- -- self.template = "diskman/cbi/disabled_button" + -- -- self.view_disabled = true + -- -- self.inputstyle = "reset" + -- else + -- self.inputtitle = "" + -- self.template = "cbi/dvalue" + -- end + -- Button.render(self, section, scope) + -- end + -- btn_format.forcewrite = true + -- btn_format.write = function(self, section, value) + -- local partition_name = "/dev/".. disk_info.partitions[section].name + -- if not nixio.fs.access(partition_name) then + -- m.errmessage = translate("Partition NOT found!") + -- return + -- end + -- local fs = disk_info.partitions[section]._fs + -- if not format_cmd[fs] then + -- m.errmessage = translate("Filesystem NOT support!") + -- return + -- end + -- local cmd = format_cmd[fs].cmd .. " " .. format_cmd[fs].option .. " " .. partition_name + -- local res = luci.util.exec(cmd .. " 2>&1") + -- if res and res:lower():match("error+") then + -- m.errmessage = luci.util.pcdata(res) + -- else + -- luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev)) + -- end + -- end + + local btn_action = s_partition_table:option(Button, "_action") + btn_action.forcewrite = true + btn_action.template = "diskman/cbi/disabled_button" + btn_action.render = function(self, section, scope) + -- if partition is mounted or the size < 1mb, then disable the add action + if disk_info.partitions[section].mount_point ~= "-" or (disk_info.partitions[section].type ~= "extended" and disk_info.partitions[section].number == -1 and disk_info.partitions[section].size <= 1 * 1024 * 1024) then + self.view_disabled = true + -- self.inputtitle = "" + -- self.template = "cbi/dvalue" + elseif disk_info.partitions[section].type == "extended" and next(disk_info.partitions[section]["logicals"]) ~= nil then + self.view_disabled = true + else + -- self.template = "diskman/cbi/disabled_button" + self.view_disabled = false + end + if disk_info.partitions[section].number ~= -1 then + self.inputtitle = translate("Remove") + self.inputstyle = "remove" + else + self.inputtitle = translate("New") + self.inputstyle = "add" + end + Button.render(self, section, scope) + end + btn_action.write = function(self, section, value) + if value == translate("New") then + local start_sec = disk_info.partitions[section]._sec_start and tonumber(disk_info.partitions[section]._sec_start) or tonumber(disk_info.partitions[section].sec_start) + local end_sec = disk_info.partitions[section]._sec_end + + if start_sec then + -- for sector alignment + local align = tonumber(disk_info.phy_sec) / tonumber(disk_info.logic_sec) + align = (align < 2048) and 2048 + if start_sec < 2048 then + start_sec = "2048" .. "s" + elseif math.fmod( start_sec, align ) ~= 0 then + start_sec = tostring(start_sec + align - math.fmod( start_sec, align )) .. "s" + else + start_sec = start_sec .. "s" + end + else + m.errmessage = translate("Invalid Start Sector!") + return + end + -- support +size format for End sector + local end_size, end_unit = end_sec:match("^+(%d-)([bkmgtsBKMGTS])$") + if tonumber(end_size) and end_unit then + local unit ={ + B=1, + S=512, + K=1024, + M=1048576, + G=1073741824, + T=1099511627776 + } + end_unit = end_unit:upper() + end_sec = tostring(tonumber(end_size) * unit[end_unit] / unit["S"] + tonumber(start_sec:sub(1,-2)) - 1 ) .. "s" + elseif tonumber(end_sec) then + end_sec = end_sec .. "s" + else + m.errmessage = translate("Invalid End Sector!") + return + end + local part_type = "primary" + + if disk_info.p_table == "MBR" and disk_info["extended_partition_index"] then + if tonumber(disk_info.partitions[disk_info["extended_partition_index"]].sec_start) <= tonumber(start_sec:sub(1,-2)) and tonumber(disk_info.partitions[disk_info["extended_partition_index"]].sec_end) >= tonumber(end_sec:sub(1,-2)) then + part_type = "logical" + if tonumber(start_sec:sub(1,-2)) - tonumber(disk_info.partitions[section].sec_start) < 2048 then + start_sec = tonumber(start_sec:sub(1,-2)) + 2048 + start_sec = start_sec .."s" + end + end + elseif disk_info.p_table == "GPT" then + -- AUTOMATIC FIX GPT PARTITION TABLE + -- Not all of the space available to /dev/sdb appears to be used, you can fix the GPT to use all of the space (an extra 16123870 blocks) or continue with the current setting? + local cmd = ' printf "ok\nfix\n" | parted ---pretend-input-tty /dev/'.. dev ..' print' + luci.util.exec(cmd .. " 2>&1") + end + + -- partiton + local cmd = dm.command.parted .. " -s -a optimal /dev/" .. dev .. " mkpart " .. part_type .." " .. start_sec .. " " .. end_sec + local res = luci.util.exec(cmd .. " 2>&1") + if res and res:lower():match("error+") then + m.errmessage = luci.util.pcdata(res) + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev)) + end + elseif value == translate("Remove") then + -- remove partition + local number = tostring(disk_info.partitions[section].number) + if (not number) or (number == "") then + m.errmessage = translate("Partition not exists!") + return + end + local cmd = dm.command.parted .. " -s /dev/" .. dev .. " rm " .. number + local res = luci.util.exec(cmd .. " 2>&1") + if res and res:lower():match("error+") then + m.errmessage = luci.util.pcdata(res) + else + luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/partition/" .. dev)) + end + end + end +end + +return m diff --git a/luci-app-diskman/luasrc/model/diskman.lua b/luci-app-diskman/luasrc/model/diskman.lua new file mode 100755 index 000000000..b29308c31 --- /dev/null +++ b/luci-app-diskman/luasrc/model/diskman.lua @@ -0,0 +1,738 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" +local ver = require "luci.version" + +local CMD = {"parted", "mdadm", "blkid", "smartctl", "df", "btrfs", "lsblk"} + +local d = {command ={}} +for _, cmd in ipairs(CMD) do + local command = luci.sys.exec("/usr/bin/which " .. cmd) + d.command[cmd] = command:match("^.+"..cmd) or nil +end + +d.command.mount = nixio.fs.access("/usr/bin/mount") and "/usr/bin/mount" or "/bin/mount" +d.command.umount = nixio.fs.access("/usr/bin/umount") and "/usr/bin/umount" or "/bin/umount" + +local proc_mounts = nixio.fs.readfile("/proc/mounts") or "" +local mounts = luci.util.exec(d.command.mount .. " 2>/dev/null") or "" +local swaps = nixio.fs.readfile("/proc/swaps") or "" +local df = luci.sys.exec(d.command.df .. " 2>/dev/null") or "" + +function byte_format(byte) + local suff = {"B", "KB", "MB", "GB", "TB"} + for i=1, 5 do + if byte > 1024 and i < 5 then + byte = byte / 1024 + else + return string.format("%.2f %s", byte, suff[i]) + end + end +end + +local get_smart_info = function(device) + local section + local smart_info = {} + for _, line in ipairs(luci.util.execl(d.command.smartctl .. " -H -A -i -n standby -f brief /dev/" .. device)) do + local attrib, val + if section == 1 then + attrib, val = line:match "^(.-):%s+(.+)" + elseif section == 2 and smart_info.nvme_ver then + attrib, val = line:match("^(.-):%s+(.+)") + if not smart_info.health then smart_info.health = line:match(".-overall%-health.-: (.+)") end + elseif section == 2 then + attrib, val = line:match("^([0-9 ]+)%s+[^ ]+%s+[POSRCK-]+%s+[0-9-]+%s+[0-9-]+%s+[0-9-]+%s+[0-9-]+%s+([0-9-]+)") + if not smart_info.health then smart_info.health = line:match(".-overall%-health.-: (.+)") end + else + attrib = line:match "^=== START OF (.*) SECTION ===" + if attrib and attrib:match("INFORMATION") then + section = 1 + elseif attrib and attrib:match("SMART DATA") then + section = 2 + elseif not smart_info.status then + val = line:match "^Device is in (.*) mode" + if val then smart_info.status = val end + end + end + + if not attrib then + if section ~= 2 then section = 0 end + elseif (attrib == "Power mode is") or + (attrib == "Power mode was") then + smart_info.status = val:match("(%S+)") + -- elseif attrib == "Sector Sizes" then + -- -- 512 bytes logical, 4096 bytes physical + -- smart_info.phy_sec = val:match "([0-9]*) bytes physical" + -- smart_info.logic_sec = val:match "([0-9]*) bytes logical" + -- elseif attrib == "Sector Size" then + -- -- 512 bytes logical/physical + -- smart_info.phy_sec = val:match "([0-9]*)" + -- smart_info.logic_sec = smart_info.phy_sec + elseif attrib == "Serial Number" then + smart_info.sn = val + elseif attrib == "194" or attrib == "Temperature" then + smart_info.temp = val:match("(%d+)") .. "°C" + elseif attrib == "Rotation Rate" then + smart_info.rota_rate = val + elseif attrib == "SATA Version is" then + smart_info.sata_ver = val + elseif attrib == "NVMe Version" then + smart_info.nvme_ver = val + end + end + return smart_info +end + +local parse_parted_info = function(keys, line) + -- parse the output of parted command (machine parseable format) + -- /dev/sda:5860533168s:scsi:512:4096:gpt:ATA ST3000DM001-1ER1:; + -- 1:34s:2047s:2014s:free; + -- 1:2048s:1073743872s:1073741825s:ext4:primary:; + local result = {} + local values = {} + + for value in line:gmatch("(.-)[:;]") do table.insert(values, value) end + for i = 1,#keys do + result[keys[i]] = values[i] or "" + end + return result +end + +local is_raid_member = function(partition) + -- check if inuse as raid member + if nixio.fs.access("/proc/mdstat") then + for _, result in ipairs(luci.util.execl("grep md /proc/mdstat | sed 's/[][]//g'")) do + local md, buf + md, buf = result:match("(md.-):(.+)") + if buf:match(partition) then + return "Raid Member: ".. md + end + end + end + return nil +end + +local get_mount_point = function(partition) + local mount_point + for m in mounts:gmatch("/dev/"..partition.." on ([^ ]*)") do + mount_point = (mount_point and (mount_point .. " ") or "") .. m + end + if mount_point then return mount_point end + -- result = luci.sys.exec('cat /proc/mounts | awk \'{if($1=="/dev/'.. partition ..'") print $2}\'') + -- if result ~= "" then return result end + + if swaps:match("\n/dev/" .. partition .."%s") then return "swap" end + -- result = luci.sys.exec("cat /proc/swaps | grep /dev/" .. partition) + -- if result ~= "" then return "swap" end + + return is_raid_member(partition) + +end + +-- return used, free, usage +local get_partition_usage = function(partition) + if not nixio.fs.access("/dev/"..partition) then return false end + local used, free, usage = df:match("\n/dev/" .. partition .. "%s+%d+%s+(%d+)%s+(%d+)%s+(%d+)%%%s-") + + usage = usage and (usage .. "%") or "-" + used = used and (tonumber(used) * 1024) or 0 + free = free and (tonumber(free) * 1024) or 0 + + return used, free, usage +end + +local get_parted_info = function(device) + if not device then return end + local result = {partitions={}} + local DEVICE_INFO_KEYS = { "path", "size", "type", "logic_sec", "phy_sec", "p_table", "model", "flags" } + local PARTITION_INFO_KEYS = { "number", "sec_start", "sec_end", "size", "fs", "tag_name", "flags" } + local partition_temp + local partitions_temp = {} + local disk_temp + + for line in luci.util.execi(d.command.parted .. " -s -m /dev/" .. device .. " unit s print free", "r") do + if line:find("^/dev/"..device..":.+") then + disk_temp = parse_parted_info(DEVICE_INFO_KEYS, line) + disk_temp.partitions = {} + if disk_temp["size"] then + local length = disk_temp["size"]:gsub("^(%d+)s$", "%1") + local newsize = tostring(tonumber(length)*tonumber(disk_temp["logic_sec"])) + disk_temp["size"] = newsize + end + if disk_temp["p_table"] == "msdos" then + disk_temp["p_table"] = "MBR" + else + disk_temp["p_table"] = disk_temp["p_table"]:upper() + end + elseif line:find("^%d-:.+") then + partition_temp = parse_parted_info(PARTITION_INFO_KEYS, line) + -- use human-readable form instead of sector number + if partition_temp["size"] then + local length = partition_temp["size"]:gsub("^(%d+)s$", "%1") + local newsize = (tonumber(length) * tonumber(disk_temp["logic_sec"])) + partition_temp["size"] = newsize + partition_temp["size_formated"] = byte_format(newsize) + end + partition_temp["number"] = tonumber(partition_temp["number"]) or -1 + if partition_temp["fs"] == "free" then + partition_temp["number"] = -1 + partition_temp["fs"] = "Free Space" + partition_temp["name"] = "-" + elseif device:match("sd") or device:match("sata") then + partition_temp["name"] = device..partition_temp["number"] + elseif device:match("mmcblk") or device:match("md") or device:match("nvme") then + partition_temp["name"] = device.."p"..partition_temp["number"] + end + if partition_temp["number"] > 0 and partition_temp["fs"] == "" and d.command.lsblk then + partition_temp["fs"] = luci.util.exec(d.command.lsblk .. " /dev/"..device.. tostring(partition_temp["number"]) .. " -no fstype"):match("([^%s]+)") or "" + end + partition_temp["fs"] = partition_temp["fs"] == "" and "raw" or partition_temp["fs"] + partition_temp["sec_start"] = partition_temp["sec_start"] and partition_temp["sec_start"]:sub(1,-2) + partition_temp["sec_end"] = partition_temp["sec_end"] and partition_temp["sec_end"]:sub(1,-2) + partition_temp["mount_point"] = partition_temp["name"]~="-" and get_mount_point(partition_temp["name"]) or "-" + if partition_temp["mount_point"]~="-" then + partition_temp["used"], partition_temp["free"], partition_temp["usage"] = get_partition_usage(partition_temp["name"]) + partition_temp["used_formated"] = partition_temp["used"] and byte_format(partition_temp["used"]) or "-" + partition_temp["free_formated"] = partition_temp["free"] and byte_format(partition_temp["free"]) or "-" + else + partition_temp["used"], partition_temp["free"], partition_temp["usage"] = 0,0,"-" + partition_temp["used_formated"] = "-" + partition_temp["free_formated"] = "-" + end + -- if disk_temp["p_table"] == "MBR" and (partition_temp["number"] < 4) and (partition_temp["number"] > 0) then + -- local real_size_sec = tonumber(nixio.fs.readfile("/sys/block/"..device.."/"..partition_temp["name"].."/size")) * tonumber(disk_temp.phy_sec) + -- if real_size_sec ~= partition_temp["size"] then + -- disk_temp["extended_partition_index"] = partition_temp["number"] + -- partition_temp["type"] = "extended" + -- partition_temp["size"] = real_size_sec + -- partition_temp["fs"] = "-" + -- partition_temp["logicals"] = {} + -- else + -- partition_temp["type"] = "primary" + -- end + -- end + + table.insert(partitions_temp, partition_temp) + end + end + if disk_temp and disk_temp["p_table"] == "MBR" then + for i, p in ipairs(partitions_temp) do + if disk_temp["extended_partition_index"] and p["number"] > 4 then + if tonumber(p["sec_end"]) <= tonumber(partitions_temp[disk_temp["extended_partition_index"]]["sec_end"]) and tonumber(p["sec_start"]) >= tonumber(partitions_temp[disk_temp["extended_partition_index"]]["sec_start"]) then + p["type"] = "logical" + table.insert(partitions_temp[disk_temp["extended_partition_index"]]["logicals"], i) + end + elseif (p["number"] < 4) and (p["number"] > 0) then + local s = nixio.fs.readfile("/sys/block/"..device.."/"..p["name"].."/size") + if s then + local real_size_sec = tonumber(s) * tonumber(disk_temp.phy_sec) + -- if size not equal, it's an extended + if real_size_sec ~= p["size"] then + disk_temp["extended_partition_index"] = i + p["type"] = "extended" + p["size"] = real_size_sec + p["fs"] = "-" + p["logicals"] = {} + else + p["type"] = "primary" + end + else + -- if not found in "/sys/block" + p["type"] = "primary" + end + end + end + end + result = disk_temp + result.partitions = partitions_temp + + return result +end + +local mddetail = function(mdpath) + local detail = {} + local path = mdpath:match("^/dev/md%d+$") + if path then + local mdadm = io.popen(d.command.mdadm .. " --detail "..path, "r") + for line in mdadm:lines() do + local key, value = line:match("^%s*(.+) : (.+)") + if key then + detail[key] = value + end + end + mdadm:close() + end + return detail +end + +-- return {{device="", mount_points="", fs="", mount_options="", dump="", pass=""}..} +d.get_mount_points = function() + local mount + local res = {} + local h ={"device", "mount_point", "fs", "mount_options", "dump", "pass"} + for mount in proc_mounts:gmatch("[^\n]+") do + local device = mount:match("^([^%s]+)%s+.+") + -- only show /dev/xxx device + if device and device:match("/dev/") then + res[#res+1] = {} + local i = 0 + for v in mount:gmatch("[^%s]+") do + i = i + 1 + res[#res][h[i]] = v + end + end + end + return res +end + +d.get_disk_info = function(device, wakeup) + --[[ return: + { + path, model, sn, size, size_mounted, flags, type, temp, p_table, logic_sec, phy_sec, sec_size, sata_ver, rota_rate, status, health, + partitions = { + 1 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, usage, used, free, used_formated, free_formated}, + 2 = { number, name, sec_start, sec_end, size, size_mounted, fs, tag_name, type, flags, mount_point, usage, used, free, used_formated, free_formated}, + ... + } + --raid devices only + level, members, members_str + } + --]] + if not device then return end + local disk_info + local smart_info = get_smart_info(device) + + -- check if divice is the member of raid + smart_info["p_table"] = is_raid_member(device..'0') + -- if status is not active(standby), only check smart_info. + -- if only weakup == true, weakup the disk and check parted_info. + if smart_info.status ~= "STANDBY" or wakeup or (smart_info["p_table"] and not smart_info["p_table"]:match("Raid")) or device:match("^md") then + disk_info = get_parted_info(device) + disk_info["sec_size"] = disk_info["logic_sec"] .. "/" .. disk_info["phy_sec"] + disk_info["size_formated"] = byte_format(tonumber(disk_info["size"])) + -- if status is standby, after get part info, the disk is weakuped, then get smart_info again for more informations + if smart_info.status ~= "ACTIVE" then smart_info = get_smart_info(device) end + else + disk_info = {} + end + + for k, v in pairs(smart_info) do + disk_info[k] = v + end + + if disk_info.type and disk_info.type:match("md") then + local raid_info = d.list_raid_devices()[disk_info["path"]:match("/dev/(.+)")] + for k, v in pairs(raid_info) do + disk_info[k] = v + end + end + return disk_info +end + +d.list_raid_devices = function() + local fs = require "nixio.fs" + + local raid_devices = {} + if not fs.access("/proc/mdstat") then return raid_devices end + local mdstat = io.open("/proc/mdstat", "r") + for line in mdstat:lines() do + + -- md1 : active raid1 sdb2[1] sda2[0] + -- md127 : active raid5 sdh1[6] sdg1[4] sdf1[3] sde1[2] sdd1[1] sdc1[0] + local device_info = {} + local mdpath, list = line:match("^(md%d+) : (.+)") + if mdpath then + local members = {} + for member in string.gmatch(list, "%S+") do + member_path = member:match("^(%S+)%[%d+%]") + if member_path then + member = '/dev/'..member_path + end + table.insert(members, member) + end + local active = table.remove(members, 1) + local level = "-" + if active == "active" then + level = table.remove(members, 1) + end + + local size = tonumber(fs.readfile(string.format("/sys/class/block/%s/size", mdpath))) + local ss = tonumber(fs.readfile(string.format("/sys/class/block/%s/queue/logical_block_size", mdpath))) + + device_info["path"] = "/dev/"..mdpath + device_info["size"] = size*ss + device_info["size_formated"] = byte_format(size*ss) + device_info["active"] = active:upper() + device_info["level"] = level + device_info["members"] = members + device_info["members_str"] = table.concat(members, ", ") + + -- Get more info from output of mdadm --detail + local detail = mddetail(device_info["path"]) + device_info["status"] = detail["State"]:upper() + + raid_devices[mdpath] = device_info + end + end + mdstat:close() + + return raid_devices +end + +-- Collect Devices information + --[[ return: + { + sda={ + path, model, inuse, size_formated, + partitions={ + { name, inuse, size_formated } + ... + } + } + .. + } + --]] +d.list_devices = function() + local fs = require "nixio.fs" + + -- get all device names (sdX and mmcblkX) + local target_devnames = {} + for dev in fs.dir("/dev") do + if dev:match("^sd[a-z]$") + or dev:match("^mmcblk%d+$") + or dev:match("^sata[a-z]$") + or dev:match("^nvme%d+n%d+$") + then + table.insert(target_devnames, dev) + end + end + + local devices = {} + for i, bname in pairs(target_devnames) do + local device_info = {} + local device = "/dev/" .. bname + local size = tonumber(fs.readfile(string.format("/sys/class/block/%s/size", bname)) or "0") + local ss = tonumber(fs.readfile(string.format("/sys/class/block/%s/queue/logical_block_size", bname)) or "0") + local model = fs.readfile(string.format("/sys/class/block/%s/device/model", bname)) + local partitions = {} + for part in nixio.fs.glob("/sys/block/" .. bname .."/" .. bname .. "*") do + local pname = nixio.fs.basename(part) + local psize = byte_format(tonumber(nixio.fs.readfile(part .. "/size"))*ss) + local mount_point = get_mount_point(pname) + if mount_point then device_info["inuse"] = true end + table.insert(partitions, {name = pname, size_formated = psize, inuse = mount_point}) + end + + device_info["path"] = device + device_info["size_formated"] = byte_format(size*ss) + device_info["model"] = model + device_info["partitions"] = partitions + -- true or false + device_info["inuse"] = device_info["inuse"] or get_mount_point(bname) + + local udevinfo = {} + if luci.sys.exec("which udevadm") ~= "" then + local udevadm = io.popen("udevadm info --query=property --name="..device) + for attr in udevadm:lines() do + local k, v = attr:match("(%S+)=(%S+)") + udevinfo[k] = v + end + udevadm:close() + + device_info["info"] = udevinfo + if udevinfo["ID_MODEL"] then device_info["model"] = udevinfo["ID_MODEL"] end + end + devices[bname] = device_info + end + -- luci.util.perror(luci.util.serialize_json(devices)) + return devices +end + +-- get formart cmd +d.get_format_cmd = function() + local AVAILABLE_FMTS = { + ext2 = { cmd = "mkfs.ext2", option = "-F -E lazy_itable_init=1" }, + ext3 = { cmd = "mkfs.ext3", option = "-F -E lazy_itable_init=1" }, + ext4 = { cmd = "mkfs.ext4", option = "-F -E lazy_itable_init=1" }, + fat32 = { cmd = "mkfs.vfat", option = "-F" }, + exfat = { cmd = "mkexfat", option = "-f" }, + hfsplus = { cmd = "mkhfs", option = "-f" }, + ntfs = { cmd = "mkntfs", option = "-f" }, + swap = { cmd = "mkswap", option = "" }, + btrfs = { cmd = "mkfs.btrfs", option = "-f" } + } + result = {} + for fmt, obj in pairs(AVAILABLE_FMTS) do + local cmd = luci.sys.exec("/usr/bin/which " .. obj["cmd"]) + if cmd:match(obj["cmd"]) then + result[fmt] = { cmd = cmd:match("^.+"..obj["cmd"]) ,option = obj["option"] } + end + end + return result +end + +d.create_raid = function(rname, rlevel, rmembers) + local mb = {} + for _, v in ipairs(rmembers) do + mb[v]=v + end + rmembers = {} + for _, v in pairs(mb) do + table.insert(rmembers, v) + end + if type(rname) == "string" then + if rname:match("^md%d-%s+") then + rname = "/dev/"..rname:match("^(md%d-)%s+") + elseif rname:match("^/dev/md%d-%s+") then + rname = "/dev/"..rname:match("^(/dev/md%d-)%s+") + elseif not rname:match("/") then + rname = "/dev/md/".. rname + else + return "ERR: Invalid raid name" + end + else + local mdnum = 0 + for num=1,127 do + local md = io.open("/dev/md"..tostring(num), "r") + if md == nil then + mdnum = num + break + else + io.close(md) + end + end + if mdnum == 0 then return "ERR: Cannot find proper md number" end + rname = "/dev/md"..mdnum + end + + if rlevel == "5" or rlevel == "6" then + if #rmembers < 3 then return "ERR: Not enough members" end + end + if rlevel == "10" then + if #rmembers < 4 then return "ERR: Not enough members" end + end + if #rmembers < 2 then return "ERR: Not enough members" end + local cmd = d.command.mdadm .. " --create "..rname.." --run --assume-clean --homehost=any --level=" .. rlevel .. " --raid-devices=" .. #rmembers .. " " .. table.concat(rmembers, " ") + local res = luci.util.exec(cmd) + return res +end + +d.gen_mdadm_config = function() + if not nixio.fs.access("/etc/config/mdadm") then return end + local uci = require "luci.model.uci" + local x = uci.cursor() + -- delete all array sections + x:foreach("mdadm", "array", function(s) x:delete("mdadm",s[".name"]) end) + local cmd = d.command.mdadm .. " -D -s" + --ARRAY /dev/md1 metadata=1.2 name=any:1 UUID=f998ae14:37621b27:5c49e850:051f6813 + --ARRAY /dev/md3 metadata=1.2 name=any:3 UUID=c068c141:4b4232ca:f48cbf96:67d42feb + for _, v in ipairs(luci.util.execl(cmd)) do + local device, uuid = v:match("^ARRAY%s-([^%s]+)%s-[^%s]-%s-[^%s]-%s-UUID=([^%s]+)%s-") + if device and uuid then + local section_name = x:add("mdadm", "array") + x:set("mdadm", section_name, "device", device) + x:set("mdadm", section_name, "uuid", uuid) + end + end + x:commit("mdadm") + -- enable mdadm + luci.util.exec("/etc/init.d/mdadm enable") +end + +-- list btrfs filesystem device +-- {uuid={uuid, label, members, size, used}...} +d.list_btrfs_devices = function() + local btrfs_device = {} + if not d.command.btrfs then return btrfs_device end + local line, _uuid + for _, line in ipairs(luci.util.execl(d.command.btrfs .. " filesystem show -d --raw")) + do + local label, uuid = line:match("^Label:%s+([^%s]+)%s+uuid:%s+([^%s]+)") + if label and uuid then + _uuid = uuid + local _label = label:match("^'([^']+)'") + btrfs_device[_uuid] = {label = _label or label, uuid = uuid} + -- table.insert(btrfs_device, {label = label, uuid = uuid}) + end + local used = line:match("Total devices[%w%s]+used%s+(%d+)$") + if used then + btrfs_device[_uuid]["used"] = tonumber(used) + btrfs_device[_uuid]["used_formated"] = byte_format(tonumber(used)) + end + local size, device = line:match("devid[%w.%s]+size%s+(%d+)[%w.%s]+path%s+([^%s]+)$") + if size and device then + btrfs_device[_uuid]["size"] = btrfs_device[_uuid]["size"] and btrfs_device[_uuid]["size"] + tonumber(size) or tonumber(size) + btrfs_device[_uuid]["size_formated"] = byte_format(btrfs_device[_uuid]["size"]) + btrfs_device[_uuid]["members"] = btrfs_device[_uuid]["members"] and btrfs_device[_uuid]["members"]..", "..device or device + end + end + return btrfs_device +end + +d.create_btrfs = function(blabel, blevel, bmembers) + -- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb + if not d.command.btrfs or type(bmembers) ~= "table" or next(bmembers) == nil then return "ERR no btrfs support or no members" end + local label = blabel and " -L " .. blabel or "" + local cmd = "mkfs.btrfs -f " .. label .. " -d " .. blevel .. " " .. table.concat(bmembers, " ") + return luci.util.exec(cmd) +end + +-- get btrfs info +-- {uuid, label, members, data_raid_level,metadata_raid_lavel, size, used, size_formated, used_formated, free, free_formated, usage} +d.get_btrfs_info = function(m_point) + local btrfs_info = {} + if not m_point or not d.command.btrfs then return btrfs_info end + local cmd = d.command.btrfs .. " filesystem show --raw " .. m_point + local _, line, uuid, _label, members + for _, line in ipairs(luci.util.execl(cmd)) do + if not uuid and not _label then + _label, uuid = line:match("^Label:%s+([^%s]+)%s+uuid:%s+([^s]+)") + else + local mb = line:match("%s+devid.+path%s+([^%s]+)") + if mb then + members = members and (members .. ", ".. mb) or mb + end + end + end + + if not _label or not uuid then return btrfs_info end + local label = _label:match("^'([^']+)'") + cmd = d.command.btrfs .. " filesystem usage -b " .. m_point + local used, free, data_raid_level, metadata_raid_lavel + for _, line in ipairs(luci.util.execl(cmd)) do + if not used then + used = line:match("^%s+Used:%s+(%d+)") + elseif not free then + free = line:match("^%s+Free %(estimated%):%s+(%d+)") + elseif not data_raid_level then + data_raid_level = line:match("^Data,%s-(%w+)") + elseif not metadata_raid_lavel then + metadata_raid_lavel = line:match("^Metadata,%s-(%w+)") + end + end + if used and free and data_raid_level and metadata_raid_lavel then + used = tonumber(used) + free = tonumber(free) + btrfs_info = { + uuid = uuid, + label = label, + data_raid_level = data_raid_level, + metadata_raid_lavel = metadata_raid_lavel, + used = used, + free = free, + size = used + free, + size_formated = byte_format(used + free), + used_formated = byte_format(used), + free_formated = byte_format(free), + members = members, + usage = string.format("%.2f",(used / (free+used) * 100)) .. "%" + } + end + return btrfs_info +end + +-- get btrfs subvolume +-- {id={id, gen, top_level, path, snapshots, otime, default_subvolume}...} +d.get_btrfs_subv = function(m_point, snapshot) +local subvolume = {} +if not m_point or not d.command.btrfs then return subvolume end + +-- get default subvolume +local cmd = d.command.btrfs .. " subvolume get-default " .. m_point +local res = luci.util.exec(cmd) +local default_subvolume_id = res:match("^ID%s+([^%s]+)") + +-- get the root subvolume +if not snapshot then + local _, line, section_snap, _uuid, _otime, _id, _snap + cmd = d.command.btrfs .. " subvolume show ".. m_point + for _, line in ipairs(luci.util.execl(cmd)) do + if not section_snap then + if not _uuid then + _uuid = line:match("^%s-UUID:%s+([^%s]+)") + elseif not _otime then + _otime = line:match("^%s+Creation time:%s+(.+)") + elseif not _id then + _id = line:match("^%s+Subvolume ID:%s+([^%s]+)") + elseif line:match("^%s+(Snapshot%(s%):)") then + section_snap = true + end + else + local snapshot = line:match("^%s+(.+)") + if snapshot then + _snap = _snap and (_snap ..", /".. snapshot) or ("/"..snapshot) + end + end + end + if _uuid and _otime and _id then + subvolume["0".._id] = {id = _id , uuid = _uuid, otime = _otime, snapshots = _snap, path = "/"} + if default_subvolume_id == _id then + subvolume["0".._id].default_subvolume = 1 + end + end +end + +-- get subvolume of btrfs +cmd = d.command.btrfs .. " subvolume list -gcu" .. (snapshot and "s " or " ") .. m_point +for _, line in ipairs(luci.util.execl(cmd)) do + -- ID 259 gen 11 top level 258 uuid 26ae0c59-199a-cc4d-bd58-644eb4f65d33 path 1a/2b' + local id, gen, top_level, uuid, path, otime, otime2 + if snapshot then + id, gen, top_level, otime, otime2, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+otime%s+([^%s]+)%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$") + else + id, gen, top_level, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$") + end + if id and gen and top_level and uuid and path then + subvolume[id] = {id = id, gen = gen, top_level = top_level, otime = (otime and otime or "") .." ".. (otime2 and otime2 or ""), uuid = uuid, path = '/'.. path} + if not snapshot then + -- use btrfs subv show to get snapshots + local show_cmd = d.command.btrfs .. " subvolume show "..m_point.."/"..path + local __, line_show, section_snap + for __, line_show in ipairs(luci.util.execl(show_cmd)) do + if not section_snap then + local create_time = line_show:match("^%s+Creation time:%s+(.+)") + if create_time then + subvolume[id]["otime"] = create_time + elseif line_show:match("^%s+(Snapshot%(s%):)") then + section_snap = "true" + end + else + local snapshot = line_show:match("^%s+(.+)") + subvolume[id]["snapshots"] = subvolume[id]["snapshots"] and (subvolume[id]["snapshots"] .. ", /".. snapshot) or ("/"..snapshot) + end + end + end + end +end +if subvolume[default_subvolume_id] then + subvolume[default_subvolume_id].default_subvolume = 1 +end +-- if m_point == "/tmp/.btrfs_tmp" then +-- luci.util.exec("umount " .. m_point) +-- end +return subvolume +end + +d.format_partition = function(partition, fs) + local partition_name = "/dev/".. partition + if not nixio.fs.access(partition_name) then + return 500, "Partition NOT found!" + end + + local format_cmd = d.get_format_cmd() + if not format_cmd[fs] then + return 500, "Filesystem NOT support!" + end + local cmd = format_cmd[fs].cmd .. " " .. format_cmd[fs].option .. " " .. partition_name + local res = luci.util.exec(cmd .. " 2>&1") + if res and res:lower():match("error+") then + return 500, res + else + return 200, "OK" + end +end + +return d diff --git a/luci-app-diskman/luasrc/view/diskman/cbi/disabled_button.htm b/luci-app-diskman/luasrc/view/diskman/cbi/disabled_button.htm new file mode 100755 index 000000000..1ad4eca3b --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/cbi/disabled_button.htm @@ -0,0 +1,7 @@ +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> <% if self.view_disabled then %> disabled <% end %>/> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-diskman/luasrc/view/diskman/cbi/format_button.htm b/luci-app-diskman/luasrc/view/diskman/cbi/format_button.htm new file mode 100755 index 000000000..18e306e27 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/cbi/format_button.htm @@ -0,0 +1,7 @@ +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " onclick="event.preventDefault();partition_format('<%=self.partitions[section].name%>', '<%=self.format_cmd%>', '<%=self.inputtitle%>');" type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> <% if self.view_disabled then %> disabled <% end %>/> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> diff --git a/luci-app-diskman/luasrc/view/diskman/cbi/inlinebutton.htm b/luci-app-diskman/luasrc/view/diskman/cbi/inlinebutton.htm new file mode 100755 index 000000000..b1b193257 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/cbi/inlinebutton.htm @@ -0,0 +1,7 @@ +
+ <% if self:cfgvalue(section) ~= false then %> + " type="submit"" <% if self.disable then %>disabled <% end %><%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> /> + <% else %> + - + <% end %> +
diff --git a/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm b/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm new file mode 100755 index 000000000..69aa65e00 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm @@ -0,0 +1,37 @@ +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> + <% if self.description and #self.description > 0 then -%> +
<%=self.description%>
+ <%- end %> +
+
+ <% self:render_children(1, scope or {}) %> +
+ <% if self.error and self.error[1] then -%> +
+
    <% for _, e in ipairs(self.error[1]) do -%> +
  • + <%- if e == "invalid" then -%> + <%:One or more fields contain invalid values!%> + <%- elseif e == "missing" then -%> + <%:One or more required fields have no value!%> + <%- else -%> + <%=pcdata(e)%> + <%- end -%> +
  • + <%- end %>
+
+ <%- end %> +
+
+<%- + if type(self.hidden) == "table" then + for k, v in pairs(self.hidden) do +-%> + +<%- + end + end +%> \ No newline at end of file diff --git a/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm b/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm new file mode 100755 index 000000000..a831bfc77 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm @@ -0,0 +1,88 @@ +<% if not self.embedded then %> +
> + + + <% + end + + %>
<% + + if self.title and #self.title > 0 then + %>

<%=self.title%>

<% + end + + if self.description and #self.description > 0 then + %>
<%=self.description%>
<% + end + + self:render_children() + + %>
<% + + if self.message then + %>
<%=self.message%>
<% + end + + if self.errmessage then + %>
<%=self.errmessage%>
<% + end + + if not self.embedded then + if type(self.hidden) == "table" then + local k, v + for k, v in pairs(self.hidden) do + %><% + end + end + + local display_back = (self.redirect) + local display_cancel = (self.cancel ~= false and self.on_cancel) + local display_skip = (self.flow and self.flow.skip) + local display_submit = (self.submit ~= false) + local display_reset = (self.reset ~= false) + + if display_back or display_cancel or display_skip or display_submit or display_reset then + %>
<% + + if display_back then + %> <% + end + + if display_cancel then + local label = pcdata(self.cancel or translate("Cancel")) + %> <% + end + + if display_skip then + %> <% + end + + if display_submit then + local label = pcdata(self.submit or translate("Submit")) + %> <% + end + + if display_reset then + local label = pcdata(self.reset or translate("Reset")) + %> <% + end + + %>
<% + end + + %>
<% + end +%> + + diff --git a/luci-app-diskman/luasrc/view/diskman/disk_info.htm b/luci-app-diskman/luasrc/view/diskman/disk_info.htm new file mode 100755 index 000000000..118acd50d --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/disk_info.htm @@ -0,0 +1,108 @@ + diff --git a/luci-app-diskman/luasrc/view/diskman/partition_info.htm b/luci-app-diskman/luasrc/view/diskman/partition_info.htm new file mode 100755 index 000000000..78f5c1bd7 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/partition_info.htm @@ -0,0 +1,129 @@ + + \ No newline at end of file diff --git a/luci-app-diskman/luasrc/view/diskman/smart_detail.htm b/luci-app-diskman/luasrc/view/diskman/smart_detail.htm new file mode 100755 index 000000000..56a9139f0 --- /dev/null +++ b/luci-app-diskman/luasrc/view/diskman/smart_detail.htm @@ -0,0 +1,79 @@ + + + S.M.A.R.T detail of <%=dev%> + + + + +
+
+ <%:S.M.A.R.T Attrbutes%>: /dev/<%=dev%> + + + <% if dev:match("nvme") then %> + + <% else %> + + + + + + + + + + <% end %> + + + + +
<%:ID%><%:Attrbute%><%:Flag%><%:Value%><%:Worst%><%:Thresh%><%:Type%><%:Updated%><%:Raw%>

<%:Collecting data...%>
+
+
+ + \ No newline at end of file diff --git a/luci-app-diskman/po/zh-cn/diskman.po b/luci-app-diskman/po/zh-cn/diskman.po new file mode 100755 index 000000000..f380fc586 --- /dev/null +++ b/luci-app-diskman/po/zh-cn/diskman.po @@ -0,0 +1,239 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8\n" + +msgid "DiskMan" +msgstr "DiskMan 磁盘管理" + +msgid "Manage Disks over LuCI." +msgstr "通过 LuCI 管理磁盘" + +msgid "Rescan Disks" +msgstr "重新扫描磁盘" + +msgid "Disks" +msgstr "磁盘" + +msgid "Path" +msgstr "路径" + +msgid "Serial Number" +msgstr "序列号" + +msgid "Temp" +msgstr "温度" + +msgid "Partition Table" +msgstr "分区表" + +msgid "SATA Version" +msgstr "SATA 版本" + +msgid "Health" +msgstr "健康" + +msgid "File System" +msgstr "文件系统" + +msgid "Mount Options" +msgstr "挂载选项" + +msgid "Mount" +msgstr "挂载" + +msgid "Umount" +msgstr "卸载" + +msgid "Eject" +msgstr "弹出" + +msgid "New" +msgstr "创建" + +msgid "Remove" +msgstr "移除" + +msgid "Format" +msgstr "格式化" + +msgid "Start Sector" +msgstr "起始扇区" + +msgid "End Sector" +msgstr "中止扇区" + +msgid "Usage" +msgstr "用量" + +msgid "Used" +msgstr "已使用" + +msgid "Free Space" +msgstr "空闲空间" + +msgid "Model" +msgstr "型号" + +msgid "Size" +msgstr "容量" + +msgid "Status" +msgstr "状态" + +msgid "Mount Point" +msgstr "挂载点" + +msgid "Sector Size" +msgstr "扇区/物理扇区大小" + +msgid "Rotation Rate" +msgstr "转速" + +msgid "RAID Devices" +msgstr "RAID 设备" + +msgid "RAID mode" +msgstr "RAID 模式" + +msgid "Members" +msgstr "成员" + +msgid "Active" +msgstr "活动" + +msgid "RAID Creation" +msgstr "RAID 创建" + +msgid "Raid Name" +msgstr "RAID 名称" + +msgid "Raid Level" +msgstr "RAID 级别" + +msgid "Raid Member" +msgstr "磁盘阵列成员" + +msgid "Create Raid" +msgstr "创建 RAID" + +msgid "Partition Management" +msgstr "分区管理" + +msgid "Partition Disk over LuCI." +msgstr "通过LuCI分区磁盘。" + +msgid "Device Info" +msgstr "设备信息" + +msgid "Disk Man" +msgstr "磁盘管理" + +msgid "Partitions Info" +msgstr "分区信息" + +msgid "Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector" +msgstr "默认2048扇区对齐,【中止扇区】支持 +容量{b,k,m,g,t} 格式,例:+500m +10g +1t" + +msgid "Multiple Devices Btrfs Creation" +msgstr "Btrfs 阵列创建" + +msgid "Label" +msgstr "卷标" + +msgid "Btrfs Label" +msgstr "Btrfs 卷标" + +msgid "Btrfs Raid Level" +msgstr "Btrfs Raid 级别" + +msgid "Btrfs Member" +msgstr "Btrfs 整列成员" + +msgid "Create Btrfs" +msgstr "创建 Btrfs" + +msgid "New Snapshot" +msgstr "新建快照" + +msgid "SubVolumes" +msgstr "子卷" + +msgid "Top Level" +msgstr "父ID" + +msgid "Manage Btrfs" +msgstr "Btrfs 管理" + +msgid "Otime" +msgstr "创建时间" + +msgid "Snapshots" +msgstr "快照" + +msgid "Set Default" +msgstr "默认子卷" + +msgid "Source Path" +msgstr "源目录" + +msgid "Readonly" +msgstr "只读" + +msgid "Delete" +msgstr "删除" + +msgid "Create" +msgstr "创建" + +msgid "Destination Path (optional)" +msgstr "目标目录(可选)" + +msgid "Metadata" +msgstr "元数据" + +msgid "Data" +msgstr "数据" + +msgid "Btrfs Info" +msgstr "Btrfs 信息" + +msgid "The source path for create the snapshot" +msgstr "创建快照的源数据目录" + +msgid "The path where you want to store the snapshot" +msgstr "存放快照数据目录" + +msgid "Please input Source Path of snapshot, Source Path must start with '/'" +msgstr "请输入快照源路径,源路径必须以'/'开头" + +msgid "Please input Subvolume Path, Subvolume must start with '/'" +msgstr "请输入子卷路径,子卷路径必须以'/'开头" + +msgid "is in use! please unmount it first!" +msgstr "正在被使用!请先卸载!" + +msgid "Partition NOT found!" +msgstr "分区未找到!" + +msgid "Filesystem NOT support!" +msgstr "文件系统不支持!" + +msgid "Invalid Start Sector!" +msgstr "无效的起始扇区!" + +msgid "Invalid End Sector" +msgstr "无效的终止扇区!" + +msgid "Partition not exists!" +msgstr "分区不存在!" + +msgid "Creation" +msgstr "创建" + +msgid "Please select file system!" +msgstr "请选择文件系统!" + +msgid "Format partation:" +msgstr "格式化分区:" + +msgid "Warnning !! \nTHIS WILL OVERWRITE EXISTING PARTITIONS!! \nModify the partition table?" +msgstr "警告!!\n此操作会覆盖现有分区\n确定修改分区表?" diff --git a/luci-app-diskman/po/zh_Hans b/luci-app-diskman/po/zh_Hans new file mode 100755 index 000000000..41451e4a1 --- /dev/null +++ b/luci-app-diskman/po/zh_Hans @@ -0,0 +1 @@ +zh-cn \ No newline at end of file diff --git a/luci-app-dockerman/Makefile b/luci-app-dockerman/Makefile new file mode 100755 index 000000000..51dfa5c09 --- /dev/null +++ b/luci-app-dockerman/Makefile @@ -0,0 +1,21 @@ +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Support for docker +LUCI_DEPENDS:=@(aarch64||arm||x86_64) \ + +luci-compat \ + +luci-lib-docker \ + +luci-lib-ip \ + +docker \ + +dockerd \ + +ttyd +LUCI_PKGARCH:=all + +PKG_LICENSE:=AGPL-3.0 +PKG_MAINTAINER:=lisaac \ + Florian Eckert + +PKG_VERSION:=v0.5.25 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-dockerman/depends.lst b/luci-app-dockerman/depends.lst new file mode 100755 index 000000000..8a62f6a74 --- /dev/null +++ b/luci-app-dockerman/depends.lst @@ -0,0 +1 @@ +ttyd docker-cli \ No newline at end of file diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/containers.svg b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/containers.svg new file mode 100755 index 000000000..4165f90bd --- /dev/null +++ b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/containers.svg @@ -0,0 +1,7 @@ + + + + + Docker icon + + diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-icon.png b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-icon.png new file mode 100755 index 000000000..f156dc1c7 Binary files /dev/null and b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-icon.png differ diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-manager.css b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-manager.css new file mode 100755 index 000000000..911693b62 --- /dev/null +++ b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/file-manager.css @@ -0,0 +1,91 @@ +.fb-container { + margin-top: 1rem; +} +.fb-container .cbi-button { + height: 1.8rem; +} +.fb-container .cbi-input-text { + margin-bottom: 1rem; + width: 100%; +} +.fb-container .panel-title { + padding-bottom: 0; + width: 50%; + border-bottom: none; +} +.fb-container .panel-container { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 1rem; + border-bottom: 1px solid #eee; +} +.fb-container .upload-container { + display: none; + margin: 1rem 0; +} +.fb-container .upload-file { + margin-right: 2rem; +} +.fb-container .cbi-value-field { + text-align: left; +} +.fb-container .parent-icon strong { + margin-left: 1rem; +} +.fb-container td[class$="-icon"] { + cursor: pointer; +} +.fb-container .file-icon, .fb-container .folder-icon, .fb-container .link-icon { + position: relative; +} +.fb-container .file-icon:before, .fb-container .folder-icon:before, .fb-container .link-icon:before { + display: inline-block; + width: 1.5rem; + height: 1.5rem; + content: ''; + background-size: contain; + margin: 0 0.5rem 0 1rem; + vertical-align: middle; +} +.fb-container .file-icon:before { + background-image: url(file-icon.png); +} +.fb-container .folder-icon:before { + background-image: url(folder-icon.png); +} +.fb-container .link-icon:before { + background-image: url(link-icon.png); +} +@media screen and (max-width: 480px) { + .fb-container .upload-file { + width: 14.6rem; + } + .fb-container .cbi-value-owner, + .fb-container .cbi-value-perm { + display: none; + } +} + +.cbi-section-table { + width: 100%; +} + +.cbi-section-table-cell { + text-align: right; +} + +.cbi-button-install { +border-color: #c44; + color: #c44; + margin-left: 3px; +} + +.cbi-value-field { + padding: 10px 0; +} + +.parent-icon { + height: 1.8rem; + padding: 10px 0; +} \ No newline at end of file diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/folder-icon.png b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/folder-icon.png new file mode 100755 index 000000000..1370df3ad Binary files /dev/null and b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/folder-icon.png differ diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/images.svg b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/images.svg new file mode 100755 index 000000000..90ca5a1c7 --- /dev/null +++ b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/images.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/link-icon.png b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/link-icon.png new file mode 100755 index 000000000..03cc82cdf Binary files /dev/null and b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/link-icon.png differ diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/networks.svg b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/networks.svg new file mode 100755 index 000000000..3eb12a393 --- /dev/null +++ b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/networks.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/luci-app-dockerman/htdocs/luci-static/resources/dockerman/tar.min.js b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/tar.min.js new file mode 100755 index 000000000..d9c06667f --- /dev/null +++ b/luci-app-dockerman/htdocs/luci-static/resources/dockerman/tar.min.js @@ -0,0 +1,185 @@ +// https://github.com/thiscouldbebetter/TarFileExplorer +class TarFileTypeFlag +{constructor(value,name) +{this.value=value;this.id="_"+this.value;this.name=name;} +static _instances;static Instances() +{if(TarFileTypeFlag._instances==null) +{TarFileTypeFlag._instances=new TarFileTypeFlag_Instances();} +return TarFileTypeFlag._instances;}} +class TarFileTypeFlag_Instances +{constructor() +{this.Normal=new TarFileTypeFlag("0","Normal");this.HardLink=new TarFileTypeFlag("1","Hard Link");this.SymbolicLink=new TarFileTypeFlag("2","Symbolic Link");this.CharacterSpecial=new TarFileTypeFlag("3","Character Special");this.BlockSpecial=new TarFileTypeFlag("4","Block Special");this.Directory=new TarFileTypeFlag("5","Directory");this.FIFO=new TarFileTypeFlag("6","FIFO");this.ContiguousFile=new TarFileTypeFlag("7","Contiguous File");this.LongFilePath=new TarFileTypeFlag("L","././@LongLink");this._All=[this.Normal,this.HardLink,this.SymbolicLink,this.CharacterSpecial,this.BlockSpecial,this.Directory,this.FIFO,this.ContiguousFile,this.LongFilePath,];for(var i=0;ia+=String.fromCharCode(b),"");entryNext.header.fileName=entryNext.header.fileName.replace(/\0/g,"");entries.splice(i,1);i--;}}} +downloadAs(fileNameToSaveAs) +{return FileHelper.saveBytesAsFile +(this.toBytes(),fileNameToSaveAs)} +entriesForDirectories() +{return this.entries.filter(x=>x.header.typeFlag.name==TarFileTypeFlag.Instances().Directory);} +toBytes() +{this.toBytes_PrependLongPathEntriesAsNeeded();var fileAsBytes=[];var entriesAsByteArrays=this.entries.map(x=>x.toBytes());this.consolidateLongPathEntries();for(var i=0;imaxLength) +{var entryFileNameAsBytes=entryFileName.split("").map(x=>x.charCodeAt(0));var entryContainingLongPathToPrepend=TarFileEntry.fileNew +(typeFlagLongPath.name,entryFileNameAsBytes);entryContainingLongPathToPrepend.header.typeFlag=typeFlagLongPath;entryContainingLongPathToPrepend.header.timeModifiedInUnixFormat=entryHeader.timeModifiedInUnixFormat;entryContainingLongPathToPrepend.header.checksumCalculate();entryHeader.fileName=entryFileName.substr(0,maxLength)+String.fromCharCode(0);entries.splice(i,0,entryContainingLongPathToPrepend);i++;}}} +toString() +{var newline="\n";var returnValue="[TarFile]"+newline;for(var i=0;i{var fileLoadedAsBinaryString=fileLoadedEvent.target.result;var fileLoadedAsBytes=ByteHelper.stringUTF8ToBytes(fileLoadedAsBinaryString);callback(fileToLoad.name,fileLoadedAsBytes);} +fileReader.readAsBinaryString(fileToLoad);} +static loadFileAsText(fileToLoad,callback) +{var fileReader=new FileReader();fileReader.onload=(fileLoadedEvent)=>{var textFromFileLoaded=fileLoadedEvent.target.result;callback(fileToLoad.name,textFromFileLoaded);};fileReader.readAsText(fileToLoad);} +static saveBytesAsFile(bytesToWrite,fileNameToSaveAs) +{var bytesToWriteAsArrayBuffer=new ArrayBuffer(bytesToWrite.length);var bytesToWriteAsUIntArray=new Uint8Array(bytesToWriteAsArrayBuffer);for(var i=0;i + + + + + diff --git a/luci-app-dockerman/luasrc/controller/dockerman.lua b/luci-app-dockerman/luasrc/controller/dockerman.lua new file mode 100755 index 000000000..7aeed56e1 --- /dev/null +++ b/luci-app-dockerman/luasrc/controller/dockerman.lua @@ -0,0 +1,614 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" +-- local uci = (require "luci.model.uci").cursor() + +module("luci.controller.dockerman",package.seeall) + +function index() + entry({"admin", "docker"}, + alias("admin", "docker", "config"), + _("Docker"), + 40).acl_depends = { "luci-app-dockerman" } + + entry({"admin", "docker", "config"},cbi("dockerman/configuration"),_("Configuration"), 8).leaf=true + + -- local uci = (require "luci.model.uci").cursor() + -- if uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + -- local host = uci:get("dockerd", "dockerman", "remote_host") + -- local port = uci:get("dockerd", "dockerman", "remote_port") + -- if not host or not port then + -- return + -- end + -- else + -- local socket = uci:get("dockerd", "dockerman", "socket_path") or "/var/run/docker.sock" + -- if socket and not nixio.fs.access(socket) then + -- return + -- end + -- end + + -- if (require "luci.model.docker").new():_ping().code ~= 200 then + -- return + -- end + + entry({"admin", "docker", "overview"}, form("dockerman/overview"),_("Overview"), 2).leaf=true + entry({"admin", "docker", "containers"}, form("dockerman/containers"), _("Containers"), 3).leaf=true + entry({"admin", "docker", "images"}, form("dockerman/images"), _("Images"), 4).leaf=true + entry({"admin", "docker", "networks"}, form("dockerman/networks"), _("Networks"), 5).leaf=true + entry({"admin", "docker", "volumes"}, form("dockerman/volumes"), _("Volumes"), 6).leaf=true + entry({"admin", "docker", "events"}, call("action_events"), _("Events"), 7) + + entry({"admin", "docker", "newcontainer"}, form("dockerman/newcontainer")).leaf=true + entry({"admin", "docker", "newnetwork"}, form("dockerman/newnetwork")).leaf=true + entry({"admin", "docker", "container"}, form("dockerman/container")).leaf=true + + entry({"admin", "docker", "container_stats"}, call("action_get_container_stats")).leaf=true + entry({"admin", "docker", "containers_stats"}, call("action_get_containers_stats")).leaf=true + entry({"admin", "docker", "get_system_df"}, call("action_get_system_df")).leaf=true + entry({"admin", "docker", "container_get_archive"}, call("download_archive")).leaf=true + entry({"admin", "docker", "container_put_archive"}, call("upload_archive")).leaf=true + entry({"admin", "docker", "container_list_file"}, call("list_file")).leaf=true + entry({"admin", "docker", "container_remove_file"}, call("remove_file")).leaf=true + entry({"admin", "docker", "container_rename_file"}, call("rename_file")).leaf=true + entry({"admin", "docker", "container_export"}, call("export_container")).leaf=true + entry({"admin", "docker", "images_save"}, call("save_images")).leaf=true + entry({"admin", "docker", "images_load"}, call("load_images")).leaf=true + entry({"admin", "docker", "images_import"}, call("import_images")).leaf=true + entry({"admin", "docker", "images_get_tags"}, call("get_image_tags")).leaf=true + entry({"admin", "docker", "images_tag"}, call("tag_image")).leaf=true + entry({"admin", "docker", "images_untag"}, call("untag_image")).leaf=true + entry({"admin", "docker", "confirm"}, call("action_confirm")).leaf=true +end + +function action_get_system_df() + local res = docker.new():df() + luci.http.status(res.code, res.message) + luci.http.prepare_content("application/json") + luci.http.write_json(res.body) +end + +function scandir(id, directory) + local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil + if not cmd_docker or cmd_docker:match("^%s+$") then + return + end + local i, t, popen = 0, {}, io.popen + local uci = (require "luci.model.uci").cursor() + local remote = uci:get_bool("dockerd", "dockerman", "remote_endpoint") + local socket_path = not remote and uci:get("dockerd", "dockerman", "socket_path") or nil + local host = remote and uci:get("dockerd", "dockerman", "remote_host") or nil + local port = remote and uci:get("dockerd", "dockerman", "remote_port") or nil + if remote and host and port then + hosts = "tcp://" .. host .. ':'.. port + elseif socket_path then + hosts = "unix://" .. socket_path + else + return + end + local pfile = popen(cmd_docker .. ' -H "'.. hosts ..'" exec ' ..id .." ls -lh \""..directory.."\" | egrep -v '^total'") + for fileinfo in pfile:lines() do + i = i + 1 + t[i] = fileinfo + end + pfile:close() + return t +end + +function list_response(id, path, success) + luci.http.prepare_content("application/json") + local result + if success then + local rv = scandir(id, path) + result = { + ec = 0, + data = rv + } + else + result = { + ec = 1 + } + end + luci.http.write_json(result) +end + +function list_file(id) + local path = luci.http.formvalue("path") + list_response(id, path, true) +end + +function rename_file(id) + local filepath = luci.http.formvalue("filepath") + local newpath = luci.http.formvalue("newpath") + local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil + if not cmd_docker or cmd_docker:match("^%s+$") then + return + end + local uci = (require "luci.model.uci").cursor() + local remote = uci:get_bool("dockerd", "dockerman", "remote_endpoint") + local socket_path = not remote and uci:get("dockerd", "dockerman", "socket_path") or nil + local host = remote and uci:get("dockerd", "dockerman", "remote_host") or nil + local port = remote and uci:get("dockerd", "dockerman", "remote_port") or nil + if remote and host and port then + hosts = "tcp://" .. host .. ':'.. port + elseif socket_path then + hosts = "unix://" .. socket_path + else + return + end + local success = os.execute(cmd_docker .. ' -H "'.. hosts ..'" exec '.. id ..' mv "'..filepath..'" "'..newpath..'"') + list_response(nixio.fs.dirname(filepath), success) +end + +function remove_file(id) + local path = luci.http.formvalue("path") + local isdir = luci.http.formvalue("isdir") + local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil + if not cmd_docker or cmd_docker:match("^%s+$") then + return + end + local uci = (require "luci.model.uci").cursor() + local remote = uci:get_bool("dockerd", "dockerman", "remote_endpoint") + local socket_path = not remote and uci:get("dockerd", "dockerman", "socket_path") or nil + local host = remote and uci:get("dockerd", "dockerman", "remote_host") or nil + local port = remote and uci:get("dockerd", "dockerman", "remote_port") or nil + if remote and host and port then + hosts = "tcp://" .. host .. ':'.. port + elseif socket_path then + hosts = "unix://" .. socket_path + else + return + end + path = path:gsub("<>", "/") + path = path:gsub(" ", "\ ") + local success + if isdir then + success = os.execute(cmd_docker .. ' -H "'.. hosts ..'" exec '.. id ..' rm -r "'..path..'"') + else + success = os.remove(path) + end + list_response(nixio.fs.dirname(path), success) +end + +function action_events() + local logs = "" + local query ={} + + local dk = docker.new() + query["until"] = os.time() + local events = dk:events({query = query}) + + if events.code == 200 then + for _, v in ipairs(events.body) do + local date = "unknown" + if v and v.time then + date = os.date("%Y-%m-%d %H:%M:%S", v.time) + end + + local name = v.Actor.Attributes.name or "unknown" + local action = v.Action or "unknown" + + if v and v.Type == "container" then + local id = v.Actor.ID or "unknown" + logs = logs .. string.format("[%s] %s %s Container ID: %s Container Name: %s\n", date, v.Type, action, id, name) + elseif v.Type == "network" then + local container = v.Actor.Attributes.container or "unknown" + local network = v.Actor.Attributes.type or "unknown" + logs = logs .. string.format("[%s] %s %s Container ID: %s Network Name: %s Network type: %s\n", date, v.Type, action, container, name, network) + elseif v.Type == "image" then + local id = v.Actor.ID or "unknown" + logs = logs .. string.format("[%s] %s %s Image: %s Image name: %s\n", date, v.Type, action, id, name) + end + end + end + + luci.template.render("dockerman/logs", {self={syslog = logs, title="Events"}}) +end + +local calculate_cpu_percent = function(d) + if type(d) ~= "table" then + return + end + + local cpu_count = tonumber(d["cpu_stats"]["online_cpus"]) + local cpu_percent = 0.0 + local cpu_delta = tonumber(d["cpu_stats"]["cpu_usage"]["total_usage"]) - tonumber(d["precpu_stats"]["cpu_usage"]["total_usage"]) + local system_delta = tonumber(d["cpu_stats"]["system_cpu_usage"]) -- tonumber(d["precpu_stats"]["system_cpu_usage"]) + if system_delta > 0.0 then + cpu_percent = string.format("%.2f", cpu_delta / system_delta * 100.0 * cpu_count) + end + + return cpu_percent +end + +local get_memory = function(d) + if type(d) ~= "table" then + return + end + + -- local limit = string.format("%.2f", tonumber(d["memory_stats"]["limit"]) / 1024 / 1024) + -- local usage = string.format("%.2f", (tonumber(d["memory_stats"]["usage"]) - tonumber(d["memory_stats"]["stats"]["total_cache"])) / 1024 / 1024) + -- return usage .. "MB / " .. limit.. "MB" + + local limit =tonumber(d["memory_stats"]["limit"]) + local usage = tonumber(d["memory_stats"]["usage"]) + -- - tonumber(d["memory_stats"]["stats"]["total_cache"]) + + return usage, limit +end + +local get_rx_tx = function(d) + if type(d) ~="table" then + return + end + + local data = {} + if type(d["networks"]) == "table" then + for e, v in pairs(d["networks"]) do + data[e] = { + bw_tx = tonumber(v.tx_bytes), + bw_rx = tonumber(v.rx_bytes) + } + end + end + + return data +end + +local function get_stat(container_id) + if container_id then + local dk = docker.new() + local response = dk.containers:inspect({id = container_id}) + if response.code == 200 and response.body.State.Running then + response = dk.containers:stats({id = container_id, query = {stream = false, ["one-shot"] = true}}) + if response.code == 200 then + local container_stats = response.body + local cpu_percent = calculate_cpu_percent(container_stats) + local mem_useage, mem_limit = get_memory(container_stats) + local bw_rxtx = get_rx_tx(container_stats) + return response.code, response.body.message, { + cpu_percent = cpu_percent, + memory = { + mem_useage = mem_useage, + mem_limit = mem_limit + }, + bw_rxtx = bw_rxtx + } + else + return response.code, response.body.message + end + else + if response.code == 200 then + return 500, "container "..container_id.." not running" + else + return response.code, response.body.message + end + end + else + return 404, "No container name or id" + end +end +function action_get_container_stats(container_id) + local code, msg, res = get_stat(container_id) + luci.http.status(code, msg) + luci.http.prepare_content("application/json") + luci.http.write_json(res) +end + +function action_get_containers_stats() + local res = luci.http.formvalue(containers) or "" + local stats = {} + res = luci.jsonc.parse(res.containers) + if res and type(res) == "table" then + for i, v in ipairs(res) do + _,_,stats[v] = get_stat(v) + end + end + luci.http.status(200, "OK") + luci.http.prepare_content("application/json") + luci.http.write_json(stats) +end + +function action_confirm() + local data = docker:read_status() + if data then + data = data:gsub("\n","
"):gsub(" "," ") + code = 202 + msg = data + else + code = 200 + msg = "finish" + data = "finish" + end + + luci.http.status(code, msg) + luci.http.prepare_content("application/json") + luci.http.write_json({info = data}) +end + +function export_container(id) + local dk = docker.new() + local first + + local cb = function(res, chunk) + if res.code == 200 then + if not first then + first = true + luci.http.header('Content-Disposition', 'inline; filename="'.. id ..'.tar"') + luci.http.header('Content-Type', 'application\/x-tar') + end + luci.ltn12.pump.all(chunk, luci.http.write) + else + if not first then + first = true + luci.http.prepare_content("text/plain") + end + luci.ltn12.pump.all(chunk, luci.http.write) + end + end + + local res = dk.containers:export({id = id}, cb) +end + +function download_archive() + local id = luci.http.formvalue("id") + local path = luci.http.formvalue("path") + local filename = luci.http.formvalue("filename") or "archive" + local dk = docker.new() + local first + + local cb = function(res, chunk) + if res and res.code and res.code == 200 then + if not first then + first = true + luci.http.header('Content-Disposition', 'inline; filename="'.. filename .. '.tar"') + luci.http.header('Content-Type', 'application\/x-tar') + end + luci.ltn12.pump.all(chunk, luci.http.write) + else + if not first then + first = true + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("text/plain") + end + luci.ltn12.pump.all(chunk, luci.http.write) + end + end + + local res = dk.containers:get_archive({ + id = id, + query = { + path = luci.http.urlencode(path) + } + }, cb) +end + +function upload_archive(container_id) + local path = luci.http.formvalue("upload-path") + local dk = docker.new() + local ltn12 = require "luci.ltn12" + + local rec_send = function(sinkout) + luci.http.setfilehandler(function (meta, chunk, eof) + if chunk then + ltn12.pump.step(ltn12.source.string(chunk), sinkout) + end + end) + end + + local res = dk.containers:put_archive({ + id = container_id, + query = { + path = luci.http.urlencode(path) + }, + body = rec_send + }) + + local msg = res and res.message or res.body and res.body.message or nil + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg or "unknow"}) +end + +-- function save_images() +-- local names = luci.http.formvalue("names") +-- local dk = docker.new() +-- local first + +-- local cb = function(res, chunk) +-- if res.code == 200 then +-- if not first then +-- first = true +-- luci.http.status(res.code, res.message) +-- luci.http.header('Content-Disposition', 'inline; filename="'.. "images" ..'.tar"') +-- luci.http.header('Content-Type', 'application\/x-tar') +-- end +-- luci.ltn12.pump.all(chunk, luci.http.write) +-- else +-- if not first then +-- first = true +-- luci.http.prepare_content("text/plain") +-- end +-- luci.ltn12.pump.all(chunk, luci.http.write) +-- end +-- end + +-- docker:write_status("Images: saving" .. " " .. names .. "...") +-- local res = dk.images:get({ +-- query = { +-- names = luci.http.urlencode(names) +-- } +-- }, cb) +-- docker:clear_status() + +-- local msg = res and res.body and res.body.message or nil +-- luci.http.status(res.code, msg) +-- luci.http.prepare_content("application/json") +-- luci.http.write_json({message = msg}) +-- end + +function load_images() + local archive = luci.http.formvalue("upload-archive") + local dk = docker.new() + local ltn12 = require "luci.ltn12" + + local rec_send = function(sinkout) + luci.http.setfilehandler(function (meta, chunk, eof) + if chunk then + ltn12.pump.step(ltn12.source.string(chunk), sinkout) + end + end) + end + + docker:write_status("Images: loading...") + local res = dk.images:load({body = rec_send}) + local msg = res and res.body and ( res.body.message or res.body.stream or res.body.error ) or nil + if res and res.code == 200 and msg and msg:match("Loaded image ID") then + docker:clear_status() + else + docker:append_status("code:" .. (res and res.code or "500") .." ".. (msg or "unknow")) + end + + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg or "unknow"}) +end + +function import_images() + local src = luci.http.formvalue("src") + local itag = luci.http.formvalue("tag") + local dk = docker.new() + local ltn12 = require "luci.ltn12" + + local rec_send = function(sinkout) + luci.http.setfilehandler(function (meta, chunk, eof) + if chunk then + ltn12.pump.step(ltn12.source.string(chunk), sinkout) + end + end) + end + + docker:write_status("Images: importing".. " ".. itag .."...\n") + local repo = itag and itag:match("^([^:]+)") + local tag = itag and itag:match("^[^:]-:([^:]+)") + local res = dk.images:create({ + query = { + fromSrc = luci.http.urlencode(src or "-"), + repo = repo or nil, + tag = tag or nil + }, + body = not src and rec_send or nil + }, docker.import_image_show_status_cb) + + local msg = res and res.body and ( res.body.message )or nil + if not msg and #res.body == 0 then + msg = res.body.status or res.body.error + elseif not msg and #res.body >= 1 then + msg = res.body[#res.body].status or res.body[#res.body].error + end + + if res.code == 200 and msg and msg:match("sha256:") then + docker:clear_status() + else + docker:append_status("code:" .. (res and res.code or "500") .." ".. (msg or "unknow")) + end + + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg or "unknow"}) +end + +function get_image_tags(image_id) + if not image_id then + luci.http.status(400, "no image id") + luci.http.prepare_content("application/json") + luci.http.write_json({message = "no image id"}) + return + end + + local dk = docker.new() + local res = dk.images:inspect({ + id = image_id + }) + local msg = res and res.body and res.body.message or nil + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + + if res.code == 200 then + local tags = res.body.RepoTags + luci.http.write_json({tags = tags}) + else + local msg = res and res.body and res.body.message or nil + luci.http.write_json({message = msg or "unknow"}) + end +end + +function tag_image(image_id) + local src = luci.http.formvalue("tag") + local image_id = image_id or luci.http.formvalue("id") + + if type(src) ~= "string" or not image_id then + luci.http.status(400, "no image id or tag") + luci.http.prepare_content("application/json") + luci.http.write_json({message = "no image id or tag"}) + return + end + + local repo = src:match("^([^:]+)") + local tag = src:match("^[^:]-:([^:]+)") + local dk = docker.new() + local res = dk.images:tag({ + id = image_id, + query={ + repo=repo, + tag=tag + } + }) + local msg = res and res.body and res.body.message or nil + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + + if res.code == 201 then + local tags = res.body.RepoTags + luci.http.write_json({tags = tags}) + else + local msg = res and res.body and res.body.message or nil + luci.http.write_json({message = msg or "unknow"}) + end +end + +function untag_image(tag) + local tag = tag or luci.http.formvalue("tag") + + if not tag then + luci.http.status(400, "no tag name") + luci.http.prepare_content("application/json") + luci.http.write_json({message = "no tag name"}) + return + end + + local dk = docker.new() + local res = dk.images:inspect({name = tag}) + + if res.code == 200 then + local tags = res.body.RepoTags + if #tags > 1 then + local r = dk.images:remove({name = tag}) + local msg = r and r.body and r.body.message or nil + luci.http.status(r.code, msg) + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg}) + else + luci.http.status(500, "Cannot remove the last tag") + luci.http.prepare_content("application/json") + luci.http.write_json({message = "Cannot remove the last tag"}) + end + else + local msg = res and res.body and res.body.message or nil + luci.http.status(res and res.code or 500, msg or "unknow") + luci.http.prepare_content("application/json") + luci.http.write_json({message = msg or "unknow"}) + end +end diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua new file mode 100755 index 000000000..f62650fe5 --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua @@ -0,0 +1,152 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2021 Florian Eckert +Copyright 2021 lisaac +]]-- + +local uci = (require "luci.model.uci").cursor() + +local m, s, o + +m = Map("dockerd", + translate("Docker - Configuration"), + translate("DockerMan is a simple docker manager client for LuCI")) + +if nixio.fs.access("/usr/bin/dockerd") and not m.uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + s = m:section(NamedSection, "globals", "section", translate("Docker Daemon settings")) + + o = s:option(Flag, "auto_start", translate("Auto start")) + o.rmempty = false + o.write = function(self, section, value) + if value == "1" then + luci.util.exec("/etc/init.d/dockerd enable") + else + luci.util.exec("/etc/init.d/dockerd disable") + end + m.uci:set("dockerd", "globals", "auto_start", value) + end + + o = s:option(Value, "data_root", + translate("Docker Root Dir")) + o.placeholder = "/opt/docker/" + o:depends("remote_endpoint", 0) + + o = s:option(Value, "bip", + translate("Default bridge"), + translate("Configure the default bridge network")) + o.placeholder = "172.17.0.1/16" + o.datatype = "ipaddr" + o:depends("remote_endpoint", 0) + + o = s:option(DynamicList, "registry_mirrors", + translate("Registry Mirrors"), + translate("It replaces the daemon registry mirrors with a new set of registry mirrors")) + o:value("https://hub-mirror.c.163.com", "https://hub-mirror.c.163.com") + o:depends("remote_endpoint", 0) + o.forcewrite = true + + o = s:option(ListValue, "log_level", + translate("Log Level"), + translate('Set the logging level')) + o:value("debug", translate("Debug")) + o:value("", translate("Info")) -- This is the default debug level from the deamon is optin is not set + o:value("warn", translate("Warning")) + o:value("error", translate("Error")) + o:value("fatal", translate("Fatal")) + o.rmempty = true + o:depends("remote_endpoint", 0) + + o = s:option(DynamicList, "hosts", + translate("Client connection"), + translate('Specifies where the Docker daemon will listen for client connections (default: unix:///var/run/docker.sock)')) + o:value("unix:///var/run/docker.sock", "unix:///var/run/docker.sock") + o:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375") + o.rmempty = true + o:depends("remote_endpoint", 0) +end + +s = m:section(NamedSection, "dockerman", "section", translate("DockerMan settings")) +s:tab("ac", translate("Access Control")) +s:tab("dockerman", translate("DockerMan")) + +o = s:taboption("dockerman", Flag, "remote_endpoint", + translate("Remote Endpoint"), + translate("Connect to remote docker endpoint")) +o.rmempty = false +o.validate = function(self, value, sid) + local res = luci.http.formvaluetable("cbid.dockerd") + if res["dockerman.remote_endpoint"] == "1" then + if res["dockerman.remote_port"] and res["dockerman.remote_port"] ~= "" and res["dockerman.remote_host"] and res["dockerman.remote_host"] ~= "" then + return 1 + else + return nil, translate("Please input the PORT or HOST IP of remote docker instance!") + end + else + if not res["dockerman.socket_path"] then + return nil, translate("Please input the SOCKET PATH of docker daemon!") + end + end + return 0 +end + +o = s:taboption("dockerman", Value, "socket_path", + translate("Docker Socket Path")) +o.default = "/var/run/docker.sock" +o.placeholder = "/var/run/docker.sock" +o:depends("remote_endpoint", 0) + +o = s:taboption("dockerman", Value, "remote_host", + translate("Remote Host"), + translate("Host or IP Address for the connection to a remote docker instance")) +o.datatype = "host" +o.placeholder = "10.1.1.2" +o:depends("remote_endpoint", 1) + +o = s:taboption("dockerman", Value, "remote_port", + translate("Remote Port")) +o.placeholder = "2375" +o.datatype = "port" +o:depends("remote_endpoint", 1) + +-- o = s:taboption("dockerman", Value, "status_path", translate("Action Status Tempfile Path"), translate("Where you want to save the docker status file")) +-- o = s:taboption("dockerman", Flag, "debug", translate("Enable Debug"), translate("For debug, It shows all docker API actions of luci-app-dockerman in Debug Tempfile Path")) +-- o.enabled="true" +-- o.disabled="false" +-- o = s:taboption("dockerman", Value, "debug_path", translate("Debug Tempfile Path"), translate("Where you want to save the debug tempfile")) + +if nixio.fs.access("/usr/bin/dockerd") and not m.uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + o = s:taboption("ac", DynamicList, "ac_allowed_interface", translate("Allowed access interfaces"), translate("Which interface(s) can access containers under the bridge network, fill-in Interface Name")) + local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {} + for i, v in ipairs(interfaces) do + o:value(v, v) + end + o = s:taboption("ac", DynamicList, "ac_allowed_ports", translate("Ports allowed to be accessed"), translate("Which Port(s) can be accessed, it's not restricted by the Allowed Access interfaces configuration. Use this configuration with caution!")) + o.placeholder = "8080/tcp" + local docker = require "luci.model.docker" + local containers, res, lost_state + local dk = docker.new() + if dk:_ping().code ~= 200 then + lost_state = true + else + lost_state = false + res = dk.containers:list() + if res and res.code and res.code < 300 then + containers = res.body + end + end + + -- allowed_container.placeholder = "container name_or_id" + if containers then + for i, v in ipairs(containers) do + if v.State == "running" and v.Ports then + for _, port in ipairs(v.Ports) do + if port.PublicPort and port.IP and not string.find(port.IP,":") then + o:value(port.PublicPort.."/"..port.Type, v.Names[1]:sub(2) .. " | " .. port.PublicPort .. " | " .. port.Type) + end + end + end + end + end +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua new file mode 100755 index 000000000..20220ad8f --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua @@ -0,0 +1,810 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +require "luci.util" + +local docker = require "luci.model.docker" +local dk = docker.new() + +container_id = arg[1] +local action = arg[2] or "info" + +local m, s, o +local images, networks, container_info, res + +if not container_id then + return +end + +res = dk.containers:inspect({id = container_id}) +if res.code < 300 then + container_info = res.body +else + return +end + +local get_ports = function(d) + local data + + if d.HostConfig and d.HostConfig.PortBindings then + for inter, out in pairs(d.HostConfig.PortBindings) do + data = (data and (data .. "
") or "") .. out[1]["HostPort"] .. ":" .. inter + end + end + + return data +end + +local get_env = function(d) + local data + + if d.Config and d.Config.Env then + for _,v in ipairs(d.Config.Env) do + data = (data and (data .. "
") or "") .. v + end + end + + return data +end + +local get_command = function(d) + local data + + if d.Config and d.Config.Cmd then + for _,v in ipairs(d.Config.Cmd) do + data = (data and (data .. " ") or "") .. v + end + end + + return data +end + +local get_mounts = function(d) + local data + + if d.Mounts then + for _,v in ipairs(d.Mounts) do + local v_sorce_d, v_dest_d + local v_sorce = "" + local v_dest = "" + for v_sorce_d in v["Source"]:gmatch('[^/]+') do + if v_sorce_d and #v_sorce_d > 12 then + v_sorce = v_sorce .. "/" .. v_sorce_d:sub(1,12) .. "..." + else + v_sorce = v_sorce .."/".. v_sorce_d + end + end + for v_dest_d in v["Destination"]:gmatch('[^/]+') do + if v_dest_d and #v_dest_d > 12 then + v_dest = v_dest .. "/" .. v_dest_d:sub(1,12) .. "..." + else + v_dest = v_dest .."/".. v_dest_d + end + end + data = (data and (data .. "
") or "") .. v_sorce .. ":" .. v["Destination"] .. (v["Mode"] ~= "" and (":" .. v["Mode"]) or "") + end + end + + return data +end + +local get_device = function(d) + local data + + if d.HostConfig and d.HostConfig.Devices then + for _,v in ipairs(d.HostConfig.Devices) do + data = (data and (data .. "
") or "") .. v["PathOnHost"] .. ":" .. v["PathInContainer"] .. (v["CgroupPermissions"] ~= "" and (":" .. v["CgroupPermissions"]) or "") + end + end + + return data +end + +local get_links = function(d) + local data + + if d.HostConfig and d.HostConfig.Links then + for _,v in ipairs(d.HostConfig.Links) do + data = (data and (data .. "
") or "") .. v + end + end + + return data +end + +local get_tmpfs = function(d) + local data + + if d.HostConfig and d.HostConfig.Tmpfs then + for k, v in pairs(d.HostConfig.Tmpfs) do + data = (data and (data .. "
") or "") .. k .. (v~="" and ":" or "")..v + end + end + + return data +end + +local get_dns = function(d) + local data + + if d.HostConfig and d.HostConfig.Dns then + for _, v in ipairs(d.HostConfig.Dns) do + data = (data and (data .. "
") or "") .. v + end + end + + return data +end + +local get_sysctl = function(d) + local data + + if d.HostConfig and d.HostConfig.Sysctls then + for k, v in pairs(d.HostConfig.Sysctls) do + data = (data and (data .. "
") or "") .. k..":"..v + end + end + + return data +end + +local get_networks = function(d) + local data={} + + if d.NetworkSettings and d.NetworkSettings.Networks and type(d.NetworkSettings.Networks) == "table" then + for k,v in pairs(d.NetworkSettings.Networks) do + data[k] = v.IPAddress or "" + end + end + + return data +end + + +local start_stop_remove = function(m, cmd) + local res + + docker:clear_status() + docker:append_status("Containers: " .. cmd .. " " .. container_id .. "...") + + if cmd ~= "upgrade" then + res = dk.containers[cmd](dk, {id = container_id}) + else + res = dk.containers_upgrade(dk, {id = container_id}) + end + + if res and res.code >= 300 then + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id)) + else + docker:clear_status() + if cmd ~= "remove" and cmd ~= "upgrade" then + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id)) + else + luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers")) + end + end +end + +m=SimpleForm("docker", + translatef("Docker - Container (%s)", container_info.Name:sub(2)), + translate("On this page, the selected container can be managed.")) +m.redirect = luci.dispatcher.build_url("admin/docker/containers") + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err=docker:read_status() +s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(Table,{{}}) +s.notitle=true +s.rowcolors=false +s.template = "cbi/nullsection" + +o = s:option(Button, "_start") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Start") +o.inputstyle = "apply" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"start") +end + +o = s:option(Button, "_restart") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Restart") +o.inputstyle = "reload" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"restart") +end + +o = s:option(Button, "_stop") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Stop") +o.inputstyle = "reset" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"stop") +end + +o = s:option(Button, "_kill") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Kill") +o.inputstyle = "reset" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"kill") +end + +o = s:option(Button, "_export") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Export") +o.inputstyle = "apply" +o.forcewrite = true +o.write = function(self, section) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container_export/"..container_id)) +end + +o = s:option(Button, "_upgrade") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Upgrade") +o.inputstyle = "reload" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"upgrade") +end + +o = s:option(Button, "_duplicate") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Duplicate/Edit") +o.inputstyle = "add" +o.forcewrite = true +o.write = function(self, section) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer/duplicate/"..container_id)) +end + +o = s:option(Button, "_remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle=translate("Remove") +o.inputstyle = "remove" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"remove") +end + +s = m:section(SimpleSection) +s.template = "dockerman/container" + +if action == "info" then + res = dk.networks:list() + if res.code < 300 then + networks = res.body + else + return + end + m.submit = false + m.reset = false + table_info = { + ["01name"] = { + _key = translate("Name"), + _value = container_info.Name:sub(2) or "-", + _button=translate("Update") + }, + ["02id"] = { + _key = translate("ID"), + _value = container_info.Id or "-" + }, + ["03image"] = { + _key = translate("Image"), + _value = container_info.Config.Image .. "
" .. container_info.Image + }, + ["04status"] = { + _key = translate("Status"), + _value = container_info.State and container_info.State.Status or "-" + }, + ["05created"] = { + _key = translate("Created"), + _value = container_info.Created or "-" + }, + } + + if container_info.State.Status == "running" then + table_info["06start"] = { + _key = translate("Start Time"), + _value = container_info.State and container_info.State.StartedAt or "-" + } + else + table_info["06start"] = { + _key = translate("Finish Time"), + _value = container_info.State and container_info.State.FinishedAt or "-" + } + end + + table_info["07healthy"] = { + _key = translate("Healthy"), + _value = container_info.State and container_info.State.Health and container_info.State.Health.Status or "-" + } + table_info["08restart"] = { + _key = translate("Restart Policy"), + _value = container_info.HostConfig and container_info.HostConfig.RestartPolicy and container_info.HostConfig.RestartPolicy.Name or "-", + _button=translate("Update") + } + table_info["081user"] = { + _key = translate("User"), + _value = container_info.Config and (container_info.Config.User ~="" and container_info.Config.User or "-") or "-" + } + table_info["09mount"] = { + _key = translate("Mount/Volume"), + _value = get_mounts(container_info) or "-" + } + table_info["10cmd"] = { + _key = translate("Command"), + _value = get_command(container_info) or "-" + } + table_info["11env"] = { + _key = translate("Env"), + _value = get_env(container_info) or "-" + } + table_info["12ports"] = { + _key = translate("Ports"), + _value = get_ports(container_info) or "-" + } + table_info["13links"] = { + _key = translate("Links"), + _value = get_links(container_info) or "-" + } + table_info["14device"] = { + _key = translate("Device"), + _value = get_device(container_info) or "-" + } + table_info["15tmpfs"] = { + _key = translate("Tmpfs"), + _value = get_tmpfs(container_info) or "-" + } + table_info["16dns"] = { + _key = translate("DNS"), + _value = get_dns(container_info) or "-" + } + table_info["17sysctl"] = { + _key = translate("Sysctl"), + _value = get_sysctl(container_info) or "-" + } + + info_networks = get_networks(container_info) + list_networks = {} + for _, v in ipairs (networks) do + if v and v.Name then + local parent = v.Options and v.Options.parent or nil + local ip = v.IPAM and v.IPAM.Config and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil + ipv6 = v.IPAM and v.IPAM.Config and v.IPAM.Config[2] and v.IPAM.Config[2].Subnet or nil + local network_name = v.Name .. " | " .. v.Driver .. (parent and (" | " .. parent) or "") .. (ip and (" | " .. ip) or "").. (ipv6 and (" | " .. ipv6) or "") + list_networks[v.Name] = network_name + end + end + + if type(info_networks)== "table" then + for k,v in pairs(info_networks) do + table_info["14network"..k] = { + _key = translate("Network"), + _value = k.. (v~="" and (" | ".. v) or ""), + _button=translate("Disconnect") + } + list_networks[k]=nil + end + end + + table_info["15connect"] = { + _key = translate("Connect Network"), + _value = list_networks ,_opts = "", + _button=translate("Connect") + } + + s = m:section(Table,table_info) + s.nodescr=true + s.formvalue=function(self, section) + return table_info + end + + o = s:option(DummyValue, "_key", translate("Info")) + o.width = "20%" + + o = s:option(ListValue, "_value") + o.render = function(self, section, scope) + if table_info[section]._key == translate("Name") then + self:reset_values() + self.template = "cbi/value" + self.size = 30 + self.keylist = {} + self.vallist = {} + self.default=table_info[section]._value + Value.render(self, section, scope) + elseif table_info[section]._key == translate("Restart Policy") then + self.template = "cbi/lvalue" + self:reset_values() + self.size = nil + self:value("no", "No") + self:value("unless-stopped", "Unless stopped") + self:value("always", "Always") + self:value("on-failure", "On failure") + self.default=table_info[section]._value + ListValue.render(self, section, scope) + elseif table_info[section]._key == translate("Connect Network") then + self.template = "cbi/lvalue" + self:reset_values() + self.size = nil + for k,v in pairs(list_networks) do + if k ~= "host" then + self:value(k,v) + end + end + self.default=table_info[section]._value + ListValue.render(self, section, scope) + else + self:reset_values() + self.rawhtml=true + self.template = "cbi/dvalue" + self.default=table_info[section]._value + DummyValue.render(self, section, scope) + end + end + o.forcewrite = true + o.write = function(self, section, value) + table_info[section]._value=value + end + o.validate = function(self, value) + return value + end + + o = s:option(Value, "_opts") + o.forcewrite = true + o.write = function(self, section, value) + table_info[section]._opts=value + end + o.validate = function(self, value) + return value + end + o.render = function(self, section, scope) + if table_info[section]._key==translate("Connect Network") then + self.template = "cbi/value" + self.keylist = {} + self.vallist = {} + self.placeholder = "10.1.1.254" + self.datatype = "ip4addr" + self.default=table_info[section]._opts + Value.render(self, section, scope) + else + self.rawhtml=true + self.template = "cbi/dvalue" + self.default=table_info[section]._opts + DummyValue.render(self, section, scope) + end + end + + o = s:option(Button, "_button") + o.forcewrite = true + o.render = function(self, section, scope) + if table_info[section]._button and table_info[section]._value ~= nil then + self.inputtitle=table_info[section]._button + self.template = "cbi/button" + self.inputstyle = "edit" + Button.render(self, section, scope) + else + self.template = "cbi/dvalue" + self.default="" + DummyValue.render(self, section, scope) + end + end + o.write = function(self, section, value) + local res + + docker:clear_status() + + if section == "01name" then + docker:append_status("Containers: rename " .. container_id .. "...") + local new_name = table_info[section]._value + res = dk.containers:rename({ + id = container_id, + query = { + name=new_name + } + }) + elseif section == "08restart" then + docker:append_status("Containers: update " .. container_id .. "...") + local new_restart = table_info[section]._value + res = dk.containers:update({ + id = container_id, + body = { + RestartPolicy = { + Name = new_restart + } + } + }) + elseif table_info[section]._key == translate("Network") then + local _,_,leave_network + + _, _, leave_network = table_info[section]._value:find("(.-) | .+") + leave_network = leave_network or table_info[section]._value + docker:append_status("Network: disconnect " .. leave_network .. container_id .. "...") + res = dk.networks:disconnect({ + name = leave_network, + body = { + Container = container_id + } + }) + elseif section == "15connect" then + local connect_network = table_info[section]._value + local network_opiton + if connect_network ~= "none" + and connect_network ~= "bridge" + and connect_network ~= "host" then + + network_opiton = table_info[section]._opts ~= "" and { + IPAMConfig={ + IPv4Address=table_info[section]._opts + } + } or nil + end + docker:append_status("Network: connect " .. connect_network .. container_id .. "...") + res = dk.networks:connect({ + name = connect_network, + body = { + Container = container_id, + EndpointConfig= network_opiton + } + }) + end + + if res and res.code > 300 then + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) + else + docker:clear_status() + end + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id.."/info")) + end +elseif action == "resources" then + s = m:section(SimpleSection) + o = s:option( Value, "cpus", + translate("CPUs"), + translate("Number of CPUs. Number is a fractional number. 0.000 means no limit.")) + o.placeholder = "1.5" + o.rmempty = true + o.datatype="ufloat" + o.default = container_info.HostConfig.NanoCpus / (10^9) + + o = s:option(Value, "cpushares", + translate("CPU Shares Weight"), + translate("CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024.")) + o.placeholder = "1024" + o.rmempty = true + o.datatype="uinteger" + o.default = container_info.HostConfig.CpuShares + + o = s:option(Value, "memory", + translate("Memory"), + translate("Memory limit (format: []). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.")) + o.placeholder = "128m" + o.rmempty = true + o.default = container_info.HostConfig.Memory ~=0 and ((container_info.HostConfig.Memory / 1024 /1024) .. "M") or 0 + + o = s:option(Value, "blkioweight", + translate("Block IO Weight"), + translate("Block IO weight (relative weight) accepts a weight value between 10 and 1000.")) + o.placeholder = "500" + o.rmempty = true + o.datatype="uinteger" + o.default = container_info.HostConfig.BlkioWeight + + m.handle = function(self, state, data) + if state == FORM_VALID then + local memory = data.memory + if memory and memory ~= 0 then + _,_,n,unit = memory:find("([%d%.]+)([%l%u]+)") + if n then + unit = unit and unit:sub(1,1):upper() or "B" + if unit == "M" then + memory = tonumber(n) * 1024 * 1024 + elseif unit == "G" then + memory = tonumber(n) * 1024 * 1024 * 1024 + elseif unit == "K" then + memory = tonumber(n) * 1024 + else + memory = tonumber(n) + end + end + end + + request_body = { + BlkioWeight = tonumber(data.blkioweight), + NanoCPUs = tonumber(data.cpus)*10^9, + Memory = tonumber(memory), + CpuShares = tonumber(data.cpushares) + } + + docker:write_status("Containers: update " .. container_id .. "...") + local res = dk.containers:update({id = container_id, body = request_body}) + if res and res.code >= 300 then + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) + else + docker:clear_status() + end + luci.http.redirect(luci.dispatcher.build_url("admin/docker/container/"..container_id.."/resources")) + end + end + +elseif action == "file" then + m.submit = false + m.reset = false + s= m:section(SimpleSection) + s.template = "dockerman/container_file_manager" + s.container = container_id + m.redirect = nil +elseif action == "inspect" then + s = m:section(SimpleSection) + s.syslog = luci.jsonc.stringify(container_info, true) + s.title = translate("Container Inspect") + s.template = "dockerman/logs" + m.submit = false + m.reset = false +elseif action == "logs" then + local logs = "" + local query ={ + stdout = 1, + stderr = 1, + tail = 1000 + } + + s = m:section(SimpleSection) + + logs = dk.containers:logs({id = container_id, query = query}) + if logs.code == 200 then + s.syslog=logs.body + else + s.syslog="Get Logs ERROR\n"..logs.code..": "..logs.body + end + + s.title=translate("Container Logs") + s.template = "dockerman/logs" + m.submit = false + m.reset = false +elseif action == "console" then + m.submit = false + m.reset = false + local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil + local cmd_ttyd = luci.util.exec("command -v ttyd"):match("^.+ttyd") or nil + + if cmd_docker and cmd_ttyd and container_info.State.Status == "running" then + local cmd = "/bin/sh" + local uid + + s = m:section(SimpleSection) + + o = s:option(Value, "command", translate("Command")) + o:value("/bin/sh", "/bin/sh") + o:value("/bin/ash", "/bin/ash") + o:value("/bin/bash", "/bin/bash") + o.default = "/bin/sh" + o.forcewrite = true + o.write = function(self, section, value) + cmd = value + end + + o = s:option(Value, "uid", translate("UID")) + o.forcewrite = true + o.write = function(self, section, value) + uid = value + end + + o = s:option(Button, "connect") + o.render = function(self, section, scope) + self.inputstyle = "add" + self.title = " " + self.inputtitle = translate("Connect") + Button.render(self, section, scope) + end + o.write = function(self, section) + local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil + local cmd_ttyd = luci.util.exec("command -v ttyd"):match("^.+ttyd") or nil + + if not cmd_docker or not cmd_ttyd or cmd_docker:match("^%s+$") or cmd_ttyd:match("^%s+$") then + return + end + local uci = (require "luci.model.uci").cursor() + + local ttyd_ssl = uci:get("ttyd", "@ttyd[0]", "ssl") + local ttyd_ssl_key = uci:get("ttyd", "@ttyd[0]", "ssl_key") + local ttyd_ssl_cert = uci:get("ttyd", "@ttyd[0]", "ssl_cert") + + if ttyd_ssl == "1" and ttyd_ssl_cert and ttyd_ssl_key then + cmd_ttyd = string.format('%s -S -C %s -K %s', cmd_ttyd, ttyd_ssl_cert, ttyd_ssl_key) + end + + local pid = luci.util.trim(luci.util.exec("netstat -lnpt | grep :7682 | grep ttyd | tr -s ' ' | cut -d ' ' -f7 | cut -d'/' -f1")) + if pid and pid ~= "" then + luci.util.exec("kill -9 " .. pid) + end + + local hosts + local remote = uci:get_bool("dockerd", "dockerman", "remote_endpoint") or false + local host = nil + local port = nil + local socket = nil + + if remote then + host = uci:get("dockerd", "dockerman", "remote_host") or nil + port = uci:get("dockerd", "dockerman", "remote_port") or nil + else + socket = uci:get("dockerd", "dockerman", "socket_path") or "/var/run/docker.sock" + end + + if remote and host and port then + hosts = "tcp://" .. host .. ':'.. port + elseif socket then + hosts = "unix://" .. socket + else + return + end + + if uid and uid ~= "" then + uid = "-u " .. uid + else + uid = "" + end + + local start_cmd = string.format('%s -d 2 --once -p 7682 %s -H "%s" exec -it %s %s %s&', cmd_ttyd, cmd_docker, hosts, uid, container_id, cmd) + + os.execute(start_cmd) + + o = s:option(DummyValue, "console") + o.container_id = container_id + o.template = "dockerman/container_console" + end + end +elseif action == "stats" then + local response = dk.containers:top({id = container_id, query = {ps_args="-aux"}}) + local container_top + + if response.code == 200 then + container_top=response.body + else + response = dk.containers:top({id = container_id}) + if response.code == 200 then + container_top=response.body + end + end + + if type(container_top) == "table" then + s = m:section(SimpleSection) + s.container_id = container_id + s.template = "dockerman/container_stats" + table_stats = { + cpu={ + key=translate("CPU Useage"), + value='-' + }, + memory={ + key=translate("Memory Useage"), + value='-' + } + } + + container_top = response.body + s = m:section(Table, table_stats, translate("Stats")) + s:option(DummyValue, "key", translate("Stats")).width="33%" + s:option(DummyValue, "value") + top_section = m:section(Table, container_top.Processes, translate("TOP")) + for i, v in ipairs(container_top.Titles) do + top_section:option(DummyValue, i, translate(v)) + end + end + + m.submit = false + m.reset = false +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua new file mode 100755 index 000000000..47f634f8b --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua @@ -0,0 +1,284 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local http = require "luci.http" +local docker = require "luci.model.docker" + +local m, s, o +local images, networks, containers, res, lost_state +local urlencode = luci.http.protocol and luci.http.protocol.urlencode or luci.util.urlencode +local dk = docker.new() + +if dk:_ping().code ~= 200 then + lost_state = true +else + res = dk.images:list() + if res and res.code and res.code < 300 then + images = res.body + end + + res = dk.networks:list() + if res and res.code and res.code < 300 then + networks = res.body + end + + res = dk.containers:list({ + query = { + all = true + } + }) + if res and res.code and res.code < 300 then + containers = res.body + end +end + +function get_containers() + local data = {} + if type(containers) ~= "table" then + return nil + end + + for i, v in ipairs(containers) do + local index = (10^12 - v.Created) .. "_id_" .. v.Id + + data[index]={} + data[index]["_selected"] = 0 + data[index]["_id"] = v.Id:sub(1,12) + -- data[index]["name"] = v.Names[1]:sub(2) + data[index]["_status"] = v.Status + + if v.Status:find("^Up") then + data[index]["_name"] = ""..v.Names[1]:sub(2).."" + data[index]["_status"] = "".. data[index]["_status"] .. "" .. "


" + else + data[index]["_name"] = ""..v.Names[1]:sub(2).."" + data[index]["_status"] = ''.. data[index]["_status"] .. "" + end + + if (type(v.NetworkSettings) == "table" and type(v.NetworkSettings.Networks) == "table") then + for networkname, netconfig in pairs(v.NetworkSettings.Networks) do + data[index]["_network"] = (data[index]["_network"] ~= nil and (data[index]["_network"] .." | ") or "").. networkname .. (netconfig.IPAddress ~= "" and (": " .. netconfig.IPAddress) or "") + end + end + + -- networkmode = v.HostConfig.NetworkMode ~= "default" and v.HostConfig.NetworkMode or "bridge" + -- data[index]["_network"] = v.NetworkSettings.Networks[networkmode].IPAddress or nil + -- local _, _, image = v.Image:find("^sha256:(.+)") + -- if image ~= nil then + -- image=image:sub(1,12) + -- end + + if v.Ports and next(v.Ports) ~= nil then + data[index]["_ports"] = nil + local ip = require "luci.ip" + for _,v2 in ipairs(v.Ports) do + -- display ipv4 only + if ip.new(v2.IP or "0.0.0.0"):is4() then + data[index]["_ports"] = (data[index]["_ports"] and (data[index]["_ports"] .. ", ") or "") + .. ((v2.PublicPort and v2.Type and v2.Type == "tcp") and ('') or "") + .. (v2.PublicPort and (v2.PublicPort .. ":") or "") .. (v2.PrivatePort and (v2.PrivatePort .."/") or "") .. (v2.Type and v2.Type or "") + .. ((v2.PublicPort and v2.Type and v2.Type == "tcp")and "" or "") + end + end + end + + for ii,iv in ipairs(images) do + if iv.Id == v.ImageID then + data[index]["_image"] = iv.RepoTags and iv.RepoTags[1] or (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":<none>") + end + end + data[index]["_id_name"] = ''.. data[index]["_name"] .. "
ID: " .. data[index]["_id"] + .. "

Image: " .. (data[index]["_image"] or "<none>") + .. "
" + + if type(v.Mounts) == "table" and next(v.Mounts) then + for _, v2 in pairs(v.Mounts) do + if v2.Type ~= "volume" then + local v_sorce_d, v_dest_d + local v_sorce = "" + local v_dest = "" + for v_sorce_d in v2["Source"]:gmatch('[^/]+') do + if v_sorce_d and #v_sorce_d > 12 then + v_sorce = v_sorce .. "/" .. v_sorce_d:sub(1,8) .. ".." + else + v_sorce = v_sorce .."/".. v_sorce_d + end + end + for v_dest_d in v2["Destination"]:gmatch('[^/]+') do + if v_dest_d and #v_dest_d > 12 then + v_dest = v_dest .. "/" .. v_dest_d:sub(1,8) .. ".." + else + v_dest = v_dest .."/".. v_dest_d + end + end + data[index]["_mounts"] = (data[index]["_mounts"] and (data[index]["_mounts"] .. "
") or "") .. '' .. v_sorce .. "→" .. v_dest..'' + end + end + end + + data[index]["_image_id"] = v.ImageID:sub(8,20) + data[index]["_command"] = v.Command + end + return data +end + +local container_list = not lost_state and get_containers() or {} + +m = SimpleForm("docker", + translate("Docker - Containers"), + translate("This page displays all containers that have been created on the connected docker host.")) +m.submit=false +m.reset=false +m:append(Template("dockerman/containers_running_stats")) + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err=docker:read_status() +s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(Table, container_list, translate("Containers")) +s.nodescr=true +s.config="containers" + +o = s:option(Flag, "_selected","") +o.disabled = 0 +o.enabled = 1 +o.default = 0 +o.width = "1%" +o.write=function(self, section, value) + container_list[section]._selected = value +end + +-- o = s:option(DummyValue, "_id", translate("ID")) +-- o.width="10%" + +-- o = s:option(DummyValue, "_name", translate("Container Name")) +-- o.rawhtml = true + +o = s:option(DummyValue, "_id_name", translate("Container Info")) +o.rawhtml = true +o.width="15%" + +o = s:option(DummyValue, "_status", translate("Status")) +o.width="15%" +o.rawhtml=true + +o = s:option(DummyValue, "_network", translate("Network")) +o.width="10%" + +o = s:option(DummyValue, "_ports", translate("Ports")) +o.width="5%" +o.rawhtml = true +o = s:option(DummyValue, "_mounts", translate("Mounts")) +o.width="25%" +o.rawhtml = true + +-- o = s:option(DummyValue, "_image", translate("Image")) +-- o.width="8%" + +o = s:option(DummyValue, "_command", translate("Command")) +o.width="15%" + +local start_stop_remove = function(m, cmd) + local container_selected = {} + -- 遍历table中sectionid + for k in pairs(container_list) do + -- 得到选中项的名字 + if container_list[k]._selected == 1 then + container_selected[#container_selected + 1] = container_list[k]["_id"] + end + end + if #container_selected > 0 then + local success = true + + docker:clear_status() + for _, cont in ipairs(container_selected) do + docker:append_status("Containers: " .. cmd .. " " .. cont .. "...") + local res = dk.containers[cmd](dk, {id = cont}) + if res and res.code and res.code >= 300 then + success = false + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "\n") + else + docker:append_status("done\n") + end + end + + if success then + docker:clear_status() + end + + luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers")) + end +end + +s = m:section(Table,{{}}) +s.notitle=true +s.rowcolors=false +s.template="cbi/nullsection" + +o = s:option(Button, "_new") +o.inputtitle = translate("Add") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "add" +o.forcewrite = true +o.write = function(self, section) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) +end +o.disable = lost_state + +o = s:option(Button, "_start") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle = translate("Start") +o.inputstyle = "apply" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"start") +end +o.disable = lost_state + +o = s:option(Button, "_restart") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle = translate("Restart") +o.inputstyle = "reload" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"restart") +end +o.disable = lost_state + +o = s:option(Button, "_stop") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle = translate("Stop") +o.inputstyle = "reset" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"stop") +end +o.disable = lost_state + +o = s:option(Button, "_kill") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle = translate("Kill") +o.inputstyle = "reset" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m,"kill") +end +o.disable = lost_state + +o = s:option(Button, "_remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputtitle = translate("Remove") +o.inputstyle = "remove" +o.forcewrite = true +o.write = function(self, section) + start_stop_remove(m, "remove") +end +o.disable = lost_state + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua new file mode 100755 index 000000000..c3d3eab0d --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua @@ -0,0 +1,284 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" +local dk = docker.new() + +local containers, images, res, lost_state +local m, s, o + +if dk:_ping().code ~= 200 then + lost_state = true +else + res = dk.images:list() + if res and res.code and res.code < 300 then + images = res.body + end + + res = dk.containers:list({ query = { all = true } }) + if res and res.code and res.code < 300 then + containers = res.body + end +end + +function get_images() + local data = {} + + for i, v in ipairs(images) do + local index = v.Created .. v.Id + + data[index]={} + data[index]["_selected"] = 0 + data[index]["id"] = v.Id:sub(8) + data[index]["_id"] = '' .. v.Id:sub(8,20) .. '' + + if v.RepoTags and next(v.RepoTags)~=nil then + for i, v1 in ipairs(v.RepoTags) do + data[index]["_tags"] =(data[index]["_tags"] and ( data[index]["_tags"] .. "
" )or "") .. ((v1:match("") or (#v.RepoTags == 1)) and v1 or ('' .. v1 .. '')) + + if not data[index]["tag"] then + data[index]["tag"] = v1 + end + end + else + data[index]["_tags"] = v.RepoDigests[1] and v.RepoDigests[1]:match("^(.-)@.+") + data[index]["_tags"] = (data[index]["_tags"] and data[index]["_tags"] or "" ).. ":" + end + + data[index]["_tags"] = data[index]["_tags"]:gsub("","<none>") + for ci,cv in ipairs(containers) do + if v.Id == cv.ImageID then + data[index]["_containers"] = (data[index]["_containers"] and (data[index]["_containers"] .. " | ") or "").. + ''.. cv.Names[1]:sub(2).."" + end + end + + data[index]["_size"] = string.format("%.2f", tostring(v.Size/1024/1024)).."MB" + data[index]["_created"] = os.date("%Y/%m/%d %H:%M:%S",v.Created) + end + + return data +end + +local image_list = not lost_state and get_images() or {} + +m = SimpleForm("docker", + translate("Docker - Images"), + translate("On this page all images are displayed that are available on the system and with which a container can be created.")) +m.submit=false +m.reset=false + +local pull_value={ + _image_tag_name="", + _registry="index.docker.io" +} + +s = m:section(SimpleSection, + translate("Pull Image"), + translate("By entering a valid image name with the corresponding version, the docker image can be downloaded from the configured registry.")) +s.template="cbi/nullsection" + +o = s:option(Value, "_image_tag_name") +o.template = "dockerman/cbi/inlinevalue" +o.placeholder="lisaac/luci:latest" +o.write = function(self, section, value) + local hastag = value:find(":") + + if not hastag then + value = value .. ":latest" + end + pull_value["_image_tag_name"] = value +end + +o = s:option(Button, "_pull") +o.inputtitle= translate("Pull") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "add" +o.disable = lost_state +o.write = function(self, section) + local tag = pull_value["_image_tag_name"] + local json_stringify = luci.jsonc and luci.jsonc.stringify + + if tag and tag ~= "" then + docker:write_status("Images: " .. "pulling" .. " " .. tag .. "...\n") + local res = dk.images:create({query = {fromImage=tag}}, docker.pull_image_show_status_cb) + + if res and res.code and res.code == 200 and (res.body[#res.body] and not res.body[#res.body].error and res.body[#res.body].status and (res.body[#res.body].status == "Status: Downloaded newer image for ".. tag)) then + docker:clear_status() + else + docker:append_status("code:" .. res.code.." ".. (res.body[#res.body] and res.body[#res.body].error or (res.body.message or res.message)).. "\n") + end + else + docker:append_status("code: 400 please input the name of image name!") + end + + luci.http.redirect(luci.dispatcher.build_url("admin/docker/images")) +end + +s = m:section(SimpleSection, + translate("Import Image"), + translate("When pressing the Import button, both a local image can be loaded onto the system and a valid image tar can be downloaded from remote.")) + +o = s:option(DummyValue, "_image_import") +o.template = "dockerman/images_import" +o.disable = lost_state + +s = m:section(Table, image_list, translate("Images overview")) + +o = s:option(Flag, "_selected","") +o.disabled = 0 +o.enabled = 1 +o.default = 0 +o.write = function(self, section, value) + image_list[section]._selected = value +end + +o = s:option(DummyValue, "_id", translate("ID")) +o.rawhtml = true + +o = s:option(DummyValue, "_tags", translate("RepoTags")) +o.rawhtml = true + +o = s:option(DummyValue, "_containers", translate("Containers")) +o.rawhtml = true + +o = s:option(DummyValue, "_size", translate("Size")) + +o = s:option(DummyValue, "_created", translate("Created")) + +local remove_action = function(force) + local image_selected = {} + + for k in pairs(image_list) do + if image_list[k]._selected == 1 then + image_selected[#image_selected+1] = (image_list[k]["_tags"]:match("
") or image_list[k]["_tags"]:match("<none>")) and image_list[k].id or image_list[k].tag + end + end + + if next(image_selected) ~= nil then + local success = true + + docker:clear_status() + for _, img in ipairs(image_selected) do + local query + docker:append_status("Images: " .. "remove" .. " " .. img .. "...") + + if force then + query = {force = true} + end + + local msg = dk.images:remove({ + id = img, + query = query + }) + if msg and msg.code ~= 200 then + docker:append_status("code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "\n") + success = false + else + docker:append_status("done\n") + end + end + + if success then + docker:clear_status() + end + + luci.http.redirect(luci.dispatcher.build_url("admin/docker/images")) + end +end + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err = docker:read_status() +s.err = s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(Table,{{}}) +s.notitle=true +s.rowcolors=false +s.template="cbi/nullsection" + +o = s:option(Button, "remove") +o.inputtitle= translate("Remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "remove" +o.forcewrite = true +o.write = function(self, section) + remove_action() +end +o.disable = lost_state + +o = s:option(Button, "forceremove") +o.inputtitle= translate("Force Remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "remove" +o.forcewrite = true +o.write = function(self, section) + remove_action(true) +end +o.disable = lost_state + +o = s:option(Button, "save") +o.inputtitle= translate("Save") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "edit" +o.disable = lost_state +o.forcewrite = true +o.write = function (self, section) + local image_selected = {} + + for k in pairs(image_list) do + if image_list[k]._selected == 1 then + image_selected[#image_selected + 1] = image_list[k].id + end + end + + if next(image_selected) ~= nil then + local names, first, show_name + + for _, img in ipairs(image_selected) do + names = names and (names .. "&names=".. img) or img + end + if #image_selected > 1 then + show_name = "images" + else + show_name = image_selected[1] + end + local cb = function(res, chunk) + if res and res.code and res.code == 200 then + if not first then + first = true + luci.http.header('Content-Disposition', 'inline; filename="'.. show_name .. '.tar"') + luci.http.header('Content-Type', 'application\/x-tar') + end + luci.ltn12.pump.all(chunk, luci.http.write) + else + if not first then + first = true + luci.http.prepare_content("text/plain") + end + luci.ltn12.pump.all(chunk, luci.http.write) + end + end + + docker:write_status("Images: " .. "save" .. " " .. table.concat(image_selected, "\n") .. "...") + local msg = dk.images:get({query = {names = names}}, cb) + if msg and msg.code and msg.code ~= 200 then + docker:append_status("code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "\n") + else + docker:clear_status() + end + end +end + +o = s:option(Button, "load") +o.inputtitle= translate("Load") +o.template = "dockerman/images_load" +o.inputstyle = "add" +o.disable = lost_state + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua new file mode 100755 index 000000000..37702c783 --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua @@ -0,0 +1,159 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" + +local m, s, o +local networks, dk, res, lost_state + +dk = docker.new() + +if dk:_ping().code ~= 200 then + lost_state = true +else + res = dk.networks:list() + if res and res.code and res.code < 300 then + networks = res.body + end +end + +local get_networks = function () + local data = {} + + if type(networks) ~= "table" then + return nil + end + + for i, v in ipairs(networks) do + local index = v.Created .. v.Id + + data[index]={} + data[index]["_selected"] = 0 + data[index]["_id"] = v.Id:sub(1,12) + data[index]["_name"] = v.Name + data[index]["_driver"] = v.Driver + + if v.Driver == "bridge" then + data[index]["_interface"] = v.Options["com.docker.network.bridge.name"] + elseif v.Driver == "macvlan" then + data[index]["_interface"] = v.Options.parent + end + + data[index]["_subnet"] = v.IPAM and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil + data[index]["_gateway"] = v.IPAM and v.IPAM.Config[1] and v.IPAM.Config[1].Gateway or nil + end + + return data +end + +local network_list = not lost_state and get_networks() or {} + +m = SimpleForm("docker", + translate("Docker - Networks"), + translate("This page displays all docker networks that have been created on the connected docker host.")) +m.submit=false +m.reset=false + +s = m:section(Table, network_list, translate("Networks overview")) +s.nodescr=true + +o = s:option(Flag, "_selected","") +o.template = "dockerman/cbi/xfvalue" +o.disabled = 0 +o.enabled = 1 +o.default = 0 +o.render = function(self, section, scope) + self.disable = 0 + if network_list[section]["_name"] == "bridge" or network_list[section]["_name"] == "none" or network_list[section]["_name"] == "host" then + self.disable = 1 + end + Flag.render(self, section, scope) +end +o.write = function(self, section, value) + network_list[section]._selected = value +end + +o = s:option(DummyValue, "_id", translate("ID")) + +o = s:option(DummyValue, "_name", translate("Network Name")) + +o = s:option(DummyValue, "_driver", translate("Driver")) + +o = s:option(DummyValue, "_interface", translate("Parent Interface")) + +o = s:option(DummyValue, "_subnet", translate("Subnet")) + +o = s:option(DummyValue, "_gateway", translate("Gateway")) + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err = docker:read_status() +s.err = s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(Table,{{}}) +s.notitle=true +s.rowcolors=false +s.template="cbi/nullsection" + +o = s:option(Button, "_new") +o.inputtitle= translate("New") +o.template = "dockerman/cbi/inlinebutton" +o.notitle=true +o.inputstyle = "add" +o.forcewrite = true +o.disable = lost_state +o.write = function(self, section) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newnetwork")) +end + +o = s:option(Button, "_remove") +o.inputtitle= translate("Remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "remove" +o.forcewrite = true +o.disable = lost_state +o.write = function(self, section) + local network_selected = {} + local network_name_selected = {} + local network_driver_selected = {} + + for k in pairs(network_list) do + if network_list[k]._selected == 1 then + network_selected[#network_selected + 1] = network_list[k]._id + network_name_selected[#network_name_selected + 1] = network_list[k]._name + network_driver_selected[#network_driver_selected + 1] = network_list[k]._driver + end + end + + if next(network_selected) ~= nil then + local success = true + docker:clear_status() + + for ii, net in ipairs(network_selected) do + docker:append_status("Networks: " .. "remove" .. " " .. net .. "...") + local res = dk.networks["remove"](dk, {id = net}) + + if res and res.code and res.code >= 300 then + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "\n") + success = false + else + docker:append_status("done\n") + if network_driver_selected[ii] == "macvlan" then + docker.remove_macvlan_interface(network_name_selected[ii]) + end + end + end + + if success then + docker:clear_status() + end + luci.http.redirect(luci.dispatcher.build_url("admin/docker/networks")) + end +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua new file mode 100755 index 000000000..bfd1bf2a1 --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua @@ -0,0 +1,923 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" + +local m, s, o + +local dk = docker.new() + +local cmd_line = table.concat(arg, '/') +local images, networks +local create_body = {} + +if dk:_ping().code ~= 200 then + lost_state = true + images = {} + networks = {} +else + images = dk.images:list().body + networks = dk.networks:list().body +end + +local is_quot_complete = function(str) + local num = 0, w + require "math" + + if not str then + return true + end + + local num = 0, w + for w in str:gmatch("\"") do + num = num + 1 + end + + if math.fmod(num, 2) ~= 0 then + return false + end + + num = 0 + for w in str:gmatch("\'") do + num = num + 1 + end + + if math.fmod(num, 2) ~= 0 then + return false + end + + return true +end + +function contains(list, x) + for _, v in pairs(list) do + if v == x then + return true + end + end + return false +end + +local resolve_cli = function(cmd_line) + local config = { + advance = 1 + } + + local key_no_val = { + 't', + 'd', + 'i', + 'tty', + 'rm', + 'read_only', + 'interactive', + 'init', + 'help', + 'detach', + 'privileged', + 'P', + 'publish_all', + } + + local key_with_val = { + 'sysctl', + 'add_host', + 'a', + 'attach', + 'blkio_weight_device', + 'cap_add', + 'cap_drop', + 'device', + 'device_cgroup_rule', + 'device_read_bps', + 'device_read_iops', + 'device_write_bps', + 'device_write_iops', + 'dns', + 'dns_option', + 'dns_search', + 'e', + 'env', + 'env_file', + 'expose', + 'group_add', + 'l', + 'label', + 'label_file', + 'link', + 'link_local_ip', + 'log_driver', + 'log_opt', + 'network_alias', + 'p', + 'publish', + 'security_opt', + 'storage_opt', + 'tmpfs', + 'v', + 'volume', + 'volumes_from', + 'blkio_weight', + 'cgroup_parent', + 'cidfile', + 'cpu_period', + 'cpu_quota', + 'cpu_rt_period', + 'cpu_rt_runtime', + 'c', + 'cpu_shares', + 'cpus', + 'cpuset_cpus', + 'cpuset_mems', + 'detach_keys', + 'disable_content_trust', + 'domainname', + 'entrypoint', + 'gpus', + 'health_cmd', + 'health_interval', + 'health_retries', + 'health_start_period', + 'health_timeout', + 'h', + 'hostname', + 'ip', + 'ip6', + 'ipc', + 'isolation', + 'kernel_memory', + 'mac_address', + 'm', + 'memory', + 'memory_reservation', + 'memory_swap', + 'memory_swappiness', + 'mount', + 'name', + 'network', + 'no_healthcheck', + 'oom_kill_disable', + 'oom_score_adj', + 'pid', + 'pids_limit', + 'restart', + 'runtime', + 'shm_size', + 'sig_proxy', + 'stop_signal', + 'stop_timeout', + 'ulimit', + 'u', + 'user', + 'userns', + 'uts', + 'volume_driver', + 'w', + 'workdir' + } + + local key_abb = { + net='network', + a='attach', + c='cpu-shares', + d='detach', + e='env', + h='hostname', + i='interactive', + l='label', + m='memory', + p='publish', + P='publish_all', + t='tty', + u='user', + v='volume', + w='workdir' + } + + local key_with_list = { + 'sysctl', + 'add_host', + 'a', + 'attach', + 'blkio_weight_device', + 'cap_add', + 'cap_drop', + 'device', + 'device_cgroup_rule', + 'device_read_bps', + 'device_read_iops', + 'device_write_bps', + 'device_write_iops', + 'dns', + 'dns_optiondns_search', + 'e', + 'env', + 'env_file', + 'expose', + 'group_add', + 'l', + 'label', + 'label_file', + 'link', + 'link_local_ip', + 'log_opt', + 'network_alias', + 'p', + 'publish', + 'security_opt', + 'storage_opt', + 'tmpfs', + 'v', + 'volume', + 'volumes_from', + } + + local key = nil + local _key = nil + local val = nil + local is_cmd = false + + cmd_line = cmd_line:match("^DOCKERCLI%s+(.+)") + for w in cmd_line:gmatch("[^%s]+") do + if w =='\\' then + elseif not key and not _key and not is_cmd then + --key=val + key, val = w:match("^%-%-([%lP%-]-)=(.+)") + if not key then + --key val + key = w:match("^%-%-([%lP%-]+)") + if not key then + -- -v val + key = w:match("^%-([%lP%-]+)") + if key then + -- for -dit + if key:match("i") or key:match("t") or key:match("d") then + if key:match("i") then + config[key_abb["i"]] = true + key:gsub("i", "") + end + if key:match("t") then + config[key_abb["t"]] = true + key:gsub("t", "") + end + if key:match("d") then + config[key_abb["d"]] = true + key:gsub("d", "") + end + if key:match("P") then + config[key_abb["P"]] = true + key:gsub("P", "") + end + if key == "" then + key = nil + end + end + end + end + end + if key then + key = key:gsub("-","_") + key = key_abb[key] or key + if contains(key_no_val, key) then + config[key] = true + val = nil + key = nil + elseif contains(key_with_val, key) then + -- if key == "cap_add" then config.privileged = true end + else + key = nil + val = nil + end + else + config.image = w + key = nil + val = nil + is_cmd = true + end + elseif (key or _key) and not is_cmd then + if key == "mount" then + -- we need resolve mount options here + -- type=bind,source=/source,target=/app + local _type = w:match("^type=([^,]+),") or "bind" + local source = (_type ~= "tmpfs") and (w:match("source=([^,]+),") or w:match("src=([^,]+),")) or "" + local target = w:match(",target=([^,]+)") or w:match(",dst=([^,]+)") or w:match(",destination=([^,]+)") or "" + local ro = w:match(",readonly") and "ro" or nil + + if source and target then + if _type ~= "tmpfs" then + local bind_propagation = (_type == "bind") and w:match(",bind%-propagation=([^,]+)") or nil + val = source..":"..target .. ((ro or bind_propagation) and (":" .. (ro and ro or "") .. (((ro and bind_propagation) and "," or "") .. (bind_propagation and bind_propagation or ""))or "")) + else + local tmpfs_mode = w:match(",tmpfs%-mode=([^,]+)") or nil + local tmpfs_size = w:match(",tmpfs%-size=([^,]+)") or nil + key = "tmpfs" + val = target .. ((tmpfs_mode or tmpfs_size) and (":" .. (tmpfs_mode and ("mode=" .. tmpfs_mode) or "") .. ((tmpfs_mode and tmpfs_size) and "," or "") .. (tmpfs_size and ("size=".. tmpfs_size) or "")) or "") + if not config[key] then + config[key] = {} + end + table.insert( config[key], val ) + key = nil + val = nil + end + end + else + val = w + end + elseif is_cmd then + config["command"] = (config["command"] and (config["command"] .. " " )or "") .. w + end + if (key or _key) and val then + key = _key or key + if contains(key_with_list, key) then + if not config[key] then + config[key] = {} + end + if _key then + config[key][#config[key]] = config[key][#config[key]] .. " " .. w + else + table.insert( config[key], val ) + end + if is_quot_complete(config[key][#config[key]]) then + config[key][#config[key]] = config[key][#config[key]]:gsub("[\"\']", "") + _key = nil + else + _key = key + end + else + config[key] = (config[key] and (config[key] .. " ") or "") .. val + if is_quot_complete(config[key]) then + config[key] = config[key]:gsub("[\"\']", "") + _key = nil + else + _key = key + end + end + key = nil + val = nil + end + end + + return config +end + +local default_config = {} + +if cmd_line and cmd_line:match("^DOCKERCLI.+") then + default_config = resolve_cli(cmd_line) +elseif cmd_line and cmd_line:match("^duplicate/[^/]+$") then + local container_id = cmd_line:match("^duplicate/(.+)") + create_body = dk:containers_duplicate_config({id = container_id}) or {} + if not create_body.HostConfig then + create_body.HostConfig = {} + end + + if next(create_body) ~= nil then + default_config.name = nil + default_config.image = create_body.Image + default_config.hostname = create_body.Hostname + default_config.tty = create_body.Tty and true or false + default_config.interactive = create_body.OpenStdin and true or false + default_config.privileged = create_body.HostConfig.Privileged and true or false + default_config.restart = create_body.HostConfig.RestartPolicy and create_body.HostConfig.RestartPolicy.name or nil + -- default_config.network = create_body.HostConfig.NetworkMode == "default" and "bridge" or create_body.HostConfig.NetworkMode + -- if container has leave original network, and add new network, .HostConfig.NetworkMode is INcorrect, so using first child of .NetworkingConfig.EndpointsConfig + default_config.network = create_body.NetworkingConfig and create_body.NetworkingConfig.EndpointsConfig and next(create_body.NetworkingConfig.EndpointsConfig) or nil + default_config.ip = default_config.network and default_config.network ~= "bridge" and default_config.network ~= "host" and default_config.network ~= "null" and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig and create_body.NetworkingConfig.EndpointsConfig[default_config.network].IPAMConfig.IPv4Address or nil + default_config.link = create_body.HostConfig.Links + default_config.env = create_body.Env + default_config.dns = create_body.HostConfig.Dns + default_config.volume = create_body.HostConfig.Binds + default_config.cap_add = create_body.HostConfig.CapAdd + default_config.publish_all = create_body.HostConfig.PublishAllPorts + + if create_body.HostConfig.Sysctls and type(create_body.HostConfig.Sysctls) == "table" then + default_config.sysctl = {} + for k, v in pairs(create_body.HostConfig.Sysctls) do + table.insert( default_config.sysctl, k.."="..v ) + end + end + if create_body.HostConfig.LogConfig then + if create_body.HostConfig.LogConfig.Config and type(create_body.HostConfig.LogConfig.Config) == "table" then + default_config.log_opt = {} + for k, v in pairs(create_body.HostConfig.LogConfig.Config) do + table.insert( default_config.log_opt, k.."="..v ) + end + end + default_config.log_driver = create_body.HostConfig.LogConfig.Type or nil + end + + if create_body.HostConfig.PortBindings and type(create_body.HostConfig.PortBindings) == "table" then + default_config.publish = {} + for k, v in pairs(create_body.HostConfig.PortBindings) do + for x, y in ipairs(v) do + table.insert( default_config.publish, y.HostPort..":"..k:match("^(%d+)/.+").."/"..k:match("^%d+/(.+)") ) + end + end + end + + default_config.user = create_body.User or nil + default_config.command = create_body.Cmd and type(create_body.Cmd) == "table" and table.concat(create_body.Cmd, " ") or nil + default_config.advance = 1 + default_config.cpus = create_body.HostConfig.NanoCPUs + default_config.cpu_shares = create_body.HostConfig.CpuShares + default_config.memory = create_body.HostConfig.Memory + default_config.blkio_weight = create_body.HostConfig.BlkioWeight + + if create_body.HostConfig.Devices and type(create_body.HostConfig.Devices) == "table" then + default_config.device = {} + for _, v in ipairs(create_body.HostConfig.Devices) do + table.insert( default_config.device, v.PathOnHost..":"..v.PathInContainer..(v.CgroupPermissions ~= "" and (":" .. v.CgroupPermissions) or "") ) + end + end + + if create_body.HostConfig.Tmpfs and type(create_body.HostConfig.Tmpfs) == "table" then + default_config.tmpfs = {} + for k, v in pairs(create_body.HostConfig.Tmpfs) do + table.insert( default_config.tmpfs, k .. (v~="" and ":" or "")..v ) + end + end + end +end + +m = SimpleForm("docker", translate("Docker - Containers")) +m.redirect = luci.dispatcher.build_url("admin", "docker", "containers") +if lost_state then + m.submit=false + m.reset=false +end + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err=docker:read_status() +s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(SimpleSection, translate("Create new docker container")) +s.addremove = true +s.anonymous = true + +o = s:option(DummyValue,"cmd_line", translate("Resolve CLI")) +o.rawhtml = true +o.template = "dockerman/newcontainer_resolve" + +o = s:option(Value, "name", translate("Container Name")) +o.rmempty = true +o.default = default_config.name or nil + +o = s:option(Flag, "interactive", translate("Interactive (-i)")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = default_config.interactive and 1 or 0 + +o = s:option(Flag, "tty", translate("TTY (-t)")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = default_config.tty and 1 or 0 + +o = s:option(Value, "image", translate("Docker Image")) +o.rmempty = true +o.default = default_config.image or nil +for _, v in ipairs (images) do + if v.RepoTags then + o:value(v.RepoTags[1], v.RepoTags[1]) + end +end + +o = s:option(Flag, "_force_pull", translate("Always pull image first")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = 0 + +o = s:option(Flag, "privileged", translate("Privileged")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = default_config.privileged and 1 or 0 + +o = s:option(ListValue, "restart", translate("Restart Policy")) +o.rmempty = true +o:value("no", "No") +o:value("unless-stopped", "Unless stopped") +o:value("always", "Always") +o:value("on-failure", "On failure") +o.default = default_config.restart or "unless-stopped" + +local d_network = s:option(ListValue, "network", translate("Networks")) +d_network.rmempty = true +d_network.default = default_config.network or "bridge" + +local d_ip = s:option(Value, "ip", translate("IPv4 Address")) +d_ip.datatype="ip4addr" +d_ip:depends("network", "nil") +d_ip.default = default_config.ip or nil + +o = s:option(DynamicList, "link", translate("Links with other containers")) +o.placeholder = "container_name:alias" +o.rmempty = true +o:depends("network", "bridge") +o.default = default_config.link or nil + +o = s:option(DynamicList, "dns", translate("Set custom DNS servers")) +o.placeholder = "8.8.8.8" +o.rmempty = true +o.default = default_config.dns or nil + +o = s:option(Value, "user", + translate("User(-u)"), + translate("The user that commands are run as inside the container.(format: name|uid[:group|gid])")) +o.placeholder = "1000:1000" +o.rmempty = true +o.default = default_config.user or nil + +o = s:option(DynamicList, "env", + translate("Environmental Variable(-e)"), + translate("Set environment variables to inside the container")) +o.placeholder = "TZ=Asia/Shanghai" +o.rmempty = true +o.default = default_config.env or nil + +o = s:option(DynamicList, "volume", + translate("Bind Mount(-v)"), + translate("Bind mount a volume")) +o.placeholder = "/media:/media:slave" +o.rmempty = true +o.default = default_config.volume or nil + +local d_publish = s:option(DynamicList, "publish", + translate("Exposed Ports(-p)"), + translate("Publish container's port(s) to the host")) +d_publish.placeholder = "2200:22/tcp" +d_publish.rmempty = true +d_publish.default = default_config.publish or nil + +o = s:option(Value, "command", translate("Run command")) +o.placeholder = "/bin/sh init.sh" +o.rmempty = true +o.default = default_config.command or nil + +o = s:option(Flag, "advance", translate("Advance")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = default_config.advance or 0 + +o = s:option(Value, "hostname", + translate("Host Name"), + translate("The hostname to use for the container")) +o.rmempty = true +o.default = default_config.hostname or nil +o:depends("advance", 1) + +o = s:option(Flag, "publish_all", + translate("Exposed All Ports(-P)"), + translate("Allocates an ephemeral host port for all of a container's exposed ports")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = default_config.publish_all and 1 or 0 +o:depends("advance", 1) + +o = s:option(DynamicList, "device", + translate("Device(--device)"), + translate("Add host device to the container")) +o.placeholder = "/dev/sda:/dev/xvdc:rwm" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.device or nil + +o = s:option(DynamicList, "tmpfs", + translate("Tmpfs(--tmpfs)"), + translate("Mount tmpfs directory")) +o.placeholder = "/run:rw,noexec,nosuid,size=65536k" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.tmpfs or nil + +o = s:option(DynamicList, "sysctl", + translate("Sysctl(--sysctl)"), + translate("Sysctls (kernel parameters) options")) +o.placeholder = "net.ipv4.ip_forward=1" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.sysctl or nil + +o = s:option(DynamicList, "cap_add", + translate("CAP-ADD(--cap-add)"), + translate("A list of kernel capabilities to add to the container")) +o.placeholder = "NET_ADMIN" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.cap_add or nil + +o = s:option(Value, "cpus", + translate("CPUs"), + translate("Number of CPUs. Number is a fractional number. 0.000 means no limit")) +o.placeholder = "1.5" +o.rmempty = true +o:depends("advance", 1) +o.datatype="ufloat" +o.default = default_config.cpus or nil + +o = s:option(Value, "cpu_shares", + translate("CPU Shares Weight"), + translate("CPU shares relative weight, if 0 is set, the system will ignore the value and use the default of 1024")) +o.placeholder = "1024" +o.rmempty = true +o:depends("advance", 1) +o.datatype="uinteger" +o.default = default_config.cpu_shares or nil + +o = s:option(Value, "memory", + translate("Memory"), + translate("Memory limit (format: []). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M")) +o.placeholder = "128m" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.memory or nil + +o = s:option(Value, "blkio_weight", + translate("Block IO Weight"), + translate("Block IO weight (relative weight) accepts a weight value between 10 and 1000")) +o.placeholder = "500" +o.rmempty = true +o:depends("advance", 1) +o.datatype="uinteger" +o.default = default_config.blkio_weight or nil + +o = s:option(Value, "log_driver", + translate("Logging driver"), + translate("The logging driver for the container")) +o.placeholder = "json-file" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.log_driver or nil + +o = s:option(DynamicList, "log_opt", + translate("Log driver options"), + translate("The logging configuration for this container")) +o.placeholder = "max-size=1m" +o.rmempty = true +o:depends("advance", 1) +o.default = default_config.log_opt or nil + +for _, v in ipairs (networks) do + if v.Name then + local parent = v.Options and v.Options.parent or nil + local ip = v.IPAM and v.IPAM.Config and v.IPAM.Config[1] and v.IPAM.Config[1].Subnet or nil + ipv6 = v.IPAM and v.IPAM.Config and v.IPAM.Config[2] and v.IPAM.Config[2].Subnet or nil + local network_name = v.Name .. " | " .. v.Driver .. (parent and (" | " .. parent) or "") .. (ip and (" | " .. ip) or "").. (ipv6 and (" | " .. ipv6) or "") + d_network:value(v.Name, network_name) + + if v.Name ~= "none" and v.Name ~= "bridge" and v.Name ~= "host" then + d_ip:depends("network", v.Name) + end + + if v.Driver == "bridge" then + d_publish:depends("network", v.Name) + end + end +end + +m.handle = function(self, state, data) + if state ~= FORM_VALID then + return + end + + local tmp + local name = data.name or ("luci_" .. os.date("%Y%m%d%H%M%S")) + local hostname = data.hostname + local tty = type(data.tty) == "number" and (data.tty == 1 and true or false) or default_config.tty or false + local publish_all = type(data.publish_all) == "number" and (data.publish_all == 1 and true or false) or default_config.publish_all or false + local interactive = type(data.interactive) == "number" and (data.interactive == 1 and true or false) or default_config.interactive or false + local image = data.image + local user = data.user + + if image and not image:match(".-:.+") then + image = image .. ":latest" + end + + local privileged = type(data.privileged) == "number" and (data.privileged == 1 and true or false) or default_config.privileged or false + local restart = data.restart + local env = data.env + local dns = data.dns + local cap_add = data.cap_add + local sysctl = {} + local log_driver = data.log_driver + + tmp = data.sysctl + if type(tmp) == "table" then + for i, v in ipairs(tmp) do + local k,v1 = v:match("(.-)=(.+)") + if k and v1 then + sysctl[k]=v1 + end + end + end + + local log_opt = {} + tmp = data.log_opt + if type(tmp) == "table" then + for i, v in ipairs(tmp) do + local k,v1 = v:match("(.-)=(.+)") + if k and v1 then + log_opt[k]=v1 + end + end + end + + local network = data.network + local ip = (network ~= "bridge" and network ~= "host" and network ~= "none") and data.ip or nil + local volume = data.volume + local memory = data.memory or nil + local cpu_shares = data.cpu_shares or nil + local cpus = data.cpus or nil + local blkio_weight = data.blkio_weight or nil + + local portbindings = {} + local exposedports = {} + + local tmpfs = {} + tmp = data.tmpfs + if type(tmp) == "table" then + for i, v in ipairs(tmp)do + local k= v:match("([^:]+)") + local v1 = v:match(".-:([^:]+)") or "" + if k then + tmpfs[k]=v1 + end + end + end + + local device = {} + tmp = data.device + if type(tmp) == "table" then + for i, v in ipairs(tmp) do + local t = {} + local _,_, h, c, p = v:find("(.-):(.-):(.+)") + if h and c then + t['PathOnHost'] = h + t['PathInContainer'] = c + t['CgroupPermissions'] = p or "rwm" + else + local _,_, h, c = v:find("(.-):(.+)") + if h and c then + t['PathOnHost'] = h + t['PathInContainer'] = c + t['CgroupPermissions'] = "rwm" + else + t['PathOnHost'] = v + t['PathInContainer'] = v + t['CgroupPermissions'] = "rwm" + end + end + + if next(t) ~= nil then + table.insert( device, t ) + end + end + end + + tmp = data.publish or {} + for i, v in ipairs(tmp) do + for v1 ,v2 in string.gmatch(v, "(%d+):([^%s]+)") do + local _,_,p= v2:find("^%d+/(%w+)") + if p == nil then + v2=v2..'/tcp' + end + portbindings[v2] = {{HostPort=v1}} + exposedports[v2] = {HostPort=v1} + end + end + + local link = data.link + tmp = data.command + local command = {} + if tmp ~= nil then + for v in string.gmatch(tmp, "[^%s]+") do + command[#command+1] = v + end + end + + if memory and memory ~= 0 then + _,_,n,unit = memory:find("([%d%.]+)([%l%u]+)") + if n then + unit = unit and unit:sub(1,1):upper() or "B" + if unit == "M" then + memory = tonumber(n) * 1024 * 1024 + elseif unit == "G" then + memory = tonumber(n) * 1024 * 1024 * 1024 + elseif unit == "K" then + memory = tonumber(n) * 1024 + else + memory = tonumber(n) + end + end + end + + create_body.Hostname = network ~= "host" and (hostname or name) or nil + create_body.Tty = tty and true or false + create_body.OpenStdin = interactive and true or false + create_body.User = user + create_body.Cmd = command + create_body.Env = env + create_body.Image = image + create_body.ExposedPorts = exposedports + create_body.HostConfig = create_body.HostConfig or {} + create_body.HostConfig.Dns = dns + create_body.HostConfig.Binds = volume + create_body.HostConfig.RestartPolicy = { Name = restart, MaximumRetryCount = 0 } + create_body.HostConfig.Privileged = privileged and true or false + create_body.HostConfig.PortBindings = portbindings + create_body.HostConfig.Memory = memory and tonumber(memory) + create_body.HostConfig.CpuShares = cpu_shares and tonumber(cpu_shares) + create_body.HostConfig.NanoCPUs = cpus and tonumber(cpus) * 10 ^ 9 + create_body.HostConfig.BlkioWeight = blkio_weight and tonumber(blkio_weight) + create_body.HostConfig.PublishAllPorts = publish_all + + if create_body.HostConfig.NetworkMode ~= network then + create_body.NetworkingConfig = nil + end + + create_body.HostConfig.NetworkMode = network + + if ip then + if create_body.NetworkingConfig and create_body.NetworkingConfig.EndpointsConfig and type(create_body.NetworkingConfig.EndpointsConfig) == "table" then + for k, v in pairs (create_body.NetworkingConfig.EndpointsConfig) do + if k == network and v.IPAMConfig and v.IPAMConfig.IPv4Address then + v.IPAMConfig.IPv4Address = ip + else + create_body.NetworkingConfig.EndpointsConfig = { [network] = { IPAMConfig = { IPv4Address = ip } } } + end + break + end + else + create_body.NetworkingConfig = { EndpointsConfig = { [network] = { IPAMConfig = { IPv4Address = ip } } } } + end + elseif not create_body.NetworkingConfig then + create_body.NetworkingConfig = nil + end + + create_body["HostConfig"]["Tmpfs"] = tmpfs + create_body["HostConfig"]["Devices"] = device + create_body["HostConfig"]["Sysctls"] = sysctl + create_body["HostConfig"]["CapAdd"] = cap_add + create_body["HostConfig"]["LogConfig"] = { + Config = log_opt, + Type = log_driver + } + + if network == "bridge" then + create_body["HostConfig"]["Links"] = link + end + + local pull_image = function(image) + local json_stringify = luci.jsonc and luci.jsonc.stringify + docker:append_status("Images: " .. "pulling" .. " " .. image .. "...\n") + local res = dk.images:create({query = {fromImage=image}}, docker.pull_image_show_status_cb) + if res and res.code and res.code == 200 and (res.body[#res.body] and not res.body[#res.body].error and res.body[#res.body].status and (res.body[#res.body].status == "Status: Downloaded newer image for ".. image or res.body[#res.body].status == "Status: Image is up to date for ".. image)) then + docker:append_status("done\n") + else + res.code = (res.code == 200) and 500 or res.code + docker:append_status("code:" .. res.code.." ".. (res.body[#res.body] and res.body[#res.body].error or (res.body.message or res.message)).. "\n") + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) + end + end + + docker:clear_status() + local exist_image = false + + if image then + for _, v in ipairs (images) do + if v.RepoTags and v.RepoTags[1] == image then + exist_image = true + break + end + end + if not exist_image then + pull_image(image) + elseif data._force_pull == 1 then + pull_image(image) + end + end + + create_body = docker.clear_empty_tables(create_body) + + docker:append_status("Container: " .. "create" .. " " .. name .. "...") + local res = dk.containers:create({name = name, body = create_body}) + if res and res.code and res.code == 201 then + docker:clear_status() + luci.http.redirect(luci.dispatcher.build_url("admin/docker/containers")) + else + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message)) + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newcontainer")) + end +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua new file mode 100755 index 000000000..c87678b85 --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua @@ -0,0 +1,258 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" + +local m, s, o + +local dk = docker.new() +if dk:_ping().code ~= 200 then + lost_state = true +end + +m = SimpleForm("docker", translate("Docker - Network")) +m.redirect = luci.dispatcher.build_url("admin", "docker", "networks") +if lost_state then + m.submit=false + m.reset=false +end + + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err=docker:read_status() +s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(SimpleSection, translate("Create new docker network")) +s.addremove = true +s.anonymous = true + +o = s:option(Value, "name", + translate("Network Name"), + translate("Name of the network that can be selected during container creation")) +o.rmempty = true + +o = s:option(ListValue, "driver", translate("Driver")) +o.rmempty = true +o:value("bridge", translate("Bridge device")) +o:value("macvlan", translate("MAC VLAN")) +o:value("ipvlan", translate("IP VLAN")) +o:value("overlay", translate("Overlay network")) + +o = s:option(Value, "parent", translate("Base device")) +o.rmempty = true +o:depends("driver", "macvlan") +local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {} +for _, v in ipairs(interfaces) do + o:value(v, v) +end +o.default="br-lan" +o.placeholder="br-lan" + +o = s:option(ListValue, "macvlan_mode", translate("Mode")) +o.rmempty = true +o:depends("driver", "macvlan") +o.default="bridge" +o:value("bridge", translate("Bridge (Support direct communication between MAC VLANs)")) +o:value("private", translate("Private (Prevent communication between MAC VLANs)")) +o:value("vepa", translate("VEPA (Virtual Ethernet Port Aggregator)")) +o:value("passthru", translate("Pass-through (Mirror physical device to single MAC VLAN)")) + +o = s:option(ListValue, "ipvlan_mode", translate("Ipvlan Mode")) +o.rmempty = true +o:depends("driver", "ipvlan") +o.default="l3" +o:value("l2", translate("L2 bridge")) +o:value("l3", translate("L3 bridge")) + +o = s:option(Flag, "ingress", + translate("Ingress"), + translate("Ingress network is the network which provides the routing-mesh in swarm mode")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = 0 +o:depends("driver", "overlay") + +o = s:option(DynamicList, "options", translate("Options")) +o.rmempty = true +o.placeholder="com.docker.network.driver.mtu=1500" + +o = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network")) +o.rmempty = true +o:depends("driver", "overlay") +o.disabled = 0 +o.enabled = 1 +o.default = 0 + +if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then + o = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt")) + o:depends("driver", "macvlan") + o.disabled = 0 + o.enabled = 1 + o.default = 1 +end + +o = s:option(Value, "subnet", translate("Subnet")) +o.rmempty = true +o.placeholder="10.1.0.0/16" +o.datatype="ip4addr" + +o = s:option(Value, "gateway", translate("Gateway")) +o.rmempty = true +o.placeholder="10.1.1.1" +o.datatype="ip4addr" + +o = s:option(Value, "ip_range", translate("IP range")) +o.rmempty = true +o.placeholder="10.1.1.0/24" +o.datatype="ip4addr" + +o = s:option(DynamicList, "aux_address", translate("Exclude IPs")) +o.rmempty = true +o.placeholder="my-route=10.1.1.1" + +o = s:option(Flag, "ipv6", translate("Enable IPv6")) +o.rmempty = true +o.disabled = 0 +o.enabled = 1 +o.default = 0 + +o = s:option(Value, "subnet6", translate("IPv6 Subnet")) +o.rmempty = true +o.placeholder="fe80::/10" +o.datatype="ip6addr" +o:depends("ipv6", 1) + +o = s:option(Value, "gateway6", translate("IPv6 Gateway")) +o.rmempty = true +o.placeholder="fe80::1" +o.datatype="ip6addr" +o:depends("ipv6", 1) + +m.handle = function(self, state, data) + if state == FORM_VALID then + local name = data.name + local driver = data.driver + + local internal = data.internal == 1 and true or false + + local subnet = data.subnet + local gateway = data.gateway + local ip_range = data.ip_range + + local aux_address = {} + local tmp = data.aux_address or {} + for i,v in ipairs(tmp) do + _,_,k1,v1 = v:find("(.-)=(.+)") + aux_address[k1] = v1 + end + + local options = {} + tmp = data.options or {} + for i,v in ipairs(tmp) do + _,_,k1,v1 = v:find("(.-)=(.+)") + options[k1] = v1 + end + + local ipv6 = data.ipv6 == 1 and true or false + + local create_body = { + Name = name, + Driver = driver, + EnableIPv6 = ipv6, + IPAM = { + Driver= "default" + }, + Internal = internal + } + + if subnet or gateway or ip_range then + create_body["IPAM"]["Config"] = { + { + Subnet = subnet, + Gateway = gateway, + IPRange = ip_range, + AuxAddress = aux_address, + AuxiliaryAddresses = aux_address + } + } + end + + if driver == "macvlan" then + create_body["Options"] = { + macvlan_mode = data.macvlan_mode, + parent = data.parent + } + elseif driver == "ipvlan" then + create_body["Options"] = { + ipvlan_mode = data.ipvlan_mode + } + elseif driver == "overlay" then + create_body["Ingress"] = data.ingerss == 1 and true or false + end + + if ipv6 and data.subnet6 and data.subnet6 then + if type(create_body["IPAM"]["Config"]) ~= "table" then + create_body["IPAM"]["Config"] = {} + end + local index = #create_body["IPAM"]["Config"] + create_body["IPAM"]["Config"][index+1] = { + Subnet = data.subnet6, + Gateway = data.gateway6 + } + end + + if next(options) ~= nil then + create_body["Options"] = create_body["Options"] or {} + for k, v in pairs(options) do + create_body["Options"][k] = v + end + end + + create_body = docker.clear_empty_tables(create_body) + docker:write_status("Network: " .. "create" .. " " .. create_body.Name .. "...") + + local res = dk.networks:create({ + body = create_body + }) + + if res and res.code == 201 then + docker:write_status("Network: " .. "create macvlan interface...") + res = dk.networks:inspect({ + name = create_body.Name + }) + + if driver == "macvlan" and + data.op_macvlan ~= 0 and + res and + res.code and + res.code == 200 and + res.body and + res.body.IPAM and + res.body.IPAM.Config and + res.body.IPAM.Config[1] and + res.body.IPAM.Config[1].Gateway and + res.body.IPAM.Config[1].Subnet then + + docker.create_macvlan_interface(data.name, + data.parent, + res.body.IPAM.Config[1].Gateway, + res.body.IPAM.Config[1].Subnet) + end + + docker:clear_status() + luci.http.redirect(luci.dispatcher.build_url("admin/docker/networks")) + else + docker:append_status("code:" .. res.code.." ".. (res.body.message and res.body.message or res.message).. "\n") + luci.http.redirect(luci.dispatcher.build_url("admin/docker/newnetwork")) + end + end +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua new file mode 100755 index 000000000..c91f349ce --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua @@ -0,0 +1,151 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" +local uci = (require "luci.model.uci").cursor() + +local m, s, o, lost_state +local dk = docker.new() + +if dk:_ping().code ~= 200 then + lost_state = true +end + +m = SimpleForm("dockerd", + translate("Docker - Overview"), + translate("An overview with the relevant data is displayed here with which the LuCI docker client is connected.") +.. + " " .. + [[]] .. + translate("Github") .. + [[]]) +m.submit=false +m.reset=false + +local docker_info_table = {} +-- docker_info_table['0OperatingSystem'] = {_key=translate("Operating System"),_value='-'} +-- docker_info_table['1Architecture'] = {_key=translate("Architecture"),_value='-'} +-- docker_info_table['2KernelVersion'] = {_key=translate("Kernel Version"),_value='-'} +docker_info_table['3ServerVersion'] = {_key=translate("Docker Version"),_value='-'} +docker_info_table['4ApiVersion'] = {_key=translate("Api Version"),_value='-'} +docker_info_table['5NCPU'] = {_key=translate("CPUs"),_value='-'} +docker_info_table['6MemTotal'] = {_key=translate("Total Memory"),_value='-'} +docker_info_table['7DockerRootDir'] = {_key=translate("Docker Root Dir"),_value='-'} +docker_info_table['8IndexServerAddress'] = {_key=translate("Index Server Address"),_value='-'} +docker_info_table['9RegistryMirrors'] = {_key=translate("Registry Mirrors"),_value='-'} + +if nixio.fs.access("/usr/bin/dockerd") and not uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + s = m:section(SimpleSection) + s.template = "dockerman/apply_widget" + s.err=docker:read_status() + s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") + if s.err then + docker:clear_status() + end + s = m:section(Table,{{}}) + s.notitle=true + s.rowcolors=false + s.template = "cbi/nullsection" + + o = s:option(Button, "_start") + o.template = "dockerman/cbi/inlinebutton" + o.inputtitle = lost_state and translate("Start") or translate("Stop") + o.inputstyle = lost_state and "add" or "remove" + o.forcewrite = true + o.write = function(self, section) + docker:clear_status() + + if lost_state then + docker:append_status("Docker daemon: starting") + luci.util.exec("/etc/init.d/dockerd start") + luci.util.exec("sleep 5") + luci.util.exec("/etc/init.d/dockerman start") + + else + docker:append_status("Docker daemon: stopping") + luci.util.exec("/etc/init.d/dockerd stop") + end + docker:clear_status() + luci.http.redirect(luci.dispatcher.build_url("admin/docker/overview")) + end + + o = s:option(Button, "_restart") + o.template = "dockerman/cbi/inlinebutton" + o.inputtitle = translate("Restart") + o.inputstyle = "reload" + o.forcewrite = true + o.write = function(self, section) + docker:clear_status() + docker:append_status("Docker daemon: restarting") + luci.util.exec("/etc/init.d/dockerd restart") + luci.util.exec("sleep 5") + luci.util.exec("/etc/init.d/dockerman start") + docker:clear_status() + luci.http.redirect(luci.dispatcher.build_url("admin/docker/overview")) + end +end + +s = m:section(Table, docker_info_table) +s:option(DummyValue, "_key", translate("Info")) +s:option(DummyValue, "_value") + +s = m:section(SimpleSection) +s.template = "dockerman/overview" + +s.containers_running = '-' +s.images_used = '-' +s.containers_total = '-' +s.images_total = '-' +s.networks_total = '-' +s.volumes_total = '-' + +-- local socket = luci.model.uci.cursor():get("dockerd", "dockerman", "socket_path") +if not lost_state then + local containers_list = dk.containers:list({query = {all=true}}).body + local images_list = dk.images:list().body + local vol = dk.volumes:list() + local volumes_list = vol and vol.body and vol.body.Volumes or {} + local networks_list = dk.networks:list().body or {} + local docker_info = dk:info() + + -- docker_info_table['0OperatingSystem']._value = docker_info.body.OperatingSystem + -- docker_info_table['1Architecture']._value = docker_info.body.Architecture + -- docker_info_table['2KernelVersion']._value = docker_info.body.KernelVersion + docker_info_table['3ServerVersion']._value = docker_info.body.ServerVersion + docker_info_table['4ApiVersion']._value = docker_info.headers["Api-Version"] + docker_info_table['5NCPU']._value = tostring(docker_info.body.NCPU) + docker_info_table['6MemTotal']._value = docker.byte_format(docker_info.body.MemTotal) + if docker_info.body.DockerRootDir then + local statvfs = nixio.fs.statvfs(docker_info.body.DockerRootDir) + local size = statvfs and (statvfs.bavail * statvfs.bsize) or 0 + docker_info_table['7DockerRootDir']._value = docker_info.body.DockerRootDir .. " (" .. tostring(docker.byte_format(size)) .. " " .. translate("Available") .. ")" + end + + docker_info_table['8IndexServerAddress']._value = docker_info.body.IndexServerAddress + for i, v in ipairs(docker_info.body.RegistryConfig.Mirrors) do + docker_info_table['9RegistryMirrors']._value = docker_info_table['9RegistryMirrors']._value == "-" and v or (docker_info_table['9RegistryMirrors']._value .. ", " .. v) + end + + s.images_used = 0 + for i, v in ipairs(images_list) do + for ci,cv in ipairs(containers_list) do + if v.Id == cv.ImageID then + s.images_used = s.images_used + 1 + break + end + end + end + + s.containers_running = tostring(docker_info.body.ContainersRunning) + s.images_used = tostring(s.images_used) + s.containers_total = tostring(docker_info.body.Containers) + s.images_total = tostring(#images_list) + s.networks_total = tostring(#networks_list) + s.volumes_total = tostring(#volumes_list) +else + docker_info_table['3ServerVersion']._value = translate("Can NOT connect to docker daemon, please check!!") +end + +return m diff --git a/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua b/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua new file mode 100755 index 000000000..43e6bda3a --- /dev/null +++ b/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua @@ -0,0 +1,142 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.model.docker" +local dk = docker.new() + +local m, s, o + +local res, containers, volumes, lost_state + +function get_volumes() + local data = {} + for i, v in ipairs(volumes) do + local index = v.Name + data[index]={} + data[index]["_selected"] = 0 + data[index]["_nameraw"] = v.Name + data[index]["_name"] = v.Name:sub(1,12) + + for ci,cv in ipairs(containers) do + if cv.Mounts and type(cv.Mounts) ~= "table" then + break + end + for vi, vv in ipairs(cv.Mounts) do + if v.Name == vv.Name then + data[index]["_containers"] = (data[index]["_containers"] and (data[index]["_containers"] .. " | ") or "").. + ''.. cv.Names[1]:sub(2)..'' + end + end + end + data[index]["_driver"] = v.Driver + data[index]["_mountpoint"] = nil + + for v1 in v.Mountpoint:gmatch('[^/]+') do + if v1 == index then + data[index]["_mountpoint"] = data[index]["_mountpoint"] .."/" .. v1:sub(1,12) .. "..." + else + data[index]["_mountpoint"] = (data[index]["_mountpoint"] and data[index]["_mountpoint"] or "").."/".. v1 + end + end + data[index]["_created"] = v.CreatedAt + data[index]["_size"] = "-" + end + + return data +end +if dk:_ping().code ~= 200 then + lost_state = true +else + res = dk.volumes:list() + if res and res.code and res.code <300 then + volumes = res.body.Volumes + end + + res = dk.containers:list({ + query = { + all=true + } + }) + if res and res.code and res.code <300 then + containers = res.body + end +end + +local volume_list = not lost_state and get_volumes() or {} + +m = SimpleForm("docker", translate("Docker - Volumes")) +m.submit=false +m.reset=false +m:append(Template("dockerman/volume_size")) + +s = m:section(Table, volume_list, translate("Volumes overview")) + +o = s:option(Flag, "_selected","") +o.disabled = 0 +o.enabled = 1 +o.default = 0 +o.write = function(self, section, value) + volume_list[section]._selected = value +end + +o = s:option(DummyValue, "_name", translate("Name")) +o = s:option(DummyValue, "_driver", translate("Driver")) +o = s:option(DummyValue, "_containers", translate("Containers")) +o.rawhtml = true +o = s:option(DummyValue, "_mountpoint", translate("Mount Point")) +o = s:option(DummyValue, "_size", translate("Size")) +o.rawhtml = true +o = s:option(DummyValue, "_created", translate("Created")) + +s = m:section(SimpleSection) +s.template = "dockerman/apply_widget" +s.err=docker:read_status() +s.err=s.err and s.err:gsub("\n","
"):gsub(" "," ") +if s.err then + docker:clear_status() +end + +s = m:section(Table,{{}}) +s.notitle=true +s.rowcolors=false +s.template="cbi/nullsection" + +o = s:option(Button, "remove") +o.inputtitle= translate("Remove") +o.template = "dockerman/cbi/inlinebutton" +o.inputstyle = "remove" +o.forcewrite = true +o.disable = lost_state +o.write = function(self, section) + local volume_selected = {} + + for k in pairs(volume_list) do + if volume_list[k]._selected == 1 then + volume_selected[#volume_selected+1] = k + end + end + + if next(volume_selected) ~= nil then + local success = true + docker:clear_status() + for _,vol in ipairs(volume_selected) do + docker:append_status("Volumes: " .. "remove" .. " " .. vol .. "...") + local msg = dk.volumes["remove"](dk, {id = vol}) + if msg and msg.code and msg.code ~= 204 then + docker:append_status("code:" .. msg.code.." ".. (msg.body.message and msg.body.message or msg.message).. "\n") + success = false + else + docker:append_status("done\n") + end + end + + if success then + docker:clear_status() + end + luci.http.redirect(luci.dispatcher.build_url("admin/docker/volumes")) + end +end + +return m diff --git a/luci-app-dockerman/luasrc/model/docker.lua b/luci-app-dockerman/luasrc/model/docker.lua new file mode 100755 index 000000000..2a902912a --- /dev/null +++ b/luci-app-dockerman/luasrc/model/docker.lua @@ -0,0 +1,507 @@ +--[[ +LuCI - Lua Configuration Interface +Copyright 2019 lisaac +]]-- + +local docker = require "luci.docker" +local fs = require "nixio.fs" +local uci = (require "luci.model.uci").cursor() + +local _docker = {} +_docker.options = {} + +--pull image and return iamge id +local update_image = function(self, image_name) + local json_stringify = luci.jsonc and luci.jsonc.stringify + _docker:append_status("Images: " .. "pulling" .. " " .. image_name .. "...\n") + local res = self.images:create({query = {fromImage=image_name}}, _docker.pull_image_show_status_cb) + + if res and res.code and res.code == 200 and (#res.body > 0 and not res.body[#res.body].error and res.body[#res.body].status and (res.body[#res.body].status == "Status: Downloaded newer image for ".. image_name)) then + _docker:append_status("done\n") + else + res.body.message = res.body[#res.body] and res.body[#res.body].error or (res.body.message or res.message) + end + + new_image_id = self.images:inspect({name = image_name}).body.Id + return new_image_id, res +end + +local table_equal = function(t1, t2) + if not t1 then + return true + end + + if not t2 then + return false + end + + if #t1 ~= #t2 then + return false + end + + for i, v in ipairs(t1) do + if t1[i] ~= t2[i] then + return false + end + end + + return true +end + +local table_subtract = function(t1, t2) + if not t1 or next(t1) == nil then + return nil + end + + if not t2 or next(t2) == nil then + return t1 + end + + local res = {} + for _, v1 in ipairs(t1) do + local found = false + for _, v2 in ipairs(t2) do + if v1 == v2 then + found= true + break + end + end + if not found then + table.insert(res, v1) + end + end + + return next(res) == nil and nil or res +end + +local map_subtract = function(t1, t2) + if not t1 or next(t1) == nil then + return nil + end + + if not t2 or next(t2) == nil then + return t1 + end + + local res = {} + for k1, v1 in pairs(t1) do + local found = false + for k2, v2 in ipairs(t2) do + if k1 == k2 and luci.util.serialize_data(v1) == luci.util.serialize_data(v2) then + found= true + break + end + end + + if not found then + res[k1] = v1 + end + end + + return next(res) ~= nil and res or nil +end + +_docker.clear_empty_tables = function ( t ) + local k, v + + if next(t) == nil then + t = nil + else + for k, v in pairs(t) do + if type(v) == 'table' then + t[k] = _docker.clear_empty_tables(v) + if t[k] and next(t[k]) == nil then + t[k] = nil + end + end + end + end + + return t +end + +local get_config = function(container_config, image_config) + local config = container_config.Config + local old_host_config = container_config.HostConfig + local old_network_setting = container_config.NetworkSettings.Networks or {} + + if config.WorkingDir == image_config.WorkingDir then + config.WorkingDir = "" + end + + if config.User == image_config.User then + config.User = "" + end + + if table_equal(config.Cmd, image_config.Cmd) then + config.Cmd = nil + end + + if table_equal(config.Entrypoint, image_config.Entrypoint) then + config.Entrypoint = nil + end + + if table_equal(config.ExposedPorts, image_config.ExposedPorts) then + config.ExposedPorts = nil + end + + config.Env = table_subtract(config.Env, image_config.Env) + config.Labels = table_subtract(config.Labels, image_config.Labels) + config.Volumes = map_subtract(config.Volumes, image_config.Volumes) + + if old_host_config.PortBindings and next(old_host_config.PortBindings) ~= nil then + config.ExposedPorts = {} + for p, v in pairs(old_host_config.PortBindings) do + config.ExposedPorts[p] = { HostPort=v[1] and v[1].HostPort } + end + end + + local network_setting = {} + local multi_network = false + local extra_network = {} + + for k, v in pairs(old_network_setting) do + if multi_network then + extra_network[k] = v + else + network_setting[k] = v + end + multi_network = true + end + + local host_config = old_host_config + host_config.Mounts = {} + for i, v in ipairs(container_config.Mounts) do + if v.Type == "volume" then + table.insert(host_config.Mounts, { + Type = v.Type, + Target = v.Destination, + Source = v.Source:match("([^/]+)\/_data"), + BindOptions = (v.Type == "bind") and {Propagation = v.Propagation} or nil, + ReadOnly = not v.RW + }) + end + end + + local create_body = config + create_body["HostConfig"] = host_config + create_body["NetworkingConfig"] = {EndpointsConfig = network_setting} + create_body = _docker.clear_empty_tables(create_body) or {} + extra_network = _docker.clear_empty_tables(extra_network) or {} + + return create_body, extra_network +end + +local upgrade = function(self, request) + _docker:clear_status() + + local container_info = self.containers:inspect({id = request.id}) + + if container_info.code > 300 and type(container_info.body) == "table" then + return container_info + end + + local image_name = container_info.body.Config.Image + if not image_name:match(".-:.+") then + image_name = image_name .. ":latest" + end + + local old_image_id = container_info.body.Image + local container_name = container_info.body.Name:sub(2) + + local image_id, res = update_image(self, image_name) + if res and res.code and res.code ~= 200 then + return res + end + + if image_id == old_image_id then + return {code = 305, body = {message = "Already up to date"}} + end + + local t = os.date("%Y%m%d%H%M%S") + _docker:append_status("Container: rename" .. " " .. container_name .. " to ".. container_name .. "_old_".. t .. "...") + res = self.containers:rename({name = container_name, query = { name = container_name .. "_old_" ..t }}) + if res and res.code and res.code < 300 then + _docker:append_status("done\n") + else + return res + end + + local image_config = self.images:inspect({id = old_image_id}).body.Config + local create_body, extra_network = get_config(container_info.body, image_config) + + -- create new container + _docker:append_status("Container: Create" .. " " .. container_name .. "...") + create_body = _docker.clear_empty_tables(create_body) + res = self.containers:create({name = container_name, body = create_body}) + if res and res.code and res.code > 300 then + return res + end + _docker:append_status("done\n") + + -- extra networks need to network connect action + for k, v in pairs(extra_network) do + _docker:append_status("Networks: Connect" .. " " .. container_name .. "...") + res = self.networks:connect({id = k, body = {Container = container_name, EndpointConfig = v}}) + if res and res.code and res.code > 300 then + return res + end + _docker:append_status("done\n") + end + + _docker:append_status("Container: " .. "Stop" .. " " .. container_name .. "_old_".. t .. "...") + res = self.containers:stop({name = container_name .. "_old_" ..t }) + if res and res.code and res.code < 305 then + _docker:append_status("done\n") + else + return res + end + + _docker:append_status("Container: " .. "Start" .. " " .. container_name .. "...") + res = self.containers:start({name = container_name}) + if res and res.code and res.code < 305 then + _docker:append_status("done\n") + else + return res + end + + _docker:clear_status() + return res +end + +local duplicate_config = function (self, request) + local container_info = self.containers:inspect({id = request.id}) + if container_info.code > 300 and type(container_info.body) == "table" then + return nil + end + + local old_image_id = container_info.body.Image + local image_config = self.images:inspect({id = old_image_id}).body.Config + + return get_config(container_info.body, image_config) +end + +_docker.new = function() + local host = nil + local port = nil + local socket_path = nil + local debug_path = nil + + if uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + host = uci:get("dockerd", "dockerman", "remote_host") or nil + port = uci:get("dockerd", "dockerman", "remote_port") or nil + else + socket_path = uci:get("dockerd", "dockerman", "socket_path") or "/var/run/docker.sock" + end + + local debug = uci:get_bool("dockerd", "dockerman", "debug") + if debug then + debug_path = uci:get("dockerd", "dockerman", "debug_path") or "/tmp/.docker_debug" + end + + local status_path = uci:get("dockerd", "dockerman", "status_path") or "/tmp/.docker_action_status" + + _docker.options = { + host = host, + port = port, + socket_path = socket_path, + debug = debug, + debug_path = debug_path, + status_path = status_path + } + + local _new = docker.new(_docker.options) + _new.containers_upgrade = upgrade + _new.containers_duplicate_config = duplicate_config + + return _new +end + +_docker.options.status_path = uci:get("dockerd", "dockerman", "status_path") or "/tmp/.docker_action_status" + +_docker.append_status=function(self,val) + if not val then + return + end + local file_docker_action_status=io.open(self.options.status_path, "a+") + file_docker_action_status:write(val) + file_docker_action_status:close() +end + +_docker.write_status=function(self,val) + if not val then + return + end + local file_docker_action_status=io.open(self.options.status_path, "w+") + file_docker_action_status:write(val) + file_docker_action_status:close() +end + +_docker.read_status=function(self) + return fs.readfile(self.options.status_path) +end + +_docker.clear_status=function(self) + fs.remove(self.options.status_path) +end + +local status_cb = function(res, source, handler) + res.body = res.body or {} + while true do + local chunk = source() + if chunk then + --standard output to res.body + table.insert(res.body, chunk) + handler(chunk) + else + return + end + end +end + +--{"status":"Pulling from library\/debian","id":"latest"} +--{"status":"Pulling fs layer","progressDetail":[],"id":"50e431f79093"} +--{"status":"Downloading","progressDetail":{"total":50381971,"current":2029978},"id":"50e431f79093","progress":"[==> ] 2.03MB\/50.38MB"} +--{"status":"Download complete","progressDetail":[],"id":"50e431f79093"} +--{"status":"Extracting","progressDetail":{"total":50381971,"current":17301504},"id":"50e431f79093","progress":"[=================> ] 17.3MB\/50.38MB"} +--{"status":"Pull complete","progressDetail":[],"id":"50e431f79093"} +--{"status":"Digest: sha256:a63d0b2ecbd723da612abf0a8bdb594ee78f18f691d7dc652ac305a490c9b71a"} +--{"status":"Status: Downloaded newer image for debian:latest"} +_docker.pull_image_show_status_cb = function(res, source) + return status_cb(res, source, function(chunk) + local json_parse = luci.jsonc.parse + local step = json_parse(chunk) + if type(step) == "table" then + local buf = _docker:read_status() + local num = 0 + local str = '\t' .. (step.id and (step.id .. ": ") or "") .. (step.status and step.status or "") .. (step.progress and (" " .. step.progress) or "").."\n" + if step.id then + buf, num = buf:gsub("\t"..step.id .. ": .-\n", str) + end + if num == 0 then + buf = buf .. str + end + _docker:write_status(buf) + end + end) +end + +--{"status":"Downloading from https://downloads.openwrt.org/releases/19.07.0/targets/x86/64/openwrt-19.07.0-x86-64-generic-rootfs.tar.gz"} +--{"status":"Importing","progressDetail":{"current":1572391,"total":3821714},"progress":"[====================\u003e ] 1.572MB/3.822MB"} +--{"status":"sha256:d5304b58e2d8cc0a2fd640c05cec1bd4d1229a604ac0dd2909f13b2b47a29285"} +_docker.import_image_show_status_cb = function(res, source) + return status_cb(res, source, function(chunk) + local json_parse = luci.jsonc.parse + local step = json_parse(chunk) + if type(step) == "table" then + local buf = _docker:read_status() + local num = 0 + local str = '\t' .. (step.status and step.status or "") .. (step.progress and (" " .. step.progress) or "").."\n" + if step.status then + buf, num = buf:gsub("\t"..step.status .. " .-\n", str) + end + if num == 0 then + buf = buf .. str + end + _docker:write_status(buf) + end + end) +end + +_docker.create_macvlan_interface = function(name, device, gateway, subnet) + if not fs.access("/etc/config/network") or not fs.access("/etc/config/firewall") then + return + end + + if uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + return + end + + local ip = require "luci.ip" + local if_name = "docker_"..name + local dev_name = "macvlan_"..name + local net_mask = tostring(ip.new(subnet):mask()) + local lan_interfaces + + -- add macvlan device + uci:delete("network", dev_name) + uci:set("network", dev_name, "device") + uci:set("network", dev_name, "name", dev_name) + uci:set("network", dev_name, "ifname", device) + uci:set("network", dev_name, "type", "macvlan") + uci:set("network", dev_name, "mode", "bridge") + + -- add macvlan interface + uci:delete("network", if_name) + uci:set("network", if_name, "interface") + uci:set("network", if_name, "proto", "static") + uci:set("network", if_name, "ifname", dev_name) + uci:set("network", if_name, "ipaddr", gateway) + uci:set("network", if_name, "netmask", net_mask) + uci:foreach("firewall", "zone", function(s) + if s.name == "lan" then + local interfaces + if type(s.network) == "table" then + interfaces = table.concat(s.network, " ") + uci:delete("firewall", s[".name"], "network") + else + interfaces = s.network and s.network or "" + end + interfaces = interfaces .. " " .. if_name + interfaces = interfaces:gsub("%s+", " ") + uci:set("firewall", s[".name"], "network", interfaces) + end + end) + + uci:commit("firewall") + uci:commit("network") + + os.execute("ifup " .. if_name) +end + +_docker.remove_macvlan_interface = function(name) + if not fs.access("/etc/config/network") or not fs.access("/etc/config/firewall") then + return + end + + if uci:get_bool("dockerd", "dockerman", "remote_endpoint") then + return + end + + local if_name = "docker_"..name + local dev_name = "macvlan_"..name + uci:foreach("firewall", "zone", function(s) + if s.name == "lan" then + local interfaces + if type(s.network) == "table" then + interfaces = table.concat(s.network, " ") + else + interfaces = s.network and s.network or "" + end + interfaces = interfaces and interfaces:gsub(if_name, "") + interfaces = interfaces and interfaces:gsub("%s+", " ") + uci:set("firewall", s[".name"], "network", interfaces) + end + end) + + uci:delete("network", dev_name) + uci:delete("network", if_name) + uci:commit("network") + uci:commit("firewall") + + os.execute("ip link del " .. if_name) +end + +_docker.byte_format = function (byte) + if not byte then return 'NaN' end + local suff = {"B", "KB", "MB", "GB", "TB"} + for i=1, 5 do + if byte > 1024 and i < 5 then + byte = byte / 1024 + else + return string.format("%.2f %s", byte, suff[i]) + end + end +end + +return _docker diff --git a/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm b/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm new file mode 100755 index 000000000..f96b2d72a --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm @@ -0,0 +1,147 @@ + + + diff --git a/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm b/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm new file mode 100755 index 000000000..a061a6dba --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinebutton.htm @@ -0,0 +1,7 @@ +
+ <% if self:cfgvalue(section) ~= false then %> + " type="submit"" <% if self.disable then %>disabled <% end %><%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> /> + <% else %> + - + <% end %> +
diff --git a/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm b/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm new file mode 100755 index 000000000..e4b0cf7a0 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm @@ -0,0 +1,33 @@ +
+ + <%- if self.password then -%> + /> + <%- end -%> + 0, "data-choices", { self.keylist, self.vallist }) + %> /> + <%- if self.password then -%> +
+ <% end %> +
diff --git a/luci-app-dockerman/luasrc/view/dockerman/cbi/namedsection.htm b/luci-app-dockerman/luasrc/view/dockerman/cbi/namedsection.htm new file mode 100755 index 000000000..244d2c10a --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/cbi/namedsection.htm @@ -0,0 +1,9 @@ +<% if self:cfgvalue(self.section) then section = self.section %> +
+ <%+cbi/tabmenu%> +
+ <%+cbi/ucisection%> +
+
+<% end %> + diff --git a/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm b/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm new file mode 100755 index 000000000..04f7bc2ee --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/cbi/xfvalue.htm @@ -0,0 +1,10 @@ +<%+cbi/valueheader%> + /> + disabled <% end %><%= + attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) .. + ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked") + %> /> + > +<%+cbi/valuefooter%> diff --git a/luci-app-dockerman/luasrc/view/dockerman/container.htm b/luci-app-dockerman/luasrc/view/dockerman/container.htm new file mode 100755 index 000000000..9f05d9d58 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/container.htm @@ -0,0 +1,28 @@ +
+ + + diff --git a/luci-app-dockerman/luasrc/view/dockerman/container_console.htm b/luci-app-dockerman/luasrc/view/dockerman/container_console.htm new file mode 100755 index 000000000..1a4dc2a6b --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/container_console.htm @@ -0,0 +1,6 @@ +
+ +
+ diff --git a/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm b/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm new file mode 100755 index 000000000..2e0650d9d --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm @@ -0,0 +1,332 @@ + +
+ +
+ + +
+
+
+ + diff --git a/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm b/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm new file mode 100755 index 000000000..bbcd633e7 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm @@ -0,0 +1,81 @@ + diff --git a/luci-app-dockerman/luasrc/view/dockerman/containers_running_stats.htm b/luci-app-dockerman/luasrc/view/dockerman/containers_running_stats.htm new file mode 100755 index 000000000..d88e28be9 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/containers_running_stats.htm @@ -0,0 +1,91 @@ + \ No newline at end of file diff --git a/luci-app-dockerman/luasrc/view/dockerman/images_import.htm b/luci-app-dockerman/luasrc/view/dockerman/images_import.htm new file mode 100755 index 000000000..0ad6e0fce --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/images_import.htm @@ -0,0 +1,104 @@ + + +
+ disabled <% end %>/> + +
+ + diff --git a/luci-app-dockerman/luasrc/view/dockerman/images_load.htm b/luci-app-dockerman/luasrc/view/dockerman/images_load.htm new file mode 100755 index 000000000..b201510ac --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/images_load.htm @@ -0,0 +1,40 @@ +
+ disabled <% end %>/> + +
+ diff --git a/luci-app-dockerman/luasrc/view/dockerman/logs.htm b/luci-app-dockerman/luasrc/view/dockerman/logs.htm new file mode 100755 index 000000000..6cd2cb095 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/logs.htm @@ -0,0 +1,13 @@ +<% if self.title == "Events" then %> +<%+header%> +

<%:Docker - Events%>

+
+

<%:Events%>

+<% end %> +
+ +
+<% if self.title == "Events" then %> +
+<%+footer%> +<% end %> diff --git a/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm b/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm new file mode 100755 index 000000000..338fd59d5 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm @@ -0,0 +1,102 @@ + + + +<%+cbi/valueheader%> + + + +<%+cbi/valuefooter%> diff --git a/luci-app-dockerman/luasrc/view/dockerman/overview.htm b/luci-app-dockerman/luasrc/view/dockerman/overview.htm new file mode 100755 index 000000000..e491fc512 --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/overview.htm @@ -0,0 +1,197 @@ + + +
+
+
+
+
+ +
+
+
+

<%:Containers%>

+

+ <%- if self.containers_total ~= "-" then -%><%- end -%> + <%=self.containers_running%> + /<%=self.containers_total%> + <%- if self.containers_total ~= "-" then -%><%- end -%> +

+
+
+
+
+
+
+
+ +
+
+
+

<%:Images%>

+

+ <%- if self.images_total ~= "-" then -%><%- end -%> + <%=self.images_used%> + /<%=self.images_total%> + <%- if self.images_total ~= "-" then -%><%- end -%> +

+
+
+
+
+
+
+
+ +
+
+
+

<%:Networks%>

+

+ <%- if self.networks_total ~= "-" then -%><%- end -%> + <%=self.networks_total%> + + <%- if self.networks_total ~= "-" then -%><%- end -%> +

+
+
+
+
+
+
+
+ +
+
+
+

<%:Volumes%>

+

+ <%- if self.volumes_total ~= "-" then -%><%- end -%> + <%=self.volumes_total%> + + <%- if self.volumes_total ~= "-" then -%><%- end -%> +

+
+
+
+
diff --git a/luci-app-dockerman/luasrc/view/dockerman/volume_size.htm b/luci-app-dockerman/luasrc/view/dockerman/volume_size.htm new file mode 100755 index 000000000..dc024734b --- /dev/null +++ b/luci-app-dockerman/luasrc/view/dockerman/volume_size.htm @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/luci-app-dockerman/po/templates/dockerman.pot b/luci-app-dockerman/po/templates/dockerman.pot new file mode 100755 index 000000000..0d6a5de98 --- /dev/null +++ b/luci-app-dockerman/po/templates/dockerman.pot @@ -0,0 +1,1002 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:619 +msgid "A list of kernel capabilities to add to the container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:69 +msgid "Access Control" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:223 +msgid "Add" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:595 +msgid "Add host device to the container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:571 +msgid "Advance" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:586 +msgid "Allocates an ephemeral host port for all of a container's exposed ports" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:118 +msgid "Allowed access interfaces" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:498 +msgid "Always pull image first" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:29 +msgid "" +"An overview with the relevant data is displayed here with which the LuCI " +"docker client is connected." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:43 +msgid "Api Version" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:94 +msgid "Auto create macvlan interface in Openwrt" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:18 +msgid "Auto start" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:134 +msgid "Available" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:47 +msgid "Base device" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:553 +msgid "Bind Mount(-v)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:554 +msgid "Bind mount a volume" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:596 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:652 +msgid "Block IO Weight" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:653 +msgid "" +"Block IO weight (relative weight) accepts a weight value between 10 and 1000" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:597 +msgid "" +"Block IO weight (relative weight) accepts a weight value between 10 and 1000." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:61 +msgid "Bridge (Support direct communication between MAC VLANs)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:42 +msgid "Bridge device" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:84 +msgid "" +"By entering a valid image name with the corresponding version, the docker " +"image can be downloaded from the configured registry." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:618 +msgid "CAP-ADD(--cap-add)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:581 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:635 +msgid "CPU Shares Weight" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:779 +msgid "CPU Useage" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:636 +msgid "" +"CPU shares relative weight, if 0 is set, the system will ignore the value " +"and use the default of 1024" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:582 +msgid "" +"CPU shares relative weight, if 0 is set, the system will ignore the value " +"and use the default of 1024." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:573 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:626 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:44 +msgid "CPUs" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:159 +msgid "Can NOT connect to docker daemon, please check!!" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Cancel" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:60 +msgid "Client connection" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:347 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:687 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:182 +msgid "Command" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:100 +msgid "Command line" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:72 +msgid "Command line Error" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:17 +msgid "Configuration" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:36 +msgid "Configure the default bridge network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:405 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:707 +msgid "Connect" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:403 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:437 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:473 +msgid "Connect Network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:74 +msgid "Connect to remote docker endpoint" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:7 +msgid "Console" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:161 +msgid "Container Info" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:650 +msgid "Container Inspect" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:671 +msgid "Container Logs" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:473 +msgid "Container Name" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:92 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:58 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:29 +msgid "Container detail" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:38 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:142 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:148 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:87 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:133 +msgid "Containers" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:94 +msgid "Create macvlan interface" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:465 +msgid "Create new docker container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:31 +msgid "Create new docker network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:312 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:153 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:92 +msgid "Created" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:33 +msgid "DELETING" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:371 +msgid "DNS" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:51 +msgid "Debug" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:35 +msgid "Default bridge" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:363 +msgid "Device" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:594 +msgid "Device(--device)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:396 +msgid "Disconnect" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:14 +msgid "Docker" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:12 +msgid "Docker - Configuration" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:192 +msgid "Docker - Container (%s)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:128 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:450 +msgid "Docker - Containers" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/logs.htm:3 +msgid "Docker - Events" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:72 +msgid "Docker - Images" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:15 +msgid "Docker - Network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:54 +msgid "Docker - Networks" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:28 +msgid "Docker - Overview" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:69 +msgid "Docker - Volumes" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:16 +msgid "Docker Daemon settings" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:489 +msgid "Docker Image" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:30 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:46 +msgid "Docker Root Dir" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:93 +msgid "Docker Socket Path" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:42 +msgid "Docker Version" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm:91 +msgid "Docker actions done." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:70 +msgid "DockerMan" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:13 +msgid "DockerMan is a simple docker manager client for LuCI" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:68 +msgid "DockerMan settings" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:172 +msgid "Download" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:82 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:40 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:85 +msgid "Driver" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:265 +msgid "Duplicate/Edit" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:120 +msgid "Enable IPv6" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:351 +msgid "Env" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:546 +msgid "Environmental Variable(-e)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:54 +msgid "Error" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:42 +#: applications/luci-app-dockerman/luasrc/view/dockerman/logs.htm:5 +msgid "Events" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:116 +msgid "Exclude IPs" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:247 +msgid "Export" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:585 +msgid "Exposed All Ports(-P)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:560 +msgid "Exposed Ports(-p)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:55 +msgid "Fatal" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:6 +msgid "File" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:324 +msgid "Finish Time" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:220 +msgid "Force Remove" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:88 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:106 +msgid "Gateway" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:33 +msgid "Github" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm:4 +msgid "Go to relevant configuration page" +msgstr "" + +#: applications/luci-app-dockerman/root/usr/share/rpcd/acl.d/luci-app-dockerman.json:3 +msgid "Grant UCI access for luci-app-dockerman" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:330 +msgid "Healthy" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:578 +msgid "Host Name" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:100 +msgid "Host or IP Address for the connection to a remote docker instance" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:300 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:142 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:78 +msgid "ID" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:44 +msgid "IP VLAN" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:111 +msgid "IP range" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:522 +msgid "IPv4 Address" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:132 +msgid "IPv6 Gateway" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:126 +msgid "IPv6 Subnet" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:304 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "Image" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:39 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:151 +msgid "Images" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:132 +msgid "Images overview" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:4 +msgid "Import" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:125 +msgid "Import Image" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:47 +msgid "Index Server Address" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:52 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:414 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:102 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:3 +msgid "Info" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:74 +msgid "Ingress" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:75 +msgid "" +"Ingress network is the network which provides the routing-mesh in swarm mode" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:8 +msgid "Inspect" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:477 +msgid "Interactive (-i)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:86 +msgid "Internal" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:66 +msgid "Ipvlan Mode" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:43 +msgid "" +"It replaces the daemon registry mirrors with a new set of registry mirrors" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:238 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:264 +msgid "Kill" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:70 +msgid "L2 bridge" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:71 +msgid "L3 bridge" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:359 +msgid "Links" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:527 +msgid "Links with other containers" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:283 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_load.htm:2 +msgid "Load" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:49 +msgid "Log Level" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:661 +msgid "Log driver options" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:9 +msgid "Logs" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:43 +msgid "MAC VLAN" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:589 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:644 +msgid "Memory" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:783 +msgid "Memory Useage" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:645 +msgid "" +"Memory limit (format: []). Number is a positive integer. Unit " +"can be one of b, k, m, or g. Minimum is 4M" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:590 +msgid "" +"Memory limit (format: []). Number is a positive integer. Unit " +"can be one of b, k, m, or g. Minimum is 4M." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:57 +msgid "Mode" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:90 +msgid "Mount Point" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:603 +msgid "Mount tmpfs directory" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:343 +msgid "Mount/Volume" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:175 +msgid "Mounts" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:295 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:419 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:83 +msgid "Name" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:37 +msgid "Name of the network that can be selected during container creation" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:394 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:528 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:169 +msgid "Network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:80 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:36 +msgid "Network Name" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:40 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:518 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:169 +msgid "Networks" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:59 +msgid "Networks overview" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:104 +msgid "New" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:39 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "New tag" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:627 +msgid "Number of CPUs. Number is a fractional number. 0.000 means no limit" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:574 +msgid "Number of CPUs. Number is a fractional number. 0.000 means no limit." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:73 +msgid "" +"On this page all images are displayed that are available on the system and " +"with which a container can be created." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:193 +msgid "On this page, the selected container can be managed." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:82 +msgid "Options" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:45 +msgid "Overlay network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:37 +msgid "Overview" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:33 +msgid "PLEASE CONFIRM" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:84 +msgid "Parent Interface" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:64 +msgid "Pass-through (Mirror physical device to single MAC VLAN)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "Please input new tag" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:270 +msgid "Please input the PATH and select the file !" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:82 +msgid "Please input the PORT or HOST IP of remote docker instance!" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:86 +msgid "Please input the SOCKET PATH of docker daemon!" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Plese input command line:" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:355 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:172 +msgid "Ports" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:124 +msgid "Ports allowed to be accessed" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:62 +msgid "Private (Prevent communication between MAC VLANs)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:504 +msgid "Privileged" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:561 +msgid "Publish container's port(s) to the host" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:100 +msgid "Pull" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:83 +msgid "Pull Image" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:42 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:48 +msgid "Registry Mirrors" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:73 +msgid "Remote Endpoint" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:99 +msgid "Remote Host" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:106 +msgid "Remote Port" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:274 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:274 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:210 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:115 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:108 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:173 +msgid "Remove" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:43 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:82 +msgid "Remove tag" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:171 +msgid "Rename" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:145 +msgid "RepoTags" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:469 +msgid "Resolve CLI" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:4 +msgid "Resources" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:220 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:244 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:87 +msgid "Restart" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:334 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:427 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:510 +msgid "Restart Policy" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:86 +msgid "Restrict external access to the network" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm:31 +msgid "Reveal/hide password" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:566 +msgid "Run command" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:230 +msgid "Save" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:533 +msgid "Set custom DNS servers" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:547 +msgid "Set environment variables to inside the container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:50 +msgid "Set the logging level" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:151 +msgid "Size" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:61 +msgid "" +"Specifies where the Docker daemon will listen for client connections " +"(default: unix:///var/run/docker.sock)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:211 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:234 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:65 +msgid "Start" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:319 +msgid "Start Time" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:789 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:790 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:5 +msgid "Stats" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:308 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:165 +msgid "Status" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:229 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:254 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:65 +msgid "Stop" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Submit" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:86 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:101 +msgid "Subnet" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:375 +msgid "Sysctl" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:610 +msgid "Sysctl(--sysctl)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:611 +msgid "Sysctls (kernel parameters) options" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:792 +msgid "TOP" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:483 +msgid "TTY (-t)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm:56 +msgid "TX/RX" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:579 +msgid "The hostname to use for the container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:662 +msgid "The logging configuration for this container" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:540 +msgid "" +"The user that commands are run as inside the container.(format: name|uid[:" +"group|gid])" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:129 +msgid "" +"This page displays all containers that have been created on the connected " +"docker host." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:55 +msgid "" +"This page displays all docker networks that have been created on the " +"connected docker host." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:367 +msgid "Tmpfs" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:602 +msgid "Tmpfs(--tmpfs)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:45 +msgid "Total Memory" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:697 +msgid "UID" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:297 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:336 +msgid "Update" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:256 +msgid "Upgrade" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:7 +msgid "Upload" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:303 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:304 +msgid "Upload Error" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:294 +msgid "Upload Success" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm:48 +msgid "Upload/Download" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:339 +msgid "User" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:539 +msgid "User(-u)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:63 +msgid "VEPA (Virtual Ethernet Port Aggregator)" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:41 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:187 +msgid "Volumes" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:73 +msgid "Volumes overview" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:53 +msgid "Warning" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:126 +msgid "" +"When pressing the Import button, both a local image can be loaded onto the " +"system and a valid image tar can be downloaded from remote." +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:124 +msgid "" +"Which Port(s) can be accessed, it's not restricted by the Allowed Access " +"interfaces configuration. Use this configuration with caution!" +msgstr "" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:118 +msgid "" +"Which interface(s) can access containers under the bridge network, fill-in " +"Interface Name" +msgstr "" diff --git a/luci-app-dockerman/po/zh-cn/dockerman.po b/luci-app-dockerman/po/zh-cn/dockerman.po new file mode 100755 index 000000000..2bdc11b8d --- /dev/null +++ b/luci-app-dockerman/po/zh-cn/dockerman.po @@ -0,0 +1,1094 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-19 04:16+0000\n" +"Last-Translator: Eric \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2-dev\n" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:619 +msgid "A list of kernel capabilities to add to the container" +msgstr "要添加到容器的内核功能列表" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:69 +msgid "Access Control" +msgstr "访问控制" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:223 +msgid "Add" +msgstr "新增" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:595 +msgid "Add host device to the container" +msgstr "将主机设备添加到容器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:571 +msgid "Advance" +msgstr "高级选项" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:586 +msgid "Allocates an ephemeral host port for all of a container's exposed ports" +msgstr "为容器的所有暴露端口分配临时主机端口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:118 +msgid "Allowed access interfaces" +msgstr "允许的访问接口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:498 +msgid "Always pull image first" +msgstr "总是先拉取镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:29 +msgid "" +"An overview with the relevant data is displayed here with which the LuCI " +"docker client is connected." +msgstr "在此展示与LuCI docker客户端相连接的相关数据的概览。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:43 +msgid "Api Version" +msgstr "Api 版本" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:94 +msgid "Auto create macvlan interface in Openwrt" +msgstr "在 Openwrt 中自动创建 macvlan 界面" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:18 +msgid "Auto start" +msgstr "自动启动" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:134 +msgid "Available" +msgstr "可用" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:47 +msgid "Base device" +msgstr "基设备" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:553 +msgid "Bind Mount(-v)" +msgstr "绑定挂载(-v)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:554 +msgid "Bind mount a volume" +msgstr "绑定挂载卷" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:596 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:652 +msgid "Block IO Weight" +msgstr "块 IO 权重" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:653 +msgid "" +"Block IO weight (relative weight) accepts a weight value between 10 and 1000" +msgstr "块 IO 权重(相对权重)接受10到1000之间的数值" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:597 +msgid "" +"Block IO weight (relative weight) accepts a weight value between 10 and 1000." +msgstr "块 IO 权重(相对权重)接受10到1000之间的数值。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:61 +msgid "Bridge (Support direct communication between MAC VLANs)" +msgstr "桥接(支持 MAC VLAN 之间的直接通信)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:42 +msgid "Bridge device" +msgstr "Bridge device" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:84 +msgid "" +"By entering a valid image name with the corresponding version, the docker " +"image can be downloaded from the configured registry." +msgstr "" +"通过输入具有相应版本的有效映像名称,可以从镜像存储中心(Registry)中下载" +"docker映像。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:618 +msgid "CAP-ADD(--cap-add)" +msgstr "权限控制(--cap-add)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:581 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:635 +msgid "CPU Shares Weight" +msgstr "CPU 共享权重" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:779 +msgid "CPU Useage" +msgstr "CPU 使用率" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:636 +msgid "" +"CPU shares relative weight, if 0 is set, the system will ignore the value " +"and use the default of 1024" +msgstr "CPU 共享相对权重,如果设置为 0,则系统将忽略该值并使用默认值 1024" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:582 +msgid "" +"CPU shares relative weight, if 0 is set, the system will ignore the value " +"and use the default of 1024." +msgstr "CPU 共享相对权重,如果设置为 0,则系统将忽略该值并使用默认值 1024。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:573 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:626 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:44 +msgid "CPUs" +msgstr "线程数量" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:159 +msgid "Can NOT connect to docker daemon, please check!!" +msgstr "无法连接到docker守护进程(docker daemon),请检查!!" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Cancel" +msgstr "取消" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:60 +msgid "Client connection" +msgstr "客户端连接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:347 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:687 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:182 +msgid "Command" +msgstr "命令" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:100 +msgid "Command line" +msgstr "命令行" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:72 +msgid "Command line Error" +msgstr "命令行错误" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:17 +msgid "Configuration" +msgstr "配置" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:36 +msgid "Configure the default bridge network" +msgstr "配置默认桥接网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:405 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:707 +msgid "Connect" +msgstr "连接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:403 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:437 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:473 +msgid "Connect Network" +msgstr "连接网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:74 +msgid "Connect to remote docker endpoint" +msgstr "连接到远程docker" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:7 +msgid "Console" +msgstr "控制台" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:161 +msgid "Container Info" +msgstr "容器信息" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:650 +msgid "Container Inspect" +msgstr "检查容器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:671 +msgid "Container Logs" +msgstr "容器日志" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:473 +msgid "Container Name" +msgstr "容器名称" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:92 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:58 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:29 +msgid "Container detail" +msgstr "容器详情" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:38 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:142 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:148 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:87 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:133 +msgid "Containers" +msgstr "容器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:94 +msgid "Create macvlan interface" +msgstr "创建 macvlan 接口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:465 +msgid "Create new docker container" +msgstr "创建 docker 容器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:31 +msgid "Create new docker network" +msgstr "创建 docker 网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:312 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:153 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:92 +msgid "Created" +msgstr "创建时间" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:33 +msgid "DELETING" +msgstr "删除中" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:371 +msgid "DNS" +msgstr "DNS" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:51 +msgid "Debug" +msgstr "调试" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:35 +msgid "Default bridge" +msgstr "默认桥接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:363 +msgid "Device" +msgstr "设备" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:594 +msgid "Device(--device)" +msgstr "设备(--device)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:396 +msgid "Disconnect" +msgstr "断开" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:14 +msgid "Docker" +msgstr "Docker" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:12 +msgid "Docker - Configuration" +msgstr "Docker - 配置" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:192 +msgid "Docker - Container (%s)" +msgstr "Docker - 容器 (%s)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:128 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:450 +msgid "Docker - Containers" +msgstr "Docker - 容器" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/logs.htm:3 +msgid "Docker - Events" +msgstr "Docker - 事件" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:72 +msgid "Docker - Images" +msgstr "Docker - 镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:15 +msgid "Docker - Network" +msgstr "Docker - 网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:54 +msgid "Docker - Networks" +msgstr "Docker - 网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:28 +msgid "Docker - Overview" +msgstr "Docker - 概览" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:69 +msgid "Docker - Volumes" +msgstr "Docker - 存储卷" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:16 +msgid "Docker Daemon settings" +msgstr "Docker 服务端(Docker Daemon)设置" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:489 +msgid "Docker Image" +msgstr "Docker 镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:30 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:46 +msgid "Docker Root Dir" +msgstr "Docker 根目录" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:93 +msgid "Docker Socket Path" +msgstr "Docker 套接字路径" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:42 +msgid "Docker Version" +msgstr "Docker 版本" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/apply_widget.htm:91 +msgid "Docker actions done." +msgstr "Docker 执行完成。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:70 +msgid "DockerMan" +msgstr "DockerMan" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:13 +msgid "DockerMan is a simple docker manager client for LuCI" +msgstr "DockerMan是用于LuCI的简单docker管理器客户端" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:68 +msgid "DockerMan settings" +msgstr "DockerMan设置" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:172 +msgid "Download" +msgstr "下载" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:82 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:40 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:85 +msgid "Driver" +msgstr "驱动" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:265 +msgid "Duplicate/Edit" +msgstr "复制/编辑" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:120 +msgid "Enable IPv6" +msgstr "启用 IPv6" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:351 +msgid "Env" +msgstr "环境变量" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:546 +msgid "Environmental Variable(-e)" +msgstr "环境变量(-e)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:54 +msgid "Error" +msgstr "错误" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:42 +#: applications/luci-app-dockerman/luasrc/view/dockerman/logs.htm:5 +msgid "Events" +msgstr "事件" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:116 +msgid "Exclude IPs" +msgstr "排除 IP" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:247 +msgid "Export" +msgstr "导出" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:585 +msgid "Exposed All Ports(-P)" +msgstr "暴露所有端口(-P)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:560 +msgid "Exposed Ports(-p)" +msgstr "暴露端口(-p)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:55 +msgid "Fatal" +msgstr "致命的" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:6 +msgid "File" +msgstr "文件" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:324 +msgid "Finish Time" +msgstr "完成时间" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:220 +msgid "Force Remove" +msgstr "强制移除" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:88 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:106 +msgid "Gateway" +msgstr "网关" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:33 +msgid "Github" +msgstr "Github" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm:4 +msgid "Go to relevant configuration page" +msgstr "进入相关配置页面" + +#: applications/luci-app-dockerman/root/usr/share/rpcd/acl.d/luci-app-dockerman.json:3 +msgid "Grant UCI access for luci-app-dockerman" +msgstr "授予 UCI 访问 luci-app-dockerman 的权限" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:330 +msgid "Healthy" +msgstr "健康" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:578 +msgid "Host Name" +msgstr "主机名" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:100 +msgid "Host or IP Address for the connection to a remote docker instance" +msgstr "连接到远程Docker实例的主机名或IP地址" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:300 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:142 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:78 +msgid "ID" +msgstr "ID" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:44 +msgid "IP VLAN" +msgstr "IP VLAN" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:111 +msgid "IP range" +msgstr "IP 范围" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:522 +msgid "IPv4 Address" +msgstr "IPv4 地址" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:132 +msgid "IPv6 Gateway" +msgstr "IPv6 网关" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:126 +msgid "IPv6 Subnet" +msgstr "IPv6 子网" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:304 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "Image" +msgstr "镜像" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:39 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:151 +msgid "Images" +msgstr "镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:132 +msgid "Images overview" +msgstr "镜像概览" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:4 +msgid "Import" +msgstr "导入" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:125 +msgid "Import Image" +msgstr "导入镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:47 +msgid "Index Server Address" +msgstr "索引服务器地址" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:52 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:414 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:102 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:3 +msgid "Info" +msgstr "信息" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:74 +msgid "Ingress" +msgstr "入口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:75 +msgid "" +"Ingress network is the network which provides the routing-mesh in swarm mode" +msgstr "入口网络是以群模式提供路由网格的网络" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:8 +msgid "Inspect" +msgstr "检查" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:477 +msgid "Interactive (-i)" +msgstr "交互(-i)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:86 +msgid "Internal" +msgstr "内部" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:66 +msgid "Ipvlan Mode" +msgstr "Ipvlan 模式" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:43 +msgid "" +"It replaces the daemon registry mirrors with a new set of registry mirrors" +msgstr "" +"设置新的镜像存储中心(Registry)镜像源,这将取代服务端(daemon)配置的镜像存" +"储中心(Registry)的镜像源" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:238 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:264 +msgid "Kill" +msgstr "强制关闭" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:70 +msgid "L2 bridge" +msgstr "L2 桥接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:71 +msgid "L3 bridge" +msgstr "L3 桥接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:359 +msgid "Links" +msgstr "链接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:527 +msgid "Links with other containers" +msgstr "与其他容器的链接" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:283 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_load.htm:2 +msgid "Load" +msgstr "负载" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:49 +msgid "Log Level" +msgstr "日志等级" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:661 +msgid "Log driver options" +msgstr "日志驱动选项" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:9 +msgid "Logs" +msgstr "日志" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:43 +msgid "MAC VLAN" +msgstr "MAC VLAN" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:589 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:644 +msgid "Memory" +msgstr "内存" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:783 +msgid "Memory Useage" +msgstr "内存使用率" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:645 +msgid "" +"Memory limit (format: []). Number is a positive integer. Unit " +"can be one of b, k, m, or g. Minimum is 4M" +msgstr "" +"内存限制(格式:<数字>[<单位>])。数字是正整数。单位可以是 b、k、m 或 g 之一。" +"最小值为 4M" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:590 +msgid "" +"Memory limit (format: []). Number is a positive integer. Unit " +"can be one of b, k, m, or g. Minimum is 4M." +msgstr "" +"内存限制(格式:<数字>[<单位>])。数字是正整数。单位可以是 b、k、m 或 g 之一。" +"最小值为 4M。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:57 +msgid "Mode" +msgstr "模式" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:90 +msgid "Mount Point" +msgstr "挂载点" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:603 +msgid "Mount tmpfs directory" +msgstr "挂载 tmpfs 目录" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:343 +msgid "Mount/Volume" +msgstr "挂载/卷" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:175 +msgid "Mounts" +msgstr "挂载点" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:295 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:419 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:83 +msgid "Name" +msgstr "名称" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:37 +msgid "Name of the network that can be selected during container creation" +msgstr "在容器创建时可以选择网络的名称" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:394 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:528 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:169 +msgid "Network" +msgstr "网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:80 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:36 +msgid "Network Name" +msgstr "网络名称" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:40 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:518 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:169 +msgid "Networks" +msgstr "网络" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:59 +msgid "Networks overview" +msgstr "网络概览" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:104 +msgid "New" +msgstr "新建" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:39 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "New tag" +msgstr "新建标签" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:627 +msgid "Number of CPUs. Number is a fractional number. 0.000 means no limit" +msgstr "CPU 数量。数字是小数。0.000 表示没有限制" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:574 +msgid "Number of CPUs. Number is a fractional number. 0.000 means no limit." +msgstr "CPU 数量。数字是小数。0.000 表示没有限制。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:73 +msgid "" +"On this page all images are displayed that are available on the system and " +"with which a container can be created." +msgstr "在此页面上,显示系统上可用的所有镜像文件,并可以用它们来创建容器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:193 +msgid "On this page, the selected container can be managed." +msgstr "在此页面可以管理所选的容器。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:82 +msgid "Options" +msgstr "选项" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:45 +msgid "Overlay network" +msgstr "Overlay network" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:37 +msgid "Overview" +msgstr "概览" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:33 +msgid "PLEASE CONFIRM" +msgstr "请确认" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:84 +msgid "Parent Interface" +msgstr "父接口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:64 +msgid "Pass-through (Mirror physical device to single MAC VLAN)" +msgstr "直通(将物理设备镜像到单独的 MAC VLAN)" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:54 +msgid "Please input new tag" +msgstr "请输入新的标签" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:270 +msgid "Please input the PATH and select the file !" +msgstr "请输入路径并选择文件!" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:82 +msgid "Please input the PORT or HOST IP of remote docker instance!" +msgstr "请输入合法的远程docker实例端口和主机IP" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:86 +msgid "Please input the SOCKET PATH of docker daemon!" +msgstr "请输入合法docker服务端(docker daemon)的SOCKET地址" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Plese input command line:" +msgstr "请输入 的命令行:" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:355 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:172 +msgid "Ports" +msgstr "端口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:124 +msgid "Ports allowed to be accessed" +msgstr "允许访问的端口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:62 +msgid "Private (Prevent communication between MAC VLANs)" +msgstr "专用(阻止 MAC VLAN 之间的通信)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:504 +msgid "Privileged" +msgstr "特权模式" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:561 +msgid "Publish container's port(s) to the host" +msgstr "将容器的端口发布到主机" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:100 +msgid "Pull" +msgstr "拉取" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:83 +msgid "Pull Image" +msgstr "拉取镜像" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:42 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:48 +msgid "Registry Mirrors" +msgstr "镜像加速器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:73 +msgid "Remote Endpoint" +msgstr "远程实例" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:99 +msgid "Remote Host" +msgstr "远程主机" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:106 +msgid "Remote Port" +msgstr "远程端口" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:274 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:274 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:210 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:115 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:108 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:173 +msgid "Remove" +msgstr "移除" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:43 +#: applications/luci-app-dockerman/luasrc/view/dockerman/images_import.htm:82 +msgid "Remove tag" +msgstr "移除标签" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:171 +msgid "Rename" +msgstr "重命名" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:145 +msgid "RepoTags" +msgstr "仓库标签" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:469 +msgid "Resolve CLI" +msgstr "解析 CLI" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:4 +msgid "Resources" +msgstr "资源" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:220 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:244 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:87 +msgid "Restart" +msgstr "重新启动" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:334 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:427 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:510 +msgid "Restart Policy" +msgstr "重启策略" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:86 +msgid "Restrict external access to the network" +msgstr "限制外部网络访问" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm:31 +msgid "Reveal/hide password" +msgstr "显示/隐藏 密码" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:566 +msgid "Run command" +msgstr "运行命令" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:230 +msgid "Save" +msgstr "保存" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:533 +msgid "Set custom DNS servers" +msgstr "设置自定义 DNS 服务器" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:547 +msgid "Set environment variables to inside the container" +msgstr "在容器内部设置环境变量" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:50 +msgid "Set the logging level" +msgstr "设置日志记录级别" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:151 +msgid "Size" +msgstr "大小" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:61 +msgid "" +"Specifies where the Docker daemon will listen for client connections " +"(default: unix:///var/run/docker.sock)" +msgstr "" +"指定Docker服务端(Docker daemon)将在何处侦听客户端连接(默认: unix:///var/" +"run/docker.sock)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:211 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:234 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:65 +msgid "Start" +msgstr "启动" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:319 +msgid "Start Time" +msgstr "开始时间" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:789 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:790 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container.htm:5 +msgid "Stats" +msgstr "状态" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:308 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:165 +msgid "Status" +msgstr "状态" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:229 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:254 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:65 +msgid "Stop" +msgstr "停止" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/newcontainer_resolve.htm:91 +msgid "Submit" +msgstr "提交" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:86 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:101 +msgid "Subnet" +msgstr "子网" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:375 +msgid "Sysctl" +msgstr "系统控制" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:610 +msgid "Sysctl(--sysctl)" +msgstr "系统控制(--sysctl)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:611 +msgid "Sysctls (kernel parameters) options" +msgstr "系统控制(内核参数)选项" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:792 +msgid "TOP" +msgstr "TOP" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:483 +msgid "TTY (-t)" +msgstr "TTY(-t)" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm:56 +msgid "TX/RX" +msgstr "发射/接收" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:579 +msgid "The hostname to use for the container" +msgstr "容器使用的主机名" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:662 +msgid "The logging configuration for this container" +msgstr "该容器的日志记录配置" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:540 +msgid "" +"The user that commands are run as inside the container.(format: name|uid[:" +"group|gid])" +msgstr "在容器中以用户运行命令。(格式:name|uid[:group|gid])" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/containers.lua:129 +msgid "" +"This page displays all containers that have been created on the connected " +"docker host." +msgstr "此页面显示在连接的Docker主机上已创建的所有容器。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/networks.lua:55 +msgid "" +"This page displays all docker networks that have been created on the " +"connected docker host." +msgstr "此页面显示在已连接的Docker主机上创建的所有Docker网络。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:367 +msgid "Tmpfs" +msgstr "Tmpfs" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:602 +msgid "Tmpfs(--tmpfs)" +msgstr "Tmpfs(--tmpfs)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/overview.lua:45 +msgid "Total Memory" +msgstr "总内存" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:697 +msgid "UID" +msgstr "UID" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:297 +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:336 +msgid "Update" +msgstr "更新" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:256 +msgid "Upgrade" +msgstr "升级" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:7 +msgid "Upload" +msgstr "上传" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:303 +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:304 +msgid "Upload Error" +msgstr "上传错误" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_file_manager.htm:294 +msgid "Upload Success" +msgstr "上传成功" + +#: applications/luci-app-dockerman/luasrc/view/dockerman/container_stats.htm:48 +msgid "Upload/Download" +msgstr "上传/下载" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/container.lua:339 +msgid "User" +msgstr "用户" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newcontainer.lua:539 +msgid "User(-u)" +msgstr "用户(-u)" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/newnetwork.lua:63 +msgid "VEPA (Virtual Ethernet Port Aggregator)" +msgstr "VEPA(虚拟以太网端口聚合器)" + +#: applications/luci-app-dockerman/luasrc/controller/dockerman.lua:41 +#: applications/luci-app-dockerman/luasrc/view/dockerman/overview.htm:187 +msgid "Volumes" +msgstr "存储卷" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/volumes.lua:73 +msgid "Volumes overview" +msgstr "卷概览" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:53 +msgid "Warning" +msgstr "警告" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/images.lua:126 +msgid "" +"When pressing the Import button, both a local image can be loaded onto the " +"system and a valid image tar can be downloaded from remote." +msgstr "" +"按下导入按钮时,既可以将本地镜像文件加载到系统上,也可以从远程下载有效的Tar格" +"式的镜像文件。" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:124 +msgid "" +"Which Port(s) can be accessed, it's not restricted by the Allowed Access " +"interfaces configuration. Use this configuration with caution!" +msgstr "设置可以被访问的端口,该配置不受“允许的访问接口”配置的限制。请谨慎使用该配置选项!" + +#: applications/luci-app-dockerman/luasrc/model/cbi/dockerman/configuration.lua:118 +msgid "" +"Which interface(s) can access containers under the bridge network, fill-in " +"Interface Name" +msgstr "哪些接口可以访问桥接网络下的容器,请填写接口名称" + +#~ msgid "Containers allowed to be accessed" +#~ msgstr "允许访问的容器" + +#~ msgid "" +#~ "Which container(s) under bridge network can be accessed, even from " +#~ "interfaces that are not allowed, fill-in Container Id or Name" +#~ msgstr "" +#~ "桥接网络下哪些容器可以访问,即使是不允许从接口访问,也要填写容器 ID 或名称" + +#~ msgid "Connect to remote endpoint" +#~ msgstr "连接到远程终端" + +#~ msgid "Global settings" +#~ msgstr "全局设定" + +#~ msgid "Path" +#~ msgstr "路径" + +#~ msgid "Please input the PATH !" +#~ msgstr "请输入合法路径!" + +#~ msgid "Setting" +#~ msgstr "设置" + +#~ msgid "Specifies where the Docker daemon will listen for client connections" +#~ msgstr "指定Docker服务端(Docker daemon)侦听客户端连接的位置" + +#~ msgid "Docker Container" +#~ msgstr "Docker 容器" + +#~ msgid "" +#~ "DockerMan is a Simple Docker manager client for LuCI, If you have any " +#~ "issue please visit:" +#~ msgstr "" +#~ "DockerMan 是一个简单的 LuCI 客户端 Docker 管理器,如果您有任何问题,请访" +#~ "问:" + +#~ msgid "Import Images" +#~ msgstr "导入镜像" + +#~ msgid "New Container" +#~ msgstr "新建容器" + +#~ msgid "New Network" +#~ msgstr "新建网络" + +#~ msgid "Macvlan Mode" +#~ msgstr "Macvlan 模式" + +#~ msgid "" +#~ "Daemon unix socket (unix:///var/run/docker.sock) or TCP Remote Hosts " +#~ "(tcp://0.0.0.0:2375), default: unix:///var/run/docker.sock" +#~ msgstr "" +#~ "守护进程 unix 套接字 (unix:///var/run/docker.sock) 或 TCP 远程主机 " +#~ "(tcp://0.0.0.0:2375),默认值:unix:///var/run/docker.sock" + +#~ msgid "Docker Daemon" +#~ msgstr "Docker 服务端" + +#~ msgid "Dockerman connect to remote endpoint" +#~ msgstr "Dockerman 连接到远程端点" + +#~ msgid "Enable" +#~ msgstr "启用" + +#~ msgid "Server Host" +#~ msgstr "服务器主机" + +#~ msgid "Contaienr Info" +#~ msgstr "容器信息" diff --git a/luci-app-dockerman/po/zh_Hans b/luci-app-dockerman/po/zh_Hans new file mode 100755 index 000000000..41451e4a1 --- /dev/null +++ b/luci-app-dockerman/po/zh_Hans @@ -0,0 +1 @@ +zh-cn \ No newline at end of file diff --git a/luci-app-dockerman/postinst b/luci-app-dockerman/postinst new file mode 100755 index 000000000..b0db1cb89 --- /dev/null +++ b/luci-app-dockerman/postinst @@ -0,0 +1,14 @@ +#!/bin/sh + +/init.sh env +touch /etc/config/dockerd +uci set dockerd.dockerman=dockerman +uci set dockerd.dockerman.socket_path=`uci get dockerd.dockerman.socket_path 2&> /dev/null || echo '/var/run/docker.sock'` +uci set dockerd.dockerman.status_path=`uci get dockerd.dockerman.status_path 2&> /dev/null || echo '/tmp/.docker_action_status'` +uci set dockerd.dockerman.debug=`uci get dockerd.dockerman.debug 2&> /dev/null || echo 'false'` +uci set dockerd.dockerman.debug_path=`uci get dockerd.dockerman.debug_path 2&> /dev/null || echo '/tmp/.docker_debug'` +uci set dockerd.dockerman.remote_port=`uci get dockerd.dockerman.remote_port 2&> /dev/null || echo '2375'` +uci set dockerd.dockerman.remote_endpoint=`uci get dockerd.dockerman.remote_endpoint 2&> /dev/null || echo '0'` +uci del_list dockerd.dockerman.ac_allowed_interface='br-lan' +uci add_list dockerd.dockerman.ac_allowed_interface='br-lan' +uci commit dockerd \ No newline at end of file diff --git a/luci-app-dockerman/root/etc/init.d/dockerman b/luci-app-dockerman/root/etc/init.d/dockerman new file mode 100755 index 000000000..80309aeab --- /dev/null +++ b/luci-app-dockerman/root/etc/init.d/dockerman @@ -0,0 +1,131 @@ +#!/bin/sh /etc/rc.common + +START=99 +USE_PROCD=1 +# PROCD_DEBUG=1 +config_load 'dockerd' +# config_get daemon_ea "dockerman" daemon_ea +_DOCKERD=/etc/init.d/dockerd + +docker_running(){ + docker version > /dev/null 2>&1 + return $? +} + +add_ports() { + [ $# -eq 0 ] && return + $($_DOCKERD running) && docker_running || return 1 + ids=$@ + for id in $ids; do + id=$(docker ps --filter "ID=$id" --quiet) + [ -z "$id" ] && { + echo "Docker containner not running"; + return 1; + } + ports=$(docker ps --filter "ID=$id" --format "{{.Ports}}") + # echo "$ports" + for port in $ports; do + echo "$port" | grep -qE "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:.*$" || continue; + [ "${port: -1}" == "," ] && port="${port:0:-1}" + local protocol="" + [ "${port%tcp}" != "$port" ] && protocol="/tcp" + [ "${port%udp}" != "$port" ] && protocol="/udp" + [ "$protocol" == "" ] && continue + port="${port%%->*}" + port="${port##*:}" + uci_add_list dockerd dockerman ac_allowed_ports "${port}${protocol}" + done + done + uci_commit dockerd +} + + +convert() { + _convert() { + _id=$1 + _id=$(docker ps --all --filter "ID=$_id" --quiet) + if [ -z "$_id" ]; then + uci_remove_list dockerd dockerman ac_allowed_container "$1" + return + fi + if /etc/init.d/dockerman add_ports "$_id"; then + uci_remove_list dockerd dockerman ac_allowed_container "$_id" + fi + } + config_list_foreach dockerman ac_allowed_container _convert + uci_commit dockerd +} + +iptables_append(){ + # Wait for a maximum of 10 second per command, retrying every millisecond + local iptables_wait_args="--wait 10 --wait-interval 1000" + if ! iptables ${iptables_wait_args} --check $@ 2>/dev/null; then + iptables ${iptables_wait_args} -A $@ 2>/dev/null + fi +} + +init_dockerman_chain(){ + iptables -N DOCKER-MAN >/dev/null 2>&1 + iptables -F DOCKER-MAN >/dev/null 2>&1 + iptables -D DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1 + iptables -I DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1 +} + +delete_dockerman_chain(){ + iptables -D DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1 + iptables -F DOCKER-MAN >/dev/null 2>&1 + iptables -X DOCKER-MAN >/dev/null 2>&1 +} + +add_allowed_interface(){ + iptables_append DOCKER-MAN -i $1 -o docker0 -j RETURN +} + +add_allowed_ports(){ + port=$1 + if [ "${port%/tcp}" != "$port" ]; then + iptables_append DOCKER-MAN -p tcp -m conntrack --ctorigdstport ${port%/tcp} --ctdir ORIGINAL -j RETURN + elif [ "${port%/udp}" != "$port" ]; then + iptables_append DOCKER-MAN -p udp -m conntrack --ctorigdstport ${port%/udp} --ctdir ORIGINAL -j RETURN + fi +} + +handle_allowed_ports(){ + config_list_foreach "dockerman" "ac_allowed_ports" add_allowed_ports +} + +handle_allowed_interface(){ + config_list_foreach "dockerman" "ac_allowed_interface" add_allowed_interface + iptables_append DOCKER-MAN -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1 + iptables_append DOCKER-MAN -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1 + iptables_append DOCKER-MAN -j RETURN >/dev/null 2>&1 +} + +start_service(){ + [ -x "$_DOCKERD" ] && $($_DOCKERD enabled) || return 0 + delete_dockerman_chain + $($_DOCKERD running) && docker_running || return 0 + init_dockerman_chain + handle_allowed_ports + handle_allowed_interface +} + +stop_service(){ + delete_dockerman_chain +} + +service_triggers() { + procd_add_reload_trigger 'dockerd' +} + +reload_service() { + start +} + +boot() { + sleep 5s + start +} + +extra_command "add_ports" "Add allowed ports based on the container ID(s)" +extra_command "convert" "Convert Ac allowed container to AC allowed ports" diff --git a/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman b/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman new file mode 100755 index 000000000..4358728a1 --- /dev/null +++ b/luci-app-dockerman/root/etc/uci-defaults/luci-app-dockerman @@ -0,0 +1,36 @@ +#!/bin/sh + +. $IPKG_INSTROOT/lib/functions.sh + +[ -x "$(command -v dockerd)" ] && chmod +x /etc/init.d/dockerman && /etc/init.d/dockerman enable >/dev/null 2>&1 +sed -i 's/self:cfgvalue(section) or {}/self:cfgvalue(section) or self.default or {}/' /usr/lib/lua/luci/view/cbi/dynlist.htm +/etc/init.d/uhttpd restart >/dev/null 2>&1 +rm -fr /tmp/luci-indexcache /tmp/luci-modulecache >/dev/null 2>&1 +touch /etc/config/dockerd +ls /etc/rc.d/*dockerd &> /dev/null && uci -q set dockerd.globals.auto_start="1" || uci -q set dockerd.globals.auto_start="0" +uci -q batch <<-EOF >/dev/null + set uhttpd.main.script_timeout="3600" + commit uhttpd + set dockerd.dockerman=dockerman + set dockerd.dockerman.socket_path='/var/run/docker.sock' + set dockerd.dockerman.status_path='/tmp/.docker_action_status' + set dockerd.dockerman.debug='false' + set dockerd.dockerman.debug_path='/tmp/.docker_debug' + set dockerd.dockerman.remote_endpoint='0' + + del_list dockerd.dockerman.ac_allowed_interface='br-lan' + add_list dockerd.dockerman.ac_allowed_interface='br-lan' + + commit dockerd +EOF +# remove dockerd firewall +config_load dockerd +remove_firewall(){ + cfg=${1} + uci_remove dockerd ${1} +} +config_foreach remove_firewall firewall +# Convert ac_allowed_container to ac_allowed_ports +(sleep 30s && /etc/init.d/dockerman convert;/etc/init.d/dockerman restart) & + +exit 0 diff --git a/luci-app-dockerman/root/usr/share/rpcd/acl.d/luci-app-dockerman.json b/luci-app-dockerman/root/usr/share/rpcd/acl.d/luci-app-dockerman.json new file mode 100755 index 000000000..78c2c6418 --- /dev/null +++ b/luci-app-dockerman/root/usr/share/rpcd/acl.d/luci-app-dockerman.json @@ -0,0 +1,11 @@ +{ + "luci-app-dockerman": { + "description": "Grant UCI access for luci-app-dockerman", + "read": { + "uci": [ "dockerd" ] + }, + "write": { + "uci": [ "dockerd" ] + } + } +} diff --git a/luci-app-dsvpn/Makefile b/luci-app-dsvpn/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js b/luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/fr/dsvpn.po b/luci-app-dsvpn/po/fr/dsvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/fr/dsvpn.po~ b/luci-app-dsvpn/po/fr/dsvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/ru/dsvpn.po b/luci-app-dsvpn/po/ru/dsvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/templates/dsvpn.pot b/luci-app-dsvpn/po/templates/dsvpn.pot old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/zh_Hans/dsvpn.po b/luci-app-dsvpn/po/zh_Hans/dsvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ b/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/root/usr/share/luci/menu.d/luci-app-dsvpn.json b/luci-app-dsvpn/root/usr/share/luci/menu.d/luci-app-dsvpn.json old mode 100644 new mode 100755 diff --git a/luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json b/luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json old mode 100644 new mode 100755 diff --git a/luci-app-firewall/Makefile b/luci-app-firewall/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js b/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js old mode 100644 new mode 100755 diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js old mode 100644 new mode 100755 index 5ece96be2..73eaa4a22 --- a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js +++ b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js @@ -145,14 +145,14 @@ return view.extend({ o = s.taboption('general', form.Flag, 'masq', _('Masquerading')); o.editable = true; - - o = s.taboption('general', form.Flag, 'fullcone', _('Full Cone')); + o = s.taboption('general', form.Flag, 'fullcone', _('Full Cone')); o.editable = true; - o.depends('masq', '1'); - + o.depends('masq', '1'); + o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamp')); + o.modalonly = true; o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping')); o.modalonly = true; - + o = s.taboption('general', widgets.NetworkSelect, 'network', _('Covered networks')); o.modalonly = true; o.multiple = true; diff --git a/luci-app-firewall/po/bg/firewall.po b/luci-app-firewall/po/bg/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ca/firewall.po b/luci-app-firewall/po/ca/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/cs/firewall.po b/luci-app-firewall/po/cs/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/de/firewall.po b/luci-app-firewall/po/de/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/el/firewall.po b/luci-app-firewall/po/el/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/en/firewall.po b/luci-app-firewall/po/en/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/es/firewall.po b/luci-app-firewall/po/es/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/fr/firewall.po b/luci-app-firewall/po/fr/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/he/firewall.po b/luci-app-firewall/po/he/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/hi/firewall.po b/luci-app-firewall/po/hi/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/hu/firewall.po b/luci-app-firewall/po/hu/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/it/firewall.po b/luci-app-firewall/po/it/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ja/firewall.po b/luci-app-firewall/po/ja/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ko/firewall.po b/luci-app-firewall/po/ko/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/mr/firewall.po b/luci-app-firewall/po/mr/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ms/firewall.po b/luci-app-firewall/po/ms/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/nb_NO/firewall.po b/luci-app-firewall/po/nb_NO/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/pl/firewall.po b/luci-app-firewall/po/pl/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/pt/firewall.po b/luci-app-firewall/po/pt/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/pt_BR/firewall.po b/luci-app-firewall/po/pt_BR/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ro/firewall.po b/luci-app-firewall/po/ro/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/ru/firewall.po b/luci-app-firewall/po/ru/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/sk/firewall.po b/luci-app-firewall/po/sk/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/sv/firewall.po b/luci-app-firewall/po/sv/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/templates/firewall.pot b/luci-app-firewall/po/templates/firewall.pot old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/tr/firewall.po b/luci-app-firewall/po/tr/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/uk/firewall.po b/luci-app-firewall/po/uk/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/vi/firewall.po b/luci-app-firewall/po/vi/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/zh_Hans/firewall.po b/luci-app-firewall/po/zh_Hans/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/po/zh_Hant/firewall.po b/luci-app-firewall/po/zh_Hant/firewall.po old mode 100644 new mode 100755 diff --git a/luci-app-firewall/root/usr/share/luci/menu.d/luci-app-firewall.json b/luci-app-firewall/root/usr/share/luci/menu.d/luci-app-firewall.json old mode 100644 new mode 100755 diff --git a/luci-app-firewall/root/usr/share/rpcd/acl.d/luci-app-firewall.json b/luci-app-firewall/root/usr/share/rpcd/acl.d/luci-app-firewall.json old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/Makefile b/luci-app-glorytun-tcp/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js b/luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po b/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot b/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/root/etc/hotplug.d/iface/30-glorytun b/luci-app-glorytun-tcp/root/etc/hotplug.d/iface/30-glorytun old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun b/luci-app-glorytun-tcp/root/etc/uci-defaults/1200-luci-glorytun old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/root/usr/share/luci/menu.d/luci-app-glorytun-tcp.json b/luci-app-glorytun-tcp/root/usr/share/luci/menu.d/luci-app-glorytun-tcp.json old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-tcp/root/usr/share/rpcd/acl.d/luci-app-glorytun-tcp.json b/luci-app-glorytun-tcp/root/usr/share/rpcd/acl.d/luci-app-glorytun-tcp.json old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/Makefile b/luci-app-glorytun-udp/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js b/luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/fr/glorytun-udp.po b/luci-app-glorytun-udp/po/fr/glorytun-udp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ b/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/ru/glorytun-udp.po b/luci-app-glorytun-udp/po/ru/glorytun-udp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/templates/glorytun-udp.pot b/luci-app-glorytun-udp/po/templates/glorytun-udp.pot old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/root/etc/config/glorytun-udp b/luci-app-glorytun-udp/root/etc/config/glorytun-udp old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/root/etc/hotplug.d/iface/30-glorytun-udp b/luci-app-glorytun-udp/root/etc/hotplug.d/iface/30-glorytun-udp old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/root/etc/uci-defaults/1201-luci-glorytun-udp b/luci-app-glorytun-udp/root/etc/uci-defaults/1201-luci-glorytun-udp old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/root/usr/share/luci/menu.d/luci-app-glorytun-udp.json b/luci-app-glorytun-udp/root/usr/share/luci/menu.d/luci-app-glorytun-udp.json old mode 100644 new mode 100755 diff --git a/luci-app-glorytun-udp/root/usr/share/rpcd/acl.d/luci-app-glorytun-udp.json b/luci-app-glorytun-udp/root/usr/share/rpcd/acl.d/luci-app-glorytun-udp.json old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/LICENSE b/luci-app-haproxy-tcp/LICENSE old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/Makefile b/luci-app-haproxy-tcp/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/README.md b/luci-app-haproxy-tcp/README.md old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/luasrc/controller/haproxy-tcp.lua b/luci-app-haproxy-tcp/luasrc/controller/haproxy-tcp.lua old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/luasrc/model/cbi/haproxy-tcp.lua b/luci-app-haproxy-tcp/luasrc/model/cbi/haproxy-tcp.lua old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/po/fr/haproxy-tcp.po b/luci-app-haproxy-tcp/po/fr/haproxy-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/po/templates/haproxy-tcp.pot b/luci-app-haproxy-tcp/po/templates/haproxy-tcp.pot old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/po/zh-cn/haproxy-tcp.po b/luci-app-haproxy-tcp/po/zh-cn/haproxy-tcp.po old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/root/etc/config/haproxy-tcp b/luci-app-haproxy-tcp/root/etc/config/haproxy-tcp old mode 100644 new mode 100755 diff --git a/luci-app-haproxy-tcp/root/etc/uci-defaults/41_luci-haproxy-tcp b/luci-app-haproxy-tcp/root/etc/uci-defaults/41_luci-haproxy-tcp old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/Makefile b/luci-app-https-dns-proxy/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/controller/https-dns-proxy.lua b/luci-app-https-dns-proxy/luasrc/controller/https-dns-proxy.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/ch.digitale-gesellschaft.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/ch.digitale-gesellschaft.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/cn.rubyfish.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/cn.rubyfish.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/sb.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers.disabled/sb.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.adguard.dns-family.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.adguard.dns-family.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.adguard.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.adguard.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns-family.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns-family.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns-malware.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns-malware.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/com.cloudflare-dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/cz.nic.odvr.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/cz.nic.odvr.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/google.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/google.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/gr.libredns.doh-ads.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/gr.libredns.doh-ads.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/gr.libredns.doh.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/gr.libredns.doh.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns10.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns10.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns11.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns11.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns9.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/net.quad9.dns9.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-adult.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-adult.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-family.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-family.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-security.lua b/luci-app-https-dns-proxy/luasrc/https-dns-proxy/providers/org.cleanbrowsing.doh-security.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua b/luci-app-https-dns-proxy/luasrc/model/cbi/https-dns-proxy.lua old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/buttons.htm b/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/buttons.htm old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/css.htm b/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/css.htm old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/js.htm b/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/js.htm old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/status-textarea.htm b/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/status-textarea.htm old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/status.htm b/luci-app-https-dns-proxy/luasrc/view/https-dns-proxy/status.htm old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/bg/https-dns-proxy.po b/luci-app-https-dns-proxy/po/bg/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ca/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ca/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/cs/https-dns-proxy.po b/luci-app-https-dns-proxy/po/cs/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/de/https-dns-proxy.po b/luci-app-https-dns-proxy/po/de/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/el/https-dns-proxy.po b/luci-app-https-dns-proxy/po/el/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/en/https-dns-proxy.po b/luci-app-https-dns-proxy/po/en/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/es/https-dns-proxy.po b/luci-app-https-dns-proxy/po/es/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/fr/https-dns-proxy.po b/luci-app-https-dns-proxy/po/fr/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/he/https-dns-proxy.po b/luci-app-https-dns-proxy/po/he/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/hi/https-dns-proxy.po b/luci-app-https-dns-proxy/po/hi/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/hu/https-dns-proxy.po b/luci-app-https-dns-proxy/po/hu/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/it/https-dns-proxy.po b/luci-app-https-dns-proxy/po/it/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ja/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ja/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ko/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ko/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/mr/https-dns-proxy.po b/luci-app-https-dns-proxy/po/mr/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ms/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ms/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/nb_NO/https-dns-proxy.po b/luci-app-https-dns-proxy/po/nb_NO/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/pl/https-dns-proxy.po b/luci-app-https-dns-proxy/po/pl/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/pt/https-dns-proxy.po b/luci-app-https-dns-proxy/po/pt/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/pt_BR/https-dns-proxy.po b/luci-app-https-dns-proxy/po/pt_BR/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ro/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ro/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/ru/https-dns-proxy.po b/luci-app-https-dns-proxy/po/ru/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/sk/https-dns-proxy.po b/luci-app-https-dns-proxy/po/sk/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/sv/https-dns-proxy.po b/luci-app-https-dns-proxy/po/sv/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/templates/https-dns-proxy.pot b/luci-app-https-dns-proxy/po/templates/https-dns-proxy.pot old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/tr/https-dns-proxy.po b/luci-app-https-dns-proxy/po/tr/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/uk/https-dns-proxy.po b/luci-app-https-dns-proxy/po/uk/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/vi/https-dns-proxy.po b/luci-app-https-dns-proxy/po/vi/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/zh_Hans/https-dns-proxy.po b/luci-app-https-dns-proxy/po/zh_Hans/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/po/zh_Hant/https-dns-proxy.po b/luci-app-https-dns-proxy/po/zh_Hant/https-dns-proxy.po old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/root/etc/uci-defaults/40_luci-https-dns-proxy b/luci-app-https-dns-proxy/root/etc/uci-defaults/40_luci-https-dns-proxy old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/root/usr/share/luci/menu.d/luci-app-https-dns-proxy.json b/luci-app-https-dns-proxy/root/usr/share/luci/menu.d/luci-app-https-dns-proxy.json old mode 100644 new mode 100755 diff --git a/luci-app-https-dns-proxy/root/usr/share/rpcd/acl.d/luci-app-https-dns-proxy.json b/luci-app-https-dns-proxy/root/usr/share/rpcd/acl.d/luci-app-https-dns-proxy.json old mode 100644 new mode 100755 diff --git a/luci-app-iperf/Makefile b/luci-app-iperf/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-iperf/luasrc/controller/iperf.lua b/luci-app-iperf/luasrc/controller/iperf.lua old mode 100644 new mode 100755 diff --git a/luci-app-iperf/luasrc/view/iperf/test.htm b/luci-app-iperf/luasrc/view/iperf/test.htm old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/de/iperf.po b/luci-app-iperf/po/de/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/de/iperf.po~ b/luci-app-iperf/po/de/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/fr/iperf.po b/luci-app-iperf/po/fr/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/fr/iperf.po~ b/luci-app-iperf/po/fr/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/it/iperf.po b/luci-app-iperf/po/it/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/it/iperf.po~ b/luci-app-iperf/po/it/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/oc/iperf.po b/luci-app-iperf/po/oc/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/oc/iperf.po~ b/luci-app-iperf/po/oc/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/ru/iperf.po b/luci-app-iperf/po/ru/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/templates/iperf.pot b/luci-app-iperf/po/templates/iperf.pot old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/zh_Hans/iperf.po b/luci-app-iperf/po/zh_Hans/iperf.po old mode 100644 new mode 100755 diff --git a/luci-app-iperf/po/zh_Hans/iperf.po~ b/luci-app-iperf/po/zh_Hans/iperf.po~ old mode 100644 new mode 100755 diff --git a/luci-app-iperf/root/etc/config/iperf b/luci-app-iperf/root/etc/config/iperf old mode 100644 new mode 100755 diff --git a/luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json b/luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json old mode 100644 new mode 100755 diff --git a/luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json b/luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json old mode 100644 new mode 100755 diff --git a/luci-app-macvlan/po/zh_Hans/macvlan.po b/luci-app-macvlan/po/zh_Hans/macvlan.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/Makefile b/luci-app-mail/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-mail/luasrc/controller/mail.lua b/luci-app-mail/luasrc/controller/mail.lua old mode 100644 new mode 100755 diff --git a/luci-app-mail/luasrc/model/cbi/mail.lua b/luci-app-mail/luasrc/model/cbi/mail.lua old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/de/mail.po b/luci-app-mail/po/de/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/de/mail.po~ b/luci-app-mail/po/de/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/fr/mail.po b/luci-app-mail/po/fr/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/fr/mail.po~ b/luci-app-mail/po/fr/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/it/mail.po b/luci-app-mail/po/it/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/it/mail.po~ b/luci-app-mail/po/it/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/oc/mail.po b/luci-app-mail/po/oc/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/oc/mail.po~ b/luci-app-mail/po/oc/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/ru/mail.po b/luci-app-mail/po/ru/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/templates/mail.pot b/luci-app-mail/po/templates/mail.pot old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/zh_Hans/mail.po b/luci-app-mail/po/zh_Hans/mail.po old mode 100644 new mode 100755 diff --git a/luci-app-mail/po/zh_Hans/mail.po~ b/luci-app-mail/po/zh_Hans/mail.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mail/root/etc/config/mail b/luci-app-mail/root/etc/config/mail old mode 100644 new mode 100755 diff --git a/luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json b/luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json old mode 100644 new mode 100755 diff --git a/luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json b/luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/Makefile b/luci-app-mlvpn/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js b/luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/fr/mlvpn.po b/luci-app-mlvpn/po/fr/mlvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/fr/mlvpn.po~ b/luci-app-mlvpn/po/fr/mlvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/ru/mlvpn.po b/luci-app-mlvpn/po/ru/mlvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/templates/mlvpn.pot b/luci-app-mlvpn/po/templates/mlvpn.pot old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/zh_Hans/mlvpn.po b/luci-app-mlvpn/po/zh_Hans/mlvpn.po old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ b/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/root/usr/share/luci/menu.d/luci-app-mlvpn.json b/luci-app-mlvpn/root/usr/share/luci/menu.d/luci-app-mlvpn.json old mode 100644 new mode 100755 diff --git a/luci-app-mlvpn/root/usr/share/rpcd/acl.d/luci-app-mlvpn.json b/luci-app-mlvpn/root/usr/share/rpcd/acl.d/luci-app-mlvpn.json old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/Makefile b/luci-app-mptcp/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/htdocs/luci-static/resources/seedrandom.js b/luci-app-mptcp/htdocs/luci-static/resources/seedrandom.js old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/controller/mptcp.lua b/luci-app-mptcp/luasrc/controller/mptcp.lua old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/luasrc/view/mptcp/multipath.htm b/luci-app-mptcp/luasrc/view/mptcp/multipath.htm old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/de/mptcp.po b/luci-app-mptcp/po/de/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/de/mptcp.po~ b/luci-app-mptcp/po/de/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/fr/mptcp.po b/luci-app-mptcp/po/fr/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/it/mptcp.po b/luci-app-mptcp/po/it/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/it/mptcp.po~ b/luci-app-mptcp/po/it/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/oc/mptcp.po b/luci-app-mptcp/po/oc/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/oc/mptcp.po~ b/luci-app-mptcp/po/oc/mptcp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/ru/mptcp.po b/luci-app-mptcp/po/ru/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/templates/mptcp.pot b/luci-app-mptcp/po/templates/mptcp.pot old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/po/zh_Hans/mptcp.po b/luci-app-mptcp/po/zh_Hans/mptcp.po old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json b/luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json old mode 100644 new mode 100755 diff --git a/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json b/luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/LICENSE b/luci-app-nginx-ha/LICENSE old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/Makefile b/luci-app-nginx-ha/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/luasrc/controller/nginx-ha.lua b/luci-app-nginx-ha/luasrc/controller/nginx-ha.lua old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/luasrc/model/cbi/nginx-ha.lua b/luci-app-nginx-ha/luasrc/model/cbi/nginx-ha.lua old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/po/fr/nginx-ha.po b/luci-app-nginx-ha/po/fr/nginx-ha.po old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/po/templates/nginx-ha.pot b/luci-app-nginx-ha/po/templates/nginx-ha.pot old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/root/etc/config/nginx-ha b/luci-app-nginx-ha/root/etc/config/nginx-ha old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/root/etc/uci-defaults/42_luci-nginx-ha b/luci-app-nginx-ha/root/etc/uci-defaults/42_luci-nginx-ha old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/root/usr/share/luci/menu.d/luci-app-nginx-ha.json b/luci-app-nginx-ha/root/usr/share/luci/menu.d/luci-app-nginx-ha.json old mode 100644 new mode 100755 diff --git a/luci-app-nginx-ha/root/usr/share/rpcd/acl.d/luci-app-nginx-ha.json b/luci-app-nginx-ha/root/usr/share/rpcd/acl.d/luci-app-nginx-ha.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile old mode 100644 new mode 100755 index bca6d24e6..8d166a2e4 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,7 +7,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables +sqlite3-cli +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli +ifneq ($(CONFIG_TARGET_ramips),) + LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +endif + PKG_LICENSE:=GPLv3 diff --git a/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js b/luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/de/omr-bypass.po b/luci-app-omr-bypass/po/de/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/de/omr-bypass.po~ b/luci-app-omr-bypass/po/de/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/fr/omr-bypass.po b/luci-app-omr-bypass/po/fr/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po b/luci-app-omr-bypass/po/it/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po~ b/luci-app-omr-bypass/po/it/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/oc/omr-bypass.po b/luci-app-omr-bypass/po/oc/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/oc/omr-bypass.po~ b/luci-app-omr-bypass/po/oc/omr-bypass.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/ru/omr-bypass.po b/luci-app-omr-bypass/po/ru/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/templates/omr-bypass.pot b/luci-app-omr-bypass/po/templates/omr-bypass.pot old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po b/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/etc/config/omr-bypass b/luci-app-omr-bypass/root/etc/config/omr-bypass old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/etc/firewall.omr-bypass b/luci-app-omr-bypass/root/etc/firewall.omr-bypass old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 31045864d..c59107f8d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -1008,7 +1008,8 @@ start_service() { sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass config_foreach _add_proto_without_ndpi proto - sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst.new + mv /usr/share/omr-bypass/omr-bypass-proto.lst.new /usr/share/omr-bypass/omr-bypass-proto.lst logger -t "omr-bypass" "OMR-ByPass is running" } diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass index 8613d3bc3..4207018c1 100755 --- a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass +++ b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass @@ -150,6 +150,7 @@ fi #fi if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep bypass)" = "" ]; then echo "0 2 * * * /etc/init.d/omr-bypass bypass_asn" >> /etc/crontabs/root + echo "*/1 * * * * /etc/init.d/fengshan restart" >> /etc/crontabs/root fi rm -f /tmp/luci-indexcache exit 0 diff --git a/luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json b/luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass-proto.lst old mode 100644 new mode 100755 diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db old mode 100644 new mode 100755 index 2c0740b08..1c03dc910 Binary files a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db and b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db differ diff --git a/luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json b/luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/Makefile b/luci-app-omr-dscp/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/luasrc/controller/omr-dscp.lua b/luci-app-omr-dscp/luasrc/controller/omr-dscp.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua b/luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/luasrc/model/cbi/dscp.lua b/luci-app-omr-dscp/luasrc/model/cbi/dscp.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/de/omr-dscp.po b/luci-app-omr-dscp/po/de/omr-dscp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/de/omr-dscp.po~ b/luci-app-omr-dscp/po/de/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po b/luci-app-omr-dscp/po/fr/omr-dscp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po~ b/luci-app-omr-dscp/po/fr/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po b/luci-app-omr-dscp/po/it/omr-dscp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po~ b/luci-app-omr-dscp/po/it/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/oc/omr-dscp.po b/luci-app-omr-dscp/po/oc/omr-dscp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/oc/omr-dscp.po~ b/luci-app-omr-dscp/po/oc/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/templates/omr-dscp.pot b/luci-app-omr-dscp/po/templates/omr-dscp.pot old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/root/etc/config/dscp b/luci-app-omr-dscp/root/etc/config/dscp old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json b/luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json b/luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/Makefile b/luci-app-omr-quota/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/luasrc/controller/quota.lua b/luci-app-omr-quota/luasrc/controller/quota.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua b/luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm b/luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/de/omr-quota.po b/luci-app-omr-quota/po/de/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/de/omr-quota.po~ b/luci-app-omr-quota/po/de/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/fr/omr-quota.po b/luci-app-omr-quota/po/fr/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/fr/omr-quota.po~ b/luci-app-omr-quota/po/fr/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/it/omr-quota.po b/luci-app-omr-quota/po/it/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/it/omr-quota.po~ b/luci-app-omr-quota/po/it/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/oc/omr-quota.po b/luci-app-omr-quota/po/oc/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/oc/omr-quota.po~ b/luci-app-omr-quota/po/oc/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/ru/omr-quota.po b/luci-app-omr-quota/po/ru/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/templates/omr-quota.pot b/luci-app-omr-quota/po/templates/omr-quota.pot old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/zh_Hans/omr-quota.po b/luci-app-omr-quota/po/zh_Hans/omr-quota.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ b/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json b/luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json b/luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/Makefile b/luci-app-omr-tracker/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/luasrc/controller/omr-tracker.lua b/luci-app-omr-tracker/luasrc/controller/omr-tracker.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua b/luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm b/luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/de/omr-tracker.po b/luci-app-omr-tracker/po/de/omr-tracker.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/de/omr-tracker.po~ b/luci-app-omr-tracker/po/de/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/fr/omr-tracker.po b/luci-app-omr-tracker/po/fr/omr-tracker.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/fr/omr-tracker.po~ b/luci-app-omr-tracker/po/fr/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po b/luci-app-omr-tracker/po/it/omr-tracker.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po~ b/luci-app-omr-tracker/po/it/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/oc/omr-tracker.po b/luci-app-omr-tracker/po/oc/omr-tracker.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/oc/omr-tracker.po~ b/luci-app-omr-tracker/po/oc/omr-tracker.po~ old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/templates/omr-tracker.pot b/luci-app-omr-tracker/po/templates/omr-tracker.pot old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po b/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/root/etc/uci-defaults/42_luci-omr-tracker b/luci-app-omr-tracker/root/etc/uci-defaults/42_luci-omr-tracker old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json b/luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json old mode 100644 new mode 100755 diff --git a/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json b/luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-doing.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-doing.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-done.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-done.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-error.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-error.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-todo.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-todo.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-warn.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-warn.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusError.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusError.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusOK.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusOK.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusWarning.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusWarning.png old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/spinner.gif b/luci-app-openmptcprouter/htdocs/luci-static/resources/spinner.gif old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/backup.htm old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/debug.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/debug.htm old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm old mode 100644 new mode 100755 index cd1b585b9..07f8a7835 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -948,6 +948,7 @@ +
diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po b/luci-app-openmptcprouter/po/de/openmptcprouter.po old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/de/openmptcprouter.po~ b/luci-app-openmptcprouter/po/de/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po b/luci-app-openmptcprouter/po/fr/openmptcprouter.po old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/fr/openmptcprouter.po~ b/luci-app-openmptcprouter/po/fr/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po b/luci-app-openmptcprouter/po/it/openmptcprouter.po old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/it/openmptcprouter.po~ b/luci-app-openmptcprouter/po/it/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/oc/openmptcprouter.po b/luci-app-openmptcprouter/po/oc/openmptcprouter.po old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/oc/openmptcprouter.po~ b/luci-app-openmptcprouter/po/oc/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/templates/openmptcprouter.pot b/luci-app-openmptcprouter/po/templates/openmptcprouter.pot old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po~ b/luci-app-openmptcprouter/po/zh_Hans/openmptcprouter.po~ old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/root/bin/omr-modemmanager b/luci-app-openmptcprouter/root/bin/omr-modemmanager index 3cdbbda6f..d53865837 100755 --- a/luci-app-openmptcprouter/root/bin/omr-modemmanager +++ b/luci-app-openmptcprouter/root/bin/omr-modemmanager @@ -6,11 +6,13 @@ timeout 1 mmcli -L | while read MODEM; do MODEM_ID=$(echo $MODEM | awk -F' ' '{print $1}' | awk -F/ '{print $6}') MODEM_INFO="$(timeout 1 mmcli -m $MODEM_ID --output-keyvalue)" if [ -n "$MODEM_INFO" ] && [ "$(echo "$MODEM_INFO" | grep 'modem.generic.device ' | awk -F": " '{print $2}')" = "$MODEM_INTF" ]; then - PERCENT=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.signal-quality.value ' | awk -F": " '{print $2}') - OPERATOR=$(echo "$MODEM_INFO" | grep -m 1 'modem.3gpp.operator-name ' | awk -F": " '{print $2}') - NUMBER=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.own-numbders.value[1]' | awk -F": " '{print $2}') - STATE=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.state ' | awk -F": " '{print $2}') - TYPE=$(echo "$MODEM_INFO" | grep -m 1 'modem.generic.access-technologies.value\[1\]' | awk -F": " '{print $2}') + PERCENT=$(echo "$MODEM_INFO" | grep 'modem.generic.signal-quality.value ' | awk -F": " '{print $2}') + [ -z "$PERCENT" ] && PERCENT=$(awk -v n="$(mmcli -m $MODEM_ID --command 'AT+CSQ')" 'BEGIN{ print int(n*10) }') + OPERATOR=$(echo "$MODEM_INFO" | grep 'modem.3gpp.operator-name ' | awk -F": " '{print $2}') + [ -z "$OPERATOR" ] && OPERATOR=$(mmcli -m $MODEM_ID --command 'AT+QSPN' | awk -F[\"\"] '{ print $2 }') + NUMBER=$(echo "$MODEM_INFO" | grep 'modem.generic.own-numbders.value[1]' | awk -F": " '{print $2}') + STATE=$(echo "$MODEM_INFO" | grep 'modem.generic.state ' | awk -F": " '{print $2}') + TYPE=$(echo "$MODEM_INFO" | grep 'modem.generic.access-technologies.value\[1\]' | awk -F": " '{print $2}') [ -z "$INFO" ] && echo $PERCENT [ "$INFO" = "all" ] && echo "$PERCENT;$OPERATOR;$NUMBER;$STATE;$TYPE" exit diff --git a/luci-app-openmptcprouter/root/etc/config/openmptcprouter b/luci-app-openmptcprouter/root/etc/config/openmptcprouter old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index cec97258f..0befbb606 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -93,8 +93,8 @@ function add_interface(add_interface_ifname) ucic:set("qos","wan" .. i,"interface") ucic:set("qos","wan" .. i,"classgroup","Default") ucic:set("qos","wan" .. i,"enabled","0") - ucic:set("qos","wan" .. i,"upload","4000") - ucic:set("qos","wan" .. i,"download","100000") + ucic:set("qos","wan" .. i,"upload","1000000") + ucic:set("qos","wan" .. i,"download","1000000") ucic:save("qos") ucic:commit("qos") @@ -163,7 +163,7 @@ function set_interface(intf,proto,ipaddr,netmask,gateway,sqmenabled,downloadspee ucic:set("qos",intf,"interface") ucic:set("qos",intf,"classgroup","Default") ucic:set("qos",intf,"enabled","0") - ucic:set("qos",intf,"upload","4000") + ucic:set("qos",intf,"upload","100000") ucic:set("qos",intf,"download","100000") end @@ -1113,9 +1113,7 @@ function interfaces_status() mArray.openmptcprouter['model'] = sys.exec("ubus call system board | jsonfilter -q -e '@.model' 2>/dev/null | tr -d '\n'") local board_name = sys.exec("ubus call system board | jsonfilter -q -e '@.board_name' 2>/dev/null | tr -d '\n'") -- retrieve core temperature - if board_name:match("^raspberrypi.*") then - mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null"):match("%d+") - end + mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null"):match("%d+") mArray.openmptcprouter["loadavg"] = sys.exec("cat /proc/loadavg 2>/dev/null"):match("[%d%.]+ [%d%.]+ [%d%.]+") mArray.openmptcprouter["uptime"] = sys.exec("cat /proc/uptime 2>/dev/null"):match("[%d%.]+") diff --git a/luci-app-openmptcprouter/root/usr/share/luci/menu.d/luci-app-openmptcprouter.json b/luci-app-openmptcprouter/root/usr/share/luci/menu.d/luci-app-openmptcprouter.json old mode 100644 new mode 100755 diff --git a/luci-app-openmptcprouter/root/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json b/luci-app-openmptcprouter/root/usr/share/rpcd/acl.d/luci-app-openmptcprouter.json old mode 100644 new mode 100755 diff --git a/luci-app-packet-capture/Makefile b/luci-app-packet-capture/Makefile new file mode 100755 index 000000000..ef6370df3 --- /dev/null +++ b/luci-app-packet-capture/Makefile @@ -0,0 +1,14 @@ +# Copyright 2020 Wojciech Jowsa (wojciech.jowsa@gmail.com) +# This is free software, licensed under the Apache License, Version 2.0 + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Packet capture application +LUCI_DEPENDS:=+luci-mod-admin-full +tcpdump +uhttpd-mod-ubus +coreutils +coreutils-timeout + +PKG_MAINTAINER:=Wojciech Jowsa +PKG_LICENSE:=Apache-2.0 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signatureet diff --git a/luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js b/luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js new file mode 100755 index 000000000..6bf42cc3f --- /dev/null +++ b/luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js @@ -0,0 +1,287 @@ +'use strict'; +'require rpc'; +'require uci'; +'require ui'; +'require fs'; +'require form'; +'require network'; +'require tools.widgets as widgets'; + +var eventSource, + captureFilePoll, + hostName; + +function stopTcpdump() { + fs.exec("/usr/libexec/packet_capture_stop").then(function(replay) { + if (eventSource) + eventSource.close(); + }.bind(this)).catch(function(error) { + console.log(error); + }); +} + +window.addEventListener('beforeunload', stopTcpdump); + +var callLuciProcessList = rpc.declare({ + object: 'luci', + method: 'getProcessList', + expect: { result: [] } +}); + +var callInitAction = rpc.declare({ + object: 'luci', + method: 'setInitAction', + params: [ 'name', 'action' ], + expect: { result: false } +}); + +function addOutput() { + var tcpdumpOut = document.querySelectorAll('[id$="tcpdump_out"]')[0]; + if (tcpdumpOut) + return; + + var frameEl = E('div', {'class': 'cbi-value'}); + + frameEl.appendChild(E('textarea', { + 'id': 'tcpdump_out', + 'class': 'cbi-input-textarea', + 'readonly': '', + 'style': 'width:100%', + 'rows': 30, + })); + + frameEl.firstElementChild.style.fontFamily = 'monospace'; + + var downloadBtn = document.querySelectorAll('[id$="download_file"]')[0]; + if (downloadBtn) + downloadBtn.parentNode.insertBefore(frameEl, downloadBtn.nextSibling); +} + +var downloadCaptureFile = function(ev) { + var form = E('form', { + method: 'post', + action: '/cgi-bin/cgi-download', + enctype: 'application/x-www-form-urlencoded' + }, E('input', { type: 'hidden', name: 'sessionid', value: rpc.getSessionID()}, + E('input', { type: 'hidden', name: 'path', value: "/tmp/capture.pcap"}, + E('input', { type: 'hidden', name: 'filename', value: hostName + "-" + Date.now() + ".pcap"}, + E('input', { type: 'hidden', name: 'mimetype', value: 'application/vnd.tcpdump.pcap'} + ))))); + + ev.currentTarget.parentNode.appendChild(form); + form.submit(); + form.parentNode.removeChild(form); +} + +function subscribeTcpdump() { + if (eventSource) + eventSource.close(); + + eventSource = new EventSource('/ubus/subscribe/tcpdump' + '?' + rpc.getSessionID()); + eventSource.onerror = function(event) { + eventSource.close(); + console.log(event); + }; + + addOutput(); + var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0]; + textOut.value = ""; + eventSource.addEventListener("tcpdump.data", function(event) { + textOut.value = textOut.value + "\n" + JSON.parse(event.data).data; + }); +} + +function updateButtons() { + var tasks = []; + tasks.push(fs.stat("/var/run/packet_capture.pid").then(L.bind(function(res) { + var downloadBtn = document.querySelectorAll('[id$="download_file"]')[0]; + if (!downloadBtn) + return; + if (!eventSource || eventSource.readyState == 2) + subscribeTcpdump(); + var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0]; + if (textOut) + textOut.style.borderColor = "green"; + var startBtn = document.querySelectorAll('[id$="start_tcpdump"]')[0]; + if (startBtn) + startBtn.hidden = true; + var stopBtn = document.querySelectorAll('[id$="stop_tcpdump"]')[0]; + if (stopBtn) + stopBtn.hidden = false; + return; + })).catch(function(error) { + var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0]; + if (textOut) + textOut.style.borderColor = "red"; + var startBtn = document.querySelectorAll('[id$="start_tcpdump"]')[0]; + if (startBtn) + startBtn.hidden = false; + var stopBtn = document.querySelectorAll('[id$="stop_tcpdump"]')[0]; + if (stopBtn) + stopBtn.hidden = true; + if (eventSource) + eventSource.close(); + })); + + return Promise.all(tasks); +} + +function updatePollCheckCaptureFileExists() { + checkCaptureFileExists(); + L.Poll.remove(captureFilePoll); + L.Poll.add(L.bind(checkCaptureFileExists, m),5); +} + +function checkCaptureFileExists() { + var tasks = []; + tasks.push(fs.stat("/tmp/capture.pcap").then(L.bind(function(res) { + var downloadBtn = document.querySelector('[data-action="download"]'); + if (!downloadBtn) + return; + var downloadCheckBox = document.querySelectorAll('[data-widget-id$="file"]')[0].checked; + if (!downloadCheckBox) { + fs.remove("/tmp/capture.pcap").then(function(replay) { + downloadBtn.disabled = true;; + }.bind(this)).catch(function(error) { + console.log(error); + }); + } else { + downloadBtn.disabled = false; + } + })).catch(function(error) { + var downloadBtn = document.querySelector('[data-action="download"]'); + if (downloadBtn) + downloadBtn.disabled = true; + })); + + return Promise.all(tasks); +} + +return L.view.extend({ + + load: function() { + return Promise.all([ + uci.load('system') + ]); + }, + + handleDownload: function(ev) { + downloadCaptureFile(ev); + }, + + render: function(processes) { + var m, s, o; + + hostName = uci.get('system', '@system[0]', 'hostname'); + + m = new form.Map('packet_capture', _('Packet Capture - Tcpdump'), _('Capture packets with tcpdump.')); + s = m.section(form.TypedSection, 'tcpdump'); + s.anonymous = 1; + + o = s.option(widgets.DeviceSelect, 'interface', _('Interface'), _('')); + o.noaliases = true; + o.modalonly = true; + o.rmempty = false; + o.filter = function(section_id, value) { + return true; + } + + o = s.option(form.Value, 'filter', _('Filter'), _('Tcpdump filter like protocol, port etc.')); + o.modalonly = false; + o.datatype = 'and(minlength(1),maxlength(1024))'; + + o = s.option(form.Value, 'duration', _('Duration'), _('Duration of packet capturing in seconds.')); + o.modalonly = false; + o.datatype = 'range(1,4294967296)'; + + o = s.option(form.Value, 'packets', _('Packets'), _('Number of packets to be captured.')); + o.modalonly = false; + o.datatype = 'range(1,4294967296)'; + + o = s.option(form.Flag, 'domains', _('Resolve domains'), _("Convert host addresses to names.")); + + o = s.option(form.Flag, 'verbose', _('Verbose output'), _("Print the link-level header on each dump line.")); + + o = s.option(form.Flag, 'file', _('Save to file'), _("Save capture to pcap file.")); + + o = s.option(form.Button, 'start_tcpdump', _('Start tcpdump'), _('')); + o.inputstyle = 'apply'; + o.onclick = ui.createHandlerFn(this, function(section_id, ev) { + var downloadBtn = document.querySelector('[data-action="download"]'); + if (!downloadBtn) + return; + fs.remove("/tmp/capture.pcap").then(function(replay) { + downloadBtn.disabled = true;; + }.bind(this)).catch(function(error) { + console.log(error); + }); + + var iface = document.querySelectorAll('[id$="interface"]')[1].value, + filter = document.querySelectorAll('[id$="filter"]')[2].value, + packets = document.querySelectorAll('[id$="packets"]')[2].value, + duration = document.querySelectorAll('[id$="duration"]')[2].value, + verbose = document.querySelectorAll('[data-widget-id$="verbose"]')[0].checked, + domains = document.querySelectorAll('[data-widget-id$="domains"]')[0].checked, + file = document.querySelectorAll('[data-widget-id$="file"]')[0].checked + + var args = { + "interface": iface, + "filter": filter, + "packets": packets, + "duration": duration, + "verbose": verbose, + "domains": domains, + "file": file + } + + return fs.exec_direct('/usr/libexec/packet_capture_start', [JSON.stringify(args)]).then(function(replay) { + var error_position = replay.search("error:"); + if (error_position != -1){ + ui.showModal(_(replay.substring(error_position + 6, replay.length)), [ + E('div', { 'class': 'right' }, [ + E('button', { + 'class': 'cbi-button cbi-button-negative important', + 'click': function(ev) { + ui.hideModal(); + } + }, _('Close')), + ]) + ]); + return; + } + rpc.list.apply(rpc).then(function(res) { + for (var k in res) { + if (res[k] == "tcpdump" ) + subscribeTcpdump() + } + }.bind(this)); + }.bind(this)).catch(function(error) { + console.log(error); + }); + }); + + o = s.option(form.Button, 'stop_tcpdump', _('Stop tcpdump'), _('')); + o.inputstyle = 'apply'; + o.onclick = ui.createHandlerFn(this, function(section_id, ev) { + if (!eventSource) + return; + return fs.exec("/usr/libexec/packet_capture_stop").then(function(replay) { + eventSource.close(); + }.bind(this)).catch(function(error) { + console.log(error); + }); + }); + + o = s.option(form.Button, 'download_file', _('Download capture file')); + o.inputstyle = 'action important'; + o.inputtitle = _('Download'); + o.data_action = 'download' + o.onclick = this.handleDownload; + + L.Poll.add(L.bind(updateButtons, m),1); + captureFilePoll = L.bind(updatePollCheckCaptureFileExists, m); + L.Poll.add(captureFilePoll,1); + + return m.render(); + }, +}); diff --git a/luci-app-packet-capture/po/fr/packet-capture.po b/luci-app-packet-capture/po/fr/packet-capture.po new file mode 100755 index 000000000..f2169d1f7 --- /dev/null +++ b/luci-app-packet-capture/po/fr/packet-capture.po @@ -0,0 +1,99 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Capture packets with tcpdump." +msgstr "Capturez des paquets avec tcpdump." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:247 +msgid "Close" +msgstr "Fermer" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Convert host addresses to names." +msgstr "Convertissez les adresses d'hôte en noms." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:277 +msgid "Download" +msgstr "Téléchargement" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:275 +msgid "Download capture file" +msgstr "Télécharger le fichier de capture" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration" +msgstr "Durée" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration of packet capturing in seconds." +msgstr "Durée de la capture des paquets en secondes." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Filter" +msgstr "Filtre" + +#: luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json:3 +msgid "Grant access to tcpdump ubus object" +msgstr "Accorder l'accès à l'objet ubus tcpdump" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:181 +msgid "Interface" +msgstr "Interface" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Number of packets to be captured." +msgstr "Nombre de paquets à capturer." + +#: luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json:3 +msgid "Packet Capture" +msgstr "Capture de paquets" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Packet Capture - Tcpdump" +msgstr "Capture de paquets - Tcpdump" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Packets" +msgstr "Paquets" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Print the link-level header on each dump line." +msgstr "Imprimez l'en-tête du lien sur chaque ligne de capture." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Resolve domains" +msgstr "Résoudre les domaines" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save capture to pcap file." +msgstr "Enregistrez la capture dans le fichier pcap." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save to file" +msgstr "Enregistrer dans un fichier" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:207 +msgid "Start tcpdump" +msgstr "Démarrez tcpdump" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:263 +msgid "Stop tcpdump" +msgstr "Arrêter tcpdump" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Tcpdump filter like protocol, port etc." +msgstr "Filtre pour tcpdump comme le protocole, le port, etc." + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Verbose output" +msgstr "Sortie verbeuse" diff --git a/luci-app-packet-capture/po/templates/packet-capture.pot b/luci-app-packet-capture/po/templates/packet-capture.pot new file mode 100755 index 000000000..4a2659477 --- /dev/null +++ b/luci-app-packet-capture/po/templates/packet-capture.pot @@ -0,0 +1,90 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Capture packets with tcpdump." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:247 +msgid "Close" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Convert host addresses to names." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:277 +msgid "Download" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:275 +msgid "Download capture file" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration of packet capturing in seconds." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Filter" +msgstr "" + +#: luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json:3 +msgid "Grant access to tcpdump ubus object" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:181 +msgid "Interface" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Number of packets to be captured." +msgstr "" + +#: luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json:3 +msgid "Packet Capture" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Packet Capture - Tcpdump" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Packets" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Print the link-level header on each dump line." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Resolve domains" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save capture to pcap file." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save to file" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:207 +msgid "Start tcpdump" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:263 +msgid "Stop tcpdump" +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Tcpdump filter like protocol, port etc." +msgstr "" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Verbose output" +msgstr "" diff --git a/luci-app-packet-capture/po/zh_Hans/packet-capture.po b/luci-app-packet-capture/po/zh_Hans/packet-capture.po new file mode 100755 index 000000000..c8704a7f9 --- /dev/null +++ b/luci-app-packet-capture/po/zh_Hans/packet-capture.po @@ -0,0 +1,99 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:03+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Capture packets with tcpdump." +msgstr "使用tcpdump捕获数据包。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:247 +msgid "Close" +msgstr "关闭" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Convert host addresses to names." +msgstr "将主机地址转换为名称。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:277 +msgid "Download" +msgstr "下载" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:275 +msgid "Download capture file" +msgstr "下载抓包文件" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration" +msgstr "持续时间" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:193 +msgid "Duration of packet capturing in seconds." +msgstr "抓包时间(以秒为单位)。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Filter" +msgstr "过滤器" + +#: luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json:3 +msgid "Grant access to tcpdump ubus object" +msgstr "授权访问tcpdump ubus对象" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:181 +msgid "Interface" +msgstr "接口" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Number of packets to be captured." +msgstr "需要抓包的个数。" + +#: luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json:3 +msgid "Packet Capture" +msgstr "数据包捕获" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:177 +msgid "Packet Capture - Tcpdump" +msgstr "Tcpdump抓包" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:197 +msgid "Packets" +msgstr "包" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Print the link-level header on each dump line." +msgstr "打印每个转储行上的链接标题。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:201 +msgid "Resolve domains" +msgstr "解决域" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save capture to pcap file." +msgstr "保存捕获到pcap文件。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:205 +msgid "Save to file" +msgstr "保存到文件" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:207 +msgid "Start tcpdump" +msgstr "开始tcp转存" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:263 +msgid "Stop tcpdump" +msgstr "停止tcp转存" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:189 +msgid "Tcpdump filter like protocol, port etc." +msgstr "Tcp转存过滤协议,端口等。" + +#: luci-app-packet-capture/htdocs/luci-static/resources/view/packet_capture/tcpdump.js:203 +msgid "Verbose output" +msgstr "详细输出" diff --git a/luci-app-packet-capture/root/etc/config/packet_capture b/luci-app-packet-capture/root/etc/config/packet_capture new file mode 100755 index 000000000..105a0dc30 --- /dev/null +++ b/luci-app-packet-capture/root/etc/config/packet_capture @@ -0,0 +1 @@ +config tcpdump \ No newline at end of file diff --git a/luci-app-packet-capture/root/usr/libexec/packet_capture b/luci-app-packet-capture/root/usr/libexec/packet_capture new file mode 100755 index 000000000..e1ecf23f7 --- /dev/null +++ b/luci-app-packet-capture/root/usr/libexec/packet_capture @@ -0,0 +1,64 @@ +#!/usr/bin/env lua + +local ubus = require "ubus" +local fs = require "nixio.fs" + +local conn = ubus.connect() +if not conn then + error("Failed to connect to ubus") + return +end + +local args = "-n" +local duration = "" + +if arg[1] ~= nil then + args = arg[1] + if arg[2] ~= "" then + duration = arg[2] + end +end + +local filter = fs.stat("/tmp/tcpdump_filter") +if filter then + args = args .. " -F /tmp/tcpdump_filter" +end + +local ubus_objects = { + tcpdump = { + } +} + +conn:add( ubus_objects ) + +os.execute("sleep 1") + +local command = "tcpdump -l " .. args .. " 2>&1" + +if duration ~= "" then + command = "timeout " .. duration .. " " .. command +end + +local pipe = io.popen(command) + +for line in pipe:lines() do + local params = { + data = line + } + conn:notify(ubus_objects.tcpdump.__ubusobj, "tcpdump.data", params) +end + +local pcap = fs.stat("/tmp/capture.pcap0") +if pcap then + fs.move("/tmp/capture.pcap0","/tmp/capture.pcap") + fs.remove("/tmp/capture.pcap1") +end + +if filter then + fs.remove("/tmp/tcpdump_filter") +end + +conn:close() +pipe:close() + +fs.remove("/var/run/packet_capture.pid") diff --git a/luci-app-packet-capture/root/usr/libexec/packet_capture_start b/luci-app-packet-capture/root/usr/libexec/packet_capture_start new file mode 100755 index 000000000..acdf89152 --- /dev/null +++ b/luci-app-packet-capture/root/usr/libexec/packet_capture_start @@ -0,0 +1,69 @@ +#!/bin/sh + +. /usr/share/libubox/jshn.sh + +PIDFILE="/var/run/packet_capture.pid" + +if [ -f "$PIDFILE"];then + echo "error: Packet capture is running" + exit 1 +fi + +json_load "$1" +json_get_var interface interface +json_get_var filter filter +json_get_var duration duration +json_get_var packets packets +json_get_var verbose verbose +json_get_var domains domains +json_get_var file file + +args="-n" + +if [ "$domains" == "1" ];then + args="" +fi + +if [ -n "$interface" ];then + ip a show "$interface" > /dev/null 2>&1 + if [ "$?" == "1" ]; then + echo "error: Incorrect format of an interface" + exit 1 + fi + + args="$args -i $interface" +fi + +if [ -n "$packets" ];then + echo "$packets" | egrep '^[0-9]*$' + if [ "$?" -eq 0 ];then + args="$args -c $packets" + else + echo "error: Incorrect packets argument" + exit 1 + fi +fi + +if [ "$verbose" == "1" ];then + args="$args -e" +fi + +if [ "$file" == "1" ];then + mem=$(awk '/MemTotal/ {print $2}' /proc/meminfo) + args="$args -W 2 -C $((mem/(1024 * 10))) -w /tmp/capture.pcap -z /usr/libexec/packet_capture_stop" +fi + +if [ -n "$filter" ];then + tcpdump -i lo -d "$filter" >/dev/null 2>/dev/null + if [ $? -eq 1 ];then + echo "error: Incorrect filter argument" + exit 1 + fi + echo "$filter" > /tmp/tcpdump_filter +fi + +(/usr/libexec/packet_capture "$args" "$duration")& + +echo $! > /var/run/packet_capture.pid + +exit 0 diff --git a/luci-app-packet-capture/root/usr/libexec/packet_capture_stop b/luci-app-packet-capture/root/usr/libexec/packet_capture_stop new file mode 100755 index 000000000..bce650346 --- /dev/null +++ b/luci-app-packet-capture/root/usr/libexec/packet_capture_stop @@ -0,0 +1,9 @@ +#!/bin/sh + +pid=$(cat /var/run/packet_capture.pid) +if [ -n "$pid" ] && grep -sq packet_capture "/proc/$pid/cmdline"; then + ppid=$(pgrep -P $pid) + kill -TERM $ppid +fi + +exit 0 diff --git a/luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json b/luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json new file mode 100755 index 000000000..304fe5431 --- /dev/null +++ b/luci-app-packet-capture/root/usr/share/luci/menu.d/luci-app-packet-capture.json @@ -0,0 +1,18 @@ +{ + "admin/services/packet_capture": { + "title": "Packet Capture", + "order": 90, + "action": { + "type": "view", + "path": "packet_capture/tcpdump" + }, + "depends" : { + "acl": [ "luci-app-packet-capture" ], + "uci": { "packet_capture": true }, + "fs": { "/usr/libexec/packet_capture": "executable", + "/usr/libexec/packet_capture_start": "executable", + "/usr/libexec/packet_capture_stop": "executable" + } + } + } +} diff --git a/luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json b/luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json new file mode 100755 index 000000000..f59d4060b --- /dev/null +++ b/luci-app-packet-capture/root/usr/share/rpcd/acl.d/luci-app-packet-capture.json @@ -0,0 +1,25 @@ +{ + "luci-app-packet-capture": { + "description": "Grant access to tcpdump ubus object", + "read": { + "cgi-io": [ "download", "exec" ], + "ubus": { + "tcpdump": [ "*" ], + "luci": [ "getProcessList" ] + }, + "uci": [ "packet_capture", "system" ], + "file": { + "/tmp/capture.pcap": [ "read" ] + } + }, + "write": { + "uci": [ "packet_capture" ], + "file": { + "/usr/libexec/packet_capture_start": [ "exec" ], + "/usr/libexec/packet_capture_stop": [ "exec" ], + "/usr/libexec/packet_capture": [ "exec" ], + "/tmp/capture.pcap": [ "write" ] + } + } + } +} diff --git a/luci-app-shadowsocks-libev/Makefile b/luci-app-shadowsocks-libev/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/htdocs/luci-static/resources/shadowsocks-libev.js b/luci-app-shadowsocks-libev/htdocs/luci-static/resources/shadowsocks-libev.js old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/instances.js b/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/instances.js old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/rules.js b/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/rules.js old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/servers.js b/luci-app-shadowsocks-libev/htdocs/luci-static/resources/view/shadowsocks-libev/servers.js old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/luasrc/controller/shadowsocks-libev.lua b/luci-app-shadowsocks-libev/luasrc/controller/shadowsocks-libev.lua old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/bg/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/bg/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ca/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ca/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/cs/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/cs/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/de/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/de/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/el/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/el/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/en/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/en/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/es/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/es/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/fr/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/fr/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/he/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/he/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/hi/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/hi/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/hu/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/hu/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/it/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/it/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ja/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ja/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ko/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ko/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ms/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ms/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/nb_NO/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/nb_NO/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/pl/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/pl/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/pt/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/pt/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/pt_BR/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/pt_BR/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ro/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ro/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/ru/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/ru/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/sk/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/sk/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/sv/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/sv/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/templates/shadowsocks-libev.pot b/luci-app-shadowsocks-libev/po/templates/shadowsocks-libev.pot old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/tr/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/tr/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/uk/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/uk/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/vi/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/vi/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/zh-cn/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/zh-cn/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/po/zh-tw/shadowsocks-libev.po b/luci-app-shadowsocks-libev/po/zh-tw/shadowsocks-libev.po old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/root/etc/uci-defaults/40_luci-shadowsocks-libev b/luci-app-shadowsocks-libev/root/etc/uci-defaults/40_luci-shadowsocks-libev old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/root/usr/share/luci/menu.d/luci-app-shadowsocks-libev.json b/luci-app-shadowsocks-libev/root/usr/share/luci/menu.d/luci-app-shadowsocks-libev.json old mode 100644 new mode 100755 diff --git a/luci-app-shadowsocks-libev/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-libev.json b/luci-app-shadowsocks-libev/root/usr/share/rpcd/acl.d/luci-app-shadowsocks-libev.json old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/Makefile b/luci-app-shutdown/Makefile old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/htdocs/luci-static/resources/view/system/shutdown.js b/luci-app-shutdown/htdocs/luci-static/resources/view/system/shutdown.js old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/de/shutdown.po b/luci-app-shutdown/po/de/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/fr/shutdown.po b/luci-app-shutdown/po/fr/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/it/shutdown.po b/luci-app-shutdown/po/it/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/oc/shutdown.po b/luci-app-shutdown/po/oc/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/pl/shutdown.po b/luci-app-shutdown/po/pl/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/ru/shutdown.po b/luci-app-shutdown/po/ru/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/templates/shutdown.pot b/luci-app-shutdown/po/templates/shutdown.pot old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/po/zh_Hans/shutdown.po b/luci-app-shutdown/po/zh_Hans/shutdown.po old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/root/usr/share/luci/menu.d/luci-app-shutdown.json b/luci-app-shutdown/root/usr/share/luci/menu.d/luci-app-shutdown.json old mode 100644 new mode 100755 diff --git a/luci-app-shutdown/root/usr/share/rpcd/acl.d/luci-app-shutdown.json b/luci-app-shutdown/root/usr/share/rpcd/acl.d/luci-app-shutdown.json old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/Makefile b/luci-app-snmpd/Makefile old mode 100644 new mode 100755 index 3cd753a5f..12f22abd3 --- a/luci-app-snmpd/Makefile +++ b/luci-app-snmpd/Makefile @@ -1,11 +1,15 @@ +# +# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) +# +# + include $(TOPDIR)/rules.mk -LUCI_TITLE:= Net-SNMP LuCI interface -LUCI_DEPENDS:=+luci-base +snmpd -LUCI_PKGARCH:=all -LUCI_DESCRIPTION:=Some common net-snmp config items. In no way is this comprehensive. -PKG_MAINTAINER:= Karl Palsson -PKG_LICENSE:=Apache-2.0 +LUCI_TITLE:=LuCI SNMPD Interface +LUCI_DEPENDS:=+snmpd +snmptrapd +snmp-utils +snmp-mibs + +PKG_LICENSE:=GPLv3 + +#include ../luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk - # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js b/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js deleted file mode 100644 index b9e5e2853..000000000 --- a/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX: Apache-2.0 -// Karl Palsson 2021 -'use strict'; -'require form'; -'require ui'; -'require view'; - -var desc = _("" - + "SNMPD is a master daemon/agent for SNMP, from the " - + "net-snmp project. " - + "Note, OpenWrt has mostly complete UCI support for snmpd, but this LuCI applet " - + "only covers a few of those options. In particular, there is very little/no validation " - + "or help. See /etc/config/snmpd for manual configuration." -); - -return view.extend({ - render: function() { - var m, s, o; - - m = new form.Map("snmpd", _("net-snmp's SNMPD"), desc); - - s = m.section(form.TypedSection, "agent", _("Agent settings")); - s.anonymous = true; - o = s.option(form.Value, "agentaddress", _("The address the agent should listen on"), - _("Eg: UDP:161, or UDP:10.5.4.3:161 to only listen on a given interface")); - - s = m.section(form.TypedSection, "agentx", _("AgentX settings"), - _("Delete this section to disable AgentX")); - s.anonymous = true; - o = s.option(form.Value, "agentxsocket", _("The address the agent should allow AgentX connections to"), - _("This is only necessary if you have subagents using the agentX " - + "socket protocol. Eg: /var/run/agentx.sock")); - s.addremove = true; - - s = m.section(form.TypedSection, "com2sec", _("com2sec security")); - o = s.option(form.Value, "secname", "secname"); - o = s.option(form.Value, "source", "source"); - o = s.option(form.Value, "community", "community"); - - s = m.section(form.TypedSection, "group", "group", _("Groups help define access methods")); - s.addremove = true; - s.option(form.Value, "group", "group"); - s.option(form.Value, "version", "version"); - s.option(form.Value, "secname", "secname"); - - s = m.section(form.TypedSection, "access", "access"); - s.option(form.Value, "group", "group"); - s.option(form.Value, "context", "context"); - s.option(form.Value, "version", "version"); - s.option(form.Value, "level", "level"); - s.option(form.Value, "prefix", "prefix"); - s.option(form.Value, "read", "read"); - s.option(form.Value, "write", "write"); - s.option(form.Value, "notify", "notify"); - - s = m.section(form.TypedSection, "system", _("System"), _("Values used in the MIB2 System tree")); - s.anonymous = true; - s.option(form.Value, "sysLocation", "sysLocation"); - s.option(form.Value, "sysContact", "sysContact"); - s.option(form.Value, "sysName", "sysName"); - - return m.render(); - } -}); diff --git a/luci-app-snmpd/luasrc/controller/snmpd.lua b/luci-app-snmpd/luasrc/controller/snmpd.lua old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/luasrc/model/cbi/snmpd.lua b/luci-app-snmpd/luasrc/model/cbi/snmpd.lua old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/luasrc/view/snmpd.htm b/luci-app-snmpd/luasrc/view/snmpd.htm old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/po/de/snmpd.po b/luci-app-snmpd/po/de/snmpd.po old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/po/fr/snmpd.po b/luci-app-snmpd/po/fr/snmpd.po old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/po/it/snmpd.po b/luci-app-snmpd/po/it/snmpd.po old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/po/oc/snmpd.po b/luci-app-snmpd/po/oc/snmpd.po old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/po/templates/snmpd.pot b/luci-app-snmpd/po/templates/snmpd.pot old mode 100644 new mode 100755 index 5eb995f6b..9acfaf5cb --- a/luci-app-snmpd/po/templates/snmpd.pot +++ b/luci-app-snmpd/po/templates/snmpd.pot @@ -1,69 +1,175 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:22 -msgid "Agent settings" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:82 +msgid "Access" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:27 -msgid "AgentX settings" +#: luci-app-snmpd/luasrc/view/snmpd.htm:81 +#: luci-app-snmpd/luasrc/view/snmpd.htm:122 +msgid "Add" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:28 -msgid "Delete this section to disable AgentX" +#: luci-app-snmpd/luasrc/view/snmpd.htm:66 +#: luci-app-snmpd/luasrc/view/snmpd.htm:116 +msgid "All" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:25 -msgid "Eg: UDP:161, or UDP:10.5.4.3:161 to only listen on a given interface" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:139 +msgid "Arguments" msgstr "" -#: applications/luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json:3 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:42 +msgid "Community" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:23 +msgid "Contact" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:97 +msgid "Context" +msgstr "" + +#: luci-app-snmpd/luasrc/view/snmpd.htm:54 +msgid "Domain, IP or network" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:9 +#: luci-app-snmpd/luasrc/view/snmpd.htm:24 +msgid "Enabled" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:132 +msgid "Exec" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:6 +#: luci-app-snmpd/luasrc/view/snmpd.htm:21 +#: luci-app-snmpd/luasrc/view/snmpd.htm:48 +msgid "General" +msgstr "" + +#: luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json:3 msgid "Grant UCI access for luci-app-snmpd" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:40 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:63 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:72 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:86 +msgid "Group" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:63 msgid "Groups help define access methods" msgstr "" -#: applications/luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json:3 -msgid "SNMPD" +#: luci-app-snmpd/luasrc/view/snmpd.htm:64 +#: luci-app-snmpd/luasrc/view/snmpd.htm:114 +msgid "Interface" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:8 -msgid "" -"SNMPD is a master daemon/agent for SNMP, from the net-snmp project. Note, OpenWrt has mostly complete UCI " -"support for snmpd, but this LuCI applet only covers a few of those options. " -"In particular, there is very little/no validation or help. See /etc/config/" -"snmpd for manual configuration." +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:101 +msgid "Level" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:56 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:22 +msgid "Location" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:24 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:137 +msgid "Name" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:12 +msgid "Networks" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:116 +msgid "Notify" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:136 +msgid "ObjectID" +msgstr "" + +#: luci-app-snmpd/luasrc/view/snmpd.htm:55 +#: luci-app-snmpd/luasrc/view/snmpd.htm:90 +msgid "Output interface" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:138 +msgid "Program" +msgstr "" + +#: luci-app-snmpd/luasrc/view/snmpd.htm:85 +#: luci-app-snmpd/luasrc/view/snmpd.htm:89 +msgid "Protocols" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:106 +msgid "Read" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:34 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:69 +msgid "Read-only" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:35 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:70 +msgid "Read-write" +msgstr "" + +#: luci-app-snmpd/luasrc/controller/snmpd.lua:6 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:4 +#: luci-app-snmpd/luasrc/view/snmpd.htm:19 +#: luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json:3 +msgid "SNMPd" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:4 +msgid "SNMPd settings interface (Beta)" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:32 +msgid "Server" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:37 +msgid "Source" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:19 msgid "System" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:30 -msgid "The address the agent should allow AgentX connections to" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:111 +msgid "Write" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:24 -msgid "The address the agent should listen on" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:92 +msgid "any" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:31 -msgid "" -"This is only necessary if you have subagents using the agentX socket " -"protocol. Eg: /var/run/agentx.sock" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:104 +msgid "auth" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:56 -msgid "Values used in the MIB2 System tree" -msgstr "" - -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:35 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:29 msgid "com2sec security" msgstr "" -#: applications/luci-app-snmpd/htdocs/luci-static/resources/view/snmpd/snmpd.js:20 -msgid "net-snmp's SNMPD" +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:103 +msgid "noauth" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:67 +msgid "secname" +msgstr "" + +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:76 +#: luci-app-snmpd/luasrc/model/cbi/snmpd.lua:90 +msgid "version" msgstr "" diff --git a/luci-app-snmpd/po/zh_Hans/snmpd.po b/luci-app-snmpd/po/zh_Hans/snmpd.po old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/root/etc/config/snmpd b/luci-app-snmpd/root/etc/config/snmpd old mode 100644 new mode 100755 diff --git a/luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json b/luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json old mode 100644 new mode 100755 index 85850a218..771c4021a --- a/luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json +++ b/luci-app-snmpd/root/usr/share/luci/menu.d/luci-app-snmpd.json @@ -1,13 +1,13 @@ { - "admin/services/snmpd": { - "title": "SNMPD", + "admin/network/snmpd": { + "title": "SNMPd", + "order": 91, "action": { - "type": "view", - "path": "snmpd/snmpd" + "type": "cbi", + "path": "snmpd" }, "depends": { - "acl": [ "luci-app-snmpd" ], - "uci": { "snmpd": true } + "acl": [ "luci-app-snmpd" ] } } } diff --git a/luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json b/luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json old mode 100644 new mode 100755 index 566e52139..1fc168524 --- a/luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json +++ b/luci-app-snmpd/root/usr/share/rpcd/acl.d/luci-app-snmpd.json @@ -1,11 +1,11 @@ { - "luci-app-snmpd": { - "description": "Grant UCI access for luci-app-snmpd", - "read": { - "uci": [ "snmpd" ] - }, - "write": { - "uci": [ "snmpd" ] - } + "luci-app-snmpd": { + "description": "Grant UCI access for luci-app-snmpd", + "read": { + "uci": [ "snmpd" ] + }, + "write": { + "uci": [ "snmpd" ] } -} + } +} \ No newline at end of file diff --git a/luci-app-sqm-autorate/Makefile b/luci-app-sqm-autorate/Makefile new file mode 100755 index 000000000..51c3b4497 --- /dev/null +++ b/luci-app-sqm-autorate/Makefile @@ -0,0 +1,16 @@ +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Support for SQM Scripts with autorate +LUCI_DESCRIPTION:=Luci interface for the SQM scripts queue management package with SQM autorate + +PKG_MAINTAINER:=Toke Høiland-Jørgensen + +LUCI_DEPENDS:=+sqm-scripts +bash +tsping +LUCI_PKGARCH:=all + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js new file mode 100755 index 000000000..c367e660c --- /dev/null +++ b/luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js @@ -0,0 +1,298 @@ +'use strict'; +'require fs'; +'require ui'; +'require rpc'; +'require uci'; +'require view'; +'require form'; +'require tools.widgets as widgets'; + +return view.extend({ + handleGetHelpText: function(script_name, tbl) { + return fs.read("/usr/lib/sqm/" + script_name + ".help").then(function (text) { + if (text) + return [script_name, text]; + }); + }, + + handleEnableSQM: rpc.declare({ + object: 'luci', + method: 'setInitAction', + params: [ 'sqm', 'enable' ], + expect: { result: false } + }), + + load: function() { + return Promise.all([ + L.resolveDefault(fs.list('/var/run/sqm/available_qdiscs'), []), + L.resolveDefault(fs.list('/usr/lib/sqm'), []).then(L.bind(function(scripts) { + var tasks = [], scriptHelpTbl = {}; + + for (var i = 0; i < scripts.length; i++) + if (scripts[i].name.search(/\.qos$/) != -1) + tasks.push(L.resolveDefault(this.handleGetHelpText(scripts[i].name, scriptHelpTbl), [scripts[i].name, null])); + + return Promise.all(tasks); + }, this)), + uci.load('sqm') + ]); + }, + + render: function(data) { + var qdiscs = data[0], + scripts = data[1]; + + if (qdiscs.length === 0) { + ui.addNotification(null, + E('div', { 'class': 'left' }, [ + E('p', _("The SQM service seems to be disabled. Please use the button below to activate this service.")), + E('button', { + 'class': 'btn cbi-button-active', + 'click': ui.createHandlerFn(this, function() { + return fs.exec('/etc/init.d/sqm', ['enable']).then(function() { + return fs.exec('/etc/init.d/sqm', ['start']); + }).then(function() { + location.reload(); + }); + }) + }, _('Enable SQM')) + ])); + } + + var m, s, o; + + m = new form.Map('sqm', _('Smart Queue Management')); + m.description = _("With SQM you " + + "can enable traffic shaping, better mixing (Fair Queueing)," + + " active queue length management (AQM) " + + " and prioritisation on one " + + "network interface."); + + s = m.section(form.TypedSection, 'queue', _('Queues')); + s.tab("tab_basic", _("Basic Settings")); + s.tab("tab_qdisc", _("Queue Discipline")); + s.tab("tab_linklayer", _("Link Layer Adaptation")); + s.tab("tab_autorate", _("Autorate settings")); + s.anonymous = true; + s.addremove = true; + + o = s.taboption("tab_basic", form.Flag, "enabled", _("Enable this SQM instance.")); + o.rmempty = false; + o.write = L.bind(function(section, value) { + if (value == "1") { + this.handleEnableSQM(); + ui.addNotification(null, E('p', _("The SQM GUI has just enabled the sqm initscript on your behalf. Remember to disable the sqm initscript manually under System Startup menu in case this change was not wished for."))); + } + + return uci.set("sqm", section, "enabled", value); + }, this); + + o = s.taboption("tab_basic", form.Flag, "autorate", _("Enable SQM autorate")); + o.rmempty = false; + + o = s.taboption("tab_basic", widgets.DeviceSelect, "interface", _("Interface name")); + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "download", _("Base download speed (kbit/s) (ingress):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "min_download", _("Minimum download speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "max_download", _("Maximum download speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "upload", _("Base upload speed (kbit/s) (egress):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + + o = s.taboption("tab_basic", form.Value, "min_upload", _("Minimum upload speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Value, "max_upload", _("Maximum upload speed (kbit/s):")); + o.datatype = "and(uinteger,min(0))"; + o.rmempty = false; + o.depends("autorate","1"); + + o = s.taboption("tab_basic", form.Flag, "debug_logging", _("Create log file for this SQM instance under /var/run/sqm/${Interface_name}.[start|stop]-sqm.log.")); + o.rmempty = false; + + o = s.taboption("tab_basic", form.ListValue, "verbosity", _("Verbosity of SQM's output into the system log.")); + o.value("0", "silent"); + o.value("1", "error"); + o.value("2", "warning"); + o.value("5", "info ("+_("default")+")"); + o.value("8", "debug"); + o.value("10", "trace"); + o.default = "5"; + + o = s.taboption("tab_qdisc", form.ListValue, "qdisc", _("Queuing disciplines useable on this system. After installing a new qdisc, you need to restart the router to see updates!"),_("Must be set to cake if autorate is used.")); + for (var i=0; i < qdiscs.length; i++) { + o.value(qdiscs[i].name); + } + o.default = "cake"; + o.rmempty = false; + + var qos_desc = ""; + o = s.taboption("tab_qdisc", form.ListValue, "script", _("Queue setup script")); + for (i = 0; i < scripts.length; i++) { + o.value(scripts[i][0]); + qos_desc += "

" + scripts[i][0] + ":
"; + if (scripts[i][1]) + qos_desc += scripts[i][1] + "

"; + else + qos_desc += "No help text

"; + } + o.default = "piece_of_cake.qos"; + o.rmempty = false; + o.description = qos_desc; + + o = s.taboption("tab_qdisc", form.Flag, "qdisc_advanced", _("Show and Use Advanced Configuration. Advanced options will only be used as long as this box is checked.")); + o.default = false; + + o = s.taboption("tab_qdisc", form.ListValue, "squash_dscp", _("Squash DSCP on inbound packets (ingress):")); + o.value("1", "SQUASH"); + o.value("0", "DO NOT SQUASH"); + o.default = "1"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "squash_ingress", _("Ignore DSCP on ingress:")); + o.value("1", "Ignore"); + o.value("0", "Allow"); + o.default = "1"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "ingress_ecn", _("Explicit congestion notification (ECN) status on inbound packets (ingress):")); + o.value("ECN", "ECN (" + _("default") + ")"); + o.value("NOECN"); + o.default = "ECN"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.ListValue, "egress_ecn", _("Explicit congestion notification (ECN) status on outbound packets (egress).")); + o.value("NOECN", "NOECN (" + _("default") + ")"); + o.value("ECN"); + o.default = "NOECN"; + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Flag, "qdisc_really_really_advanced", _("Show and Use Dangerous Configuration. Dangerous options will only be used as long as this box is checked.")); + o.default = false + o.depends("qdisc_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "ilimit", _("Hard limit on ingress queues; leave empty for default.")); + o.datatype = "and(uinteger,min(0))"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "elimit", _("Hard limit on egress queues; leave empty for default.")); + o.datatype = "and(uinteger,min(0))"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "itarget", _("Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for automatic selection, put in the word default for the qdisc's default.")); + o.datatype = "string"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "etarget", _("Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for automatic selection, put in the word default for the qdisc's default.")); + o.datatype = "string"; + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "iqdisc_opts", _("Advanced option string to pass to the ingress queueing disciplines; no error checking, use very carefully.")); + o.depends("qdisc_really_really_advanced", "1"); + + o = s.taboption("tab_qdisc", form.Value, "eqdisc_opts", _("Advanced option string to pass to the egress queueing disciplines; no error checking, use very carefully.")); + o.depends("qdisc_really_really_advanced", "1"); + + // LINKLAYER + o = s.taboption("tab_linklayer", form.ListValue, "linklayer", _("Which link layer to account for:")); + o.value("none", "none (" + _("default") + ")"); + o.value("ethernet", "Ethernet with overhead: select for e.g. VDSL2."); + o.value("atm", "ATM: select for e.g. ADSL1, ADSL2, ADSL2+."); + o.default = "none"; + + o = s.taboption("tab_linklayer", form.Value, "overhead", _("Per Packet Overhead (byte):")); + o.datatype = "and(integer,min(-1500))"; + o.default = 0 + o.depends("linklayer", "ethernet"); + o.depends("linklayer", "atm"); + + o = s.taboption("tab_linklayer", form.Flag, "linklayer_advanced", _("Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced options will only be used as long as this box is checked.")); + o.depends("linklayer", "ethernet"); + o.depends("linklayer", "atm"); + + o = s.taboption("tab_linklayer", form.Value, "tcMTU", _("Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= interface MTU + overhead:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 2047 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.Value, "tcTSIZE", _("Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU + 1) / 16:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 128 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.Value, "tcMPU", _("Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:")); + o.datatype = "and(uinteger,min(0))"; + o.default = 0 + o.depends("linklayer_advanced", "1"); + + o = s.taboption("tab_linklayer", form.ListValue, "linklayer_adaptation_mechanism", _("Which linklayer adaptation mechanism to use; for testing only")); + o.value("default", "default (" + _("default") + ")"); + o.value("cake"); + o.value("htb_private"); + o.value("tc_stab"); + o.default = "default"; + o.depends("linklayer_advanced", "1"); + + // Autorate + o = s.taboption("tab_autorate", form.Flag, "output_processing_stats", _("Output monitoring lines showing processing stats")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "output_cake_changes", _("Output monitoring lines showing cake bandwidth changes")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "debug", _("Debug")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "sss_compensation", _("Starlink support")); + o.default = false; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "reflector_ping_interval_s", _("Reflector ping interval in seconds:")); + o.default = "0.2"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "no_pingers", _("Pingers numbers:")); + o.default = "4"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "delay_thr_ms",_("delay threshold in ms:")); + o.default = "25"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Flag, "enable_sleep_function", _("Sleep functionnality")); + o.default = true; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "connection_active_thr_kbps",_("Threshold in Kbit/s below which dl/ul is considered idle")); + o.default = "500"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "substained_idle_sleep_thr_s",_("Time threshold to put pingers to sleep on substained dl/ul achieved rate < idle_threshold")); + o.default = "60"; + o.depends("autorate","1"); + + o = s.taboption("tab_autorate", form.Value, "startup_wait_s",_("Number of seconds to wait on startup:")); + o.default = "60"; + o.depends("autorate","1"); + + + return m.render(); + } +}) diff --git a/luci-app-sqm-autorate/po/ar/sqm.po b/luci-app-sqm-autorate/po/ar/sqm.po new file mode 100755 index 000000000..48447fae9 --- /dev/null +++ b/luci-app-sqm-autorate/po/ar/sqm.po @@ -0,0 +1,211 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-07 14:36+0000\n" +"Last-Translator: Said Zakaria \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" +"X-Generator: Weblate 4.5.1\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"سلسلة خيارات متقدمة لتمريرها إلى تخصصات الخروج قائمة انتظار; لا يوجد خطأ " +"التحقق، واستخدام بعناية فائقة." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "الإعدادات الأساسية" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "اسم الواجهة" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/bg/sqm.po b/luci-app-sqm-autorate/po/bg/sqm.po new file mode 100755 index 000000000..4763b4aa3 --- /dev/null +++ b/luci-app-sqm-autorate/po/bg/sqm.po @@ -0,0 +1,219 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-09-27 22:36+0000\n" +"Last-Translator: Iskren Mihaylov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Основни настройки" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Създаване на журнален файл за тази инстанция на SQM под /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +#, fuzzy +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Скорост на изтегляне (kbit/s) (входящ) зададена на 0, деактивира оформянето " +"на входящия трафик:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Активиране на SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Активиране на тази SQM инстанция." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Предоставяне на достъп на UCI за luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Твърд лимит на изходните опашки; оставете празно по подразбиране." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Твърд лимит на входящите опашки; оставете празно по подразбиране." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Игнориране на DSCP за входящ:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Име на интерфейса" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Целева латентност за изходящ трафик, напр. 5ms [единици: s, ms или us]; " +"оставете празно за автоматичен избор, поставете думата default за използване " +"стойности по подразбиране на qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Целева латентност за входящ трафик, например 5ms [единици: s, ms или us]; " +"оставете празно за автоматичен избор, поставете думата default за стойности " +"по подразбиране на qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/bn_BD/sqm.po b/luci-app-sqm-autorate/po/bn_BD/sqm.po new file mode 100755 index 000000000..81e5f56c2 --- /dev/null +++ b/luci-app-sqm-autorate/po/bn_BD/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-10 19:29+0000\n" +"Last-Translator: Debashish Das \n" +"Language-Team: Bengali (Bangladesh) \n" +"Language: bn_BD\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "সাধারন সেটিংস" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/ca/sqm.po b/luci-app-sqm-autorate/po/ca/sqm.po new file mode 100755 index 000000000..bab2a9f42 --- /dev/null +++ b/luci-app-sqm-autorate/po/ca/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: ca\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/cs/sqm.po b/luci-app-sqm-autorate/po/cs/sqm.po new file mode 100755 index 000000000..53293384b --- /dev/null +++ b/luci-app-sqm-autorate/po/cs/sqm.po @@ -0,0 +1,210 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-07 11:32+0000\n" +"Last-Translator: Adam Salač \n" +"Language-Team: Czech \n" +"Language: cs\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Řetězec rozšířených možností pro předání do frontových disciplín; bez " +"kontroly chyb, používejte s opatrností." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Základní nastavení" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/da/sqm.po b/luci-app-sqm-autorate/po/da/sqm.po new file mode 100755 index 000000000..66b4f784a --- /dev/null +++ b/luci-app-sqm-autorate/po/da/sqm.po @@ -0,0 +1,248 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-11-11 19:12+0000\n" +"Last-Translator: drax red \n" +"Language-Team: Danish \n" +"Language: da\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avanceret indstillingsstreng, der skal sendes til egress-kø-disciplinerne; " +"ingen fejlkontrol, brug den med stor forsigtighed." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avanceret indstillingsstreng, der skal overføres til de indgående " +"kø-discipliner; ingen fejlkontrol, brug den med stor forsigtighed." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundlæggende indstillinger" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Opret logfil for denne SQM-instans under /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Downloadhastighed (kbit/s) (ingress) indstilles til 0 for selektivt at " +"deaktivere indgangsformning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Aktiver SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Aktiver denne SQM-instans." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"ECN-status (Explicit congestion notification) for indgående pakker (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"ECN-status (Explicit congestion notification) på udgående pakker (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Giv UCI-adgang til luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Hård grænse for egress køer; lad den være tom som standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Hård grænse for ingress køer; lad den være tom som standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignorer DSCP ved ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Interface navn" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latency-mål for egress, f.eks. 5ms [enheder: s, ms eller os]; lad det være " +"tomt for automatisk valg, indsæt ordet standard for qdisc'ens standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latency-mål for ingress, f.eks. 5ms [enheder: s, ms eller os]; lad det være " +"tomt for automatisk valg, indsæt ordet standard for qdisc'ens standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Tilpasning af linklag" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maksimal størrelse til beregning af størrelse og hastighed, tcMTU (byte); " +"skal være >= MTU for grænsefladen + overhead:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimal pakkestørrelse, MPU (byte); skal være > 0 for ethernet-" +"størrelsestabeller:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Antal poster i størrelses-/taksttabeller, TSIZE; for ATM skal du vælge TSIZE " +"= (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead pr. pakke (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Kø Disciplin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Køopsætningsscript" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Køer" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Kø-discipliner, der kan bruges på dette system. Når du har installeret en ny " +"qdisc, skal du genstarte routeren for at se opdateringer!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Vis avancerede linklagsindstillinger (kun nødvendige, hvis MTU > 1500). " +"Avancerede indstillinger bruges kun, så længe dette afkrydsningsfelt er " +"markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Vis og brug avanceret konfiguration. Avancerede indstillinger vil kun blive " +"brugt, så længe dette felt er markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Vis og brug farlig konfiguration. Farlige indstillinger anvendes kun, så " +"længe dette felt er markeret." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Smart køstyring" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP på indgående pakker (indgang):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI har netop aktiveret sqm initscript på dine vegne. Husk at deaktivere " +"sqm initscript manuelt under System Startup menuen, hvis denne ændring ikke " +"var ønsket." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"SQM-tjenesten ser ud til at være deaktiveret. Brug venligst knappen nedenfor " +"for at aktivere denne tjeneste." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Uploadhastighed (kbit/s) (egress) sat til 0 for selektivt at deaktivere " +"udgående formning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosity af SQM's output i systemloggen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Hvilket forbindelseslag der skal tages hensyn til:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Hvilken forbindelseslag tilpasningsmekanisme der skal bruges; kun til test" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Med SQM kan du aktivere " +"trafikformning, bedre blanding (Fair Queueing), aktiv kølængdestyring (AQM) " +"og prioritering på én netværksgrænseflade." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Standard" diff --git a/luci-app-sqm-autorate/po/de/sqm.po b/luci-app-sqm-autorate/po/de/sqm.po new file mode 100755 index 000000000..e3cadb151 --- /dev/null +++ b/luci-app-sqm-autorate/po/de/sqm.po @@ -0,0 +1,255 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-26 22:07+0000\n" +"Last-Translator: ssantos \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Erweiterte Optionszeichenkette zur Übergabe an die ausgangsseitigen " +"Warteschlangendisziplinen; keine Fehlerprüfung, sehr vorsichtig verwenden." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Erweiterte Optionszeichenkette zur Übergabe an die in die Warteschlange " +"einsteigenden Disziplinen; keine Fehlerprüfung, sehr vorsichtig verwenden." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundlegende Einstellungen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Logdatei für diese SQM-Instanz unter /var/run/sqm/${Interface_name}.[start|" +"stop]-sqm.log erstellen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Download-Geschwindigkeit (kbit/s) (Ingress) auf 0 setzen, um Ingress-Shaping " +"selektiv zu deaktivieren:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM aktivieren" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Diese SQM-Instanz aktivieren" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Explicit congestion notification (ECN) Status für eingehende Pakete " +"(ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Explicit congestion notification (ECN) Status für ausgehende Pakete (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "UCI-Zugriff für luci-app-sqm erlauben" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Harte Begrenzung der Ausgangswarteschlangen; Standardmäßig leer lassen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Harte Begrenzung der Eingangswarteschlangen; Standardmäßig leer lassen." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "DSCP bei Paketeingang ignorieren:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Schnittstellenname" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latenzziel für Ausgangswarteschlange, z.B. 5ms [Einheit: s, ms oder us]; " +"Leer lassen für automatische Auswahl, das Wort 'default' eintragen für qdisc " +"Standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Latenzziel für Eingangswarteschlange, z.B. 5ms [Einheit: s, ms oder us]; " +"Leer lassen für automatische Auswahl, das Wort 'default' eintragen für qdisc " +"Standard." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Anpassung der Verbindungsschicht" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maximale Größe für Größen- und Ratenberechnungen, tcMTU (Byte); muss >= " +"Schnittstellen-MTU + Overhead sein:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimale Paketgröße, MPU (Byte); muss > 0 für Ethernet-Größentabellen sein:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Anzahl der Einträge in Größen/Raten-Tabellen, TSIZE; für ATM wählen Sie " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead pro Paket (Byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +#, fuzzy +msgid "Queue Discipline" +msgstr "Queue Discipline" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Skript zum Aufsetzen der Warteschlange" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Warteschlangen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Warteschlangenstrukturen die auf diesem System benutzbar sind. Der Router " +"muss nach der Installation einer neuen qdisc neu gestartet werden, um die " +"Änderungen sehen zu können." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Erweiterte Verbindungsschicht-Optionen anzeigen, (nur erforderlich, wenn MTU " +"> 1500). Die erweiterten Optionen werden nur verwendet, solange dieses " +"Kästchen markiert ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Erweiterte Konfiguration anzeigen und verwenden. Die erweiterten Optionen " +"werden nur verwendet, wenn diese Option ausgewählt ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Gefährliche Einstellungen anzeigen und nutzen. Gefährliche Optionen werden " +"nur benutzt, solange diese Box ausgewählt ist." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Smart Queue Management" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +#, fuzzy +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP bei eingehenden Paketen (Ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"Die SQM-GUI hat soeben das sqm-Initskript in Ihrem Namen aktiviert. Denken " +"Sie daran, das sqm-Initscript manuell im Systemstartmenü zu deaktivieren, " +"falls diese Änderung nicht gewünscht wurde." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Der SQM-Dienst scheint deaktiviert zu sein. Bitte verwenden Sie die " +"Schaltfläche unten, um diesen Dienst zu aktivieren." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Upload-Geschwindigkeit (kbit/s) (egress) auf 0 setzen, um die egress " +"Paketflusskontrolle abzuschalten:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Festlegen, wie ausführlich SQM ins Systemlog schreiben soll" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Welche Verbindungsschicht zu berücksichtigen ist:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Welcher Verbindungsschicht-Anpassungsmechanismus verwendet werden soll; nur " +"zum Testen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Mit SQM können Sie Traffic " +"Shaping, besseres Mischen (Fair Queueing), aktives Queue Length Management " +"(AQM) und Priorisierung auf einer Netzwerkschnittstelle aktivieren." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Standardeinstellung" diff --git a/luci-app-sqm-autorate/po/el/sqm.po b/luci-app-sqm-autorate/po/el/sqm.po new file mode 100755 index 000000000..d165ea0d0 --- /dev/null +++ b/luci-app-sqm-autorate/po/el/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-06 14:38+0000\n" +"Last-Translator: Stefanos Batsios \n" +"Language-Team: Greek \n" +"Language: el\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Βασικές Ρυθμίσεις" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Χορήγηση δικαιώματος χρήσης του UCI από το luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Όνομα διεπαφής (Interface)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/en/sqm.po b/luci-app-sqm-autorate/po/en/sqm.po new file mode 100755 index 000000000..548b41e7d --- /dev/null +++ b/luci-app-sqm-autorate/po/en/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: en\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/es/sqm.po b/luci-app-sqm-autorate/po/es/sqm.po new file mode 100755 index 000000000..8ca3d0c57 --- /dev/null +++ b/luci-app-sqm-autorate/po/es/sqm.po @@ -0,0 +1,250 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-28 18:11+0000\n" +"Last-Translator: Franco Castillo \n" +"Language-Team: Spanish \n" +"Language: es\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadena de opciones avanzadas para pasar a las disciplinas de cola de salida; " +"sin verificación de errores, use con mucho cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadena de opciones avanzadas para pasar a las disciplinas de colas de " +"ingreso; sin verificación de errores, use con mucho cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configuración básica" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Cree un archivo de registro para esta instancia de SQM en /var/run/sqm/" +"${Interface_name}.[start|stopfont>-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"La velocidad de descarga (kbit/s) (ingreso) se establece en 0 para " +"desactivar selectivamente la configuración de ingreso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Activar SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activar esta instancia de SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Estado de notificación explícita de congestión (ECN) en paquetes entrantes " +"(ingreso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Estado explícito de notificación de congestión (ECN) en paquetes salientes " +"(salida)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceder acceso UCI para luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Límite estricto en las colas de salida; dejar en blanco por defecto." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Límite estricto en las colas de ingreso; dejar en blanco por defecto." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignorar DSCP en ingreso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nombre de interfaz" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Objetivo de latencia para la salida, p.e. 5ms [unidades: s, ms o us]; déjelo " +"en blanco para la selección automática, ingrese la palabra default para el " +"qdisc predeterminado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Objetivo de latencia para la entrada, p.e. 5 ms [unidades: s, ms o us]; " +"déjelo en blanco para la selección automática, ingrese la palabra default " +"para el qdisc predeterminado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptación de capa de enlace" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamaño máximo para cálculos de tamaño y velocidad, tcMTU (byte); necesita " +"ser >= interfaz MTU + gastos generales:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamaño de paquete mínimo, MPU (byte); debe ser > 0 para tablas de tamaño de " +"ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Número de entradas en tablas de tamaño/tasa, TSIZE; para ATM, elija TSIZE = " +"(tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Por paquete de arriba (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina de cola" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuración de cola" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Disciplinas de colas utilizables en este sistema. Después de instalar un " +"nuevo qdisc, ¡debe reiniciar el enrutador para ver las actualizaciones!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "Gestión inteligente de colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar opciones avanzadas de Linklayer (solo es necesario si MTU > 1500). " +"Las opciones avanzadas solo se utilizarán mientras esta casilla esté marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar y usar la Configuración avanzada. Las opciones avanzadas solo se " +"utilizarán mientras esta casilla esté marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar y usar la Configuración Peligrosa. Las opciones peligrosas sólo se " +"utilizarán mientras esté marcada esta casilla." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestión inteligente de colas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Aplastar DSCP en paquetes entrantes (ingreso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"La GUI de SQM acaba de activar el initscript de sqm en su nombre. Recuerde " +"desactivar el initscript de sqm manualmente en el menú Inicio del sistema en " +"caso de que no se desee este cambio." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"El servicio SQM parece estar desactivado. Utilice el botón de abajo para " +"activar este servicio." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidad de carga (kbit/s) (salida) establecida en 0 para desactivar " +"selectivamente la configuración de salida:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosidad de la salida de SQM en el registro del sistema." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Qué capa de enlace debe tener en cuenta:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Qué mecanismo de adaptación de capa de enlace usar; solo para pruebas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Con SQM puede activar la " +"conformación del tráfico, una mejor mezcla (Fair Queuing), gestión activa de " +"la longitud de la cola (AQM) y priorización en una interfaz de red." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "predeterminado" diff --git a/luci-app-sqm-autorate/po/fi/sqm.po b/luci-app-sqm-autorate/po/fi/sqm.po new file mode 100755 index 000000000..d37903f76 --- /dev/null +++ b/luci-app-sqm-autorate/po/fi/sqm.po @@ -0,0 +1,216 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-06-30 13:42+0000\n" +"Last-Translator: Petri Asikainen \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.2-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Perusasetukset" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Luo lokitiedosto tälle SQM-esiintymälle: /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Latausnopeus (kbit/s) (ingress). Aseta arvoksi 0 ottaaksesi latausnopeuden " +"säädön pois päältä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ota tämä SQM-esiintymä käyttöön." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Salli pääsy SQM-asetuksiin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Sivuuta DSCP saapuvalta liikenteeltä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Sovittimen nimi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Linkkikerroksen sopeuttaminen" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Lisäkuorma pakettia kohti (tavu):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Jonomenetelmä (qdisc)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Jonomenetelmän asetustiedosto" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Jonot" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Käytettävissä olevat jonomenetelmät (qdisc). Uuden qdiscin asentamisen " +"jälkeen tiedot päivittyvät laitteen uudelleenkäynnistyksen yhteydessä." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Älykäs jononhallinta" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Lähetysnopeus kilobitteinä sekunnissa (kbit/s). Aseta arvoksi 0 ottaaksesi " +"lähetysnopeuden säädön pois päältä:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM tapahtumien lokiinkirjaamisen tarkkuus." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Mitä linkkerroksen sopeutumistapaa käytetään (vain testaamiseen)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "vakio" diff --git a/luci-app-sqm-autorate/po/fr/sqm.po b/luci-app-sqm-autorate/po/fr/sqm.po new file mode 100755 index 000000000..91b243562 --- /dev/null +++ b/luci-app-sqm-autorate/po/fr/sqm.po @@ -0,0 +1,247 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-08-10 18:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.10.1\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Chaîne d'options avancées pour passer aux disciplines de file d'attente de " +"sortie ; pas de vérification d'erreur, à utiliser avec précaution." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Chaîne d'options avancées à passer aux disciplines de file d'attente " +"d'entrée ; pas de vérification d'erreur, à utiliser avec beaucoup de " +"précaution." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Paramètres de base" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Créer un fichier journal pour cette instance SQM sous /var/run/sqm/" +"${nom_interface}. [start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Vitesse de téléchargement (kbit/s) (ingress) réglée sur 0 pour désactiver " +"sélectivement la mise en forme de l'ingress :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Active SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activez cette instance SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Statut de notification de congestion (ECN) sur les paquets entrants " +"(ingress) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Statut de notification de congestion (ECN) sur les paquets sortant (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Autoriser l'accès UCI pour luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Limite des files d'attente pour la sortie ; laisser vide par défaut." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Limite des files d'attente entrée ; laisser vide par défaut." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoré DSCP à l'entrée :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nom de l’interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cible de latence pour la sortie, par exemple 5ms [unités : s, ms ou us] ; " +"laisser vide pour la sélection automatique, mettre Default pour la valeur " +"par défaut du qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cible de latence d'entrée, par exemple 5ms [unités : s, ms ou us] ; laisser " +"vide pour la sélection automatique, mettre default pour la valeur par défaut " +"du qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptation de liaison" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Taille maximale pour les calculs de taille et de taux, tcMTU (byte) ; doit " +"être >= interface MTU + overhead :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Taille minimale des paquets, MPU (byte) ; doit être > 0 pour les tailes de " +"tables ethernet :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Nombre d'entrées de taille/debit tables, TSIZE ; for ATM choose TSIZE = " +"(tcMTU + 1) / 16 :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Overhead par Packet(byte) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Queue Discipline" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de file d'attente" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Queues" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Les disciplines de file d'attente sur ce système. Après avoir installé un " +"nouveau qdisc, vous devez redémarrer le routeur pour voir les mises à jour !" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Afficher les options avancées du Linklayer, (uniquement nécessaire si MTU > " +"1500). Les options avancées ne seront utilisées que si cette case est cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Afficher et utiliser la configuration avancée. Les options avancées ne " +"seront utilisées que tant que cette case sera cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Afficher et utiliser une configuration dangereuse. Les options dangereuses " +"ne seront utilisées que si cette case est cochée." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Management File d'attente" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Écraser le DSCP sur les paquets entrants (ingress) :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"L'interface graphique SQM vient d'activer l'initscript sqm en votre nom. " +"N'oubliez pas de désactiver manuellement le sqm initscript dans le menu de " +"démarrage du système au cas où ce changement ne serait pas souhaité." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "Vitesse de chargement (kbit/s) (sortie) Mettre sur 0 pour désactiver :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosité de la sortie de SQM dans le journal du système." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Quelle couche liaison à prendre en compte :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Mécanisme d'adaptation de la couche de liaison ; pour essai uniquement" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Avec SQM vous pouvez permettre " +"la régulation du trafic, un meilleur mélange (Fair Queueing), la gestion " +"active de la longueur des files d'attente (AQM) et la priorisation sur une " +"seule interface réseau." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Par défaut" diff --git a/luci-app-sqm-autorate/po/he/sqm.po b/luci-app-sqm-autorate/po/he/sqm.po new file mode 100755 index 000000000..587c49fcd --- /dev/null +++ b/luci-app-sqm-autorate/po/he/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: he\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/hi/sqm.po b/luci-app-sqm-autorate/po/hi/sqm.po new file mode 100755 index 000000000..111424659 --- /dev/null +++ b/luci-app-sqm-autorate/po/hi/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: hi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/hu/sqm.po b/luci-app-sqm-autorate/po/hu/sqm.po new file mode 100755 index 000000000..e4b96b811 --- /dev/null +++ b/luci-app-sqm-autorate/po/hu/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-16 16:38+0000\n" +"Last-Translator: Bence Csókás \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Alapszintű beállítások" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM engedélyezése" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Csatoló neve" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "alapértelmezett" diff --git a/luci-app-sqm-autorate/po/it/sqm.po b/luci-app-sqm-autorate/po/it/sqm.po new file mode 100755 index 000000000..3a867c3ad --- /dev/null +++ b/luci-app-sqm-autorate/po/it/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-09-09 08:44+0000\n" +"Last-Translator: pisquan8 \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome interfaccia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "predefinito" diff --git a/luci-app-sqm-autorate/po/ja/sqm.po b/luci-app-sqm-autorate/po/ja/sqm.po new file mode 100755 index 000000000..f7179b9dc --- /dev/null +++ b/luci-app-sqm-autorate/po/ja/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-10 19:29+0000\n" +"Last-Translator: Ryota <21ryotagamer@gmail.com>\n" +"Language-Team: Japanese \n" +"Language: ja\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本設定" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "この SQM インスタンスを有効にします。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "luci-app-sqmにUCIアクセスを許可" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "インターフェース名" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "キュー" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "スマート・キュー管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "デフォルト" diff --git a/luci-app-sqm-autorate/po/ko/sqm.po b/luci-app-sqm-autorate/po/ko/sqm.po new file mode 100755 index 000000000..8dbf6b6dd --- /dev/null +++ b/luci-app-sqm-autorate/po/ko/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-07 10:49+0000\n" +"Last-Translator: Sunggu Choi \n" +"Language-Team: Korean \n" +"Language: ko\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.7-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "기본 설정" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/mr/sqm.po b/luci-app-sqm-autorate/po/mr/sqm.po new file mode 100755 index 000000000..4c14d4090 --- /dev/null +++ b/luci-app-sqm-autorate/po/mr/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: mr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/ms/sqm.po b/luci-app-sqm-autorate/po/ms/sqm.po new file mode 100755 index 000000000..b1857d906 --- /dev/null +++ b/luci-app-sqm-autorate/po/ms/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: ms\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/nb_NO/sqm.po b/luci-app-sqm-autorate/po/nb_NO/sqm.po new file mode 100755 index 000000000..2c2441298 --- /dev/null +++ b/luci-app-sqm-autorate/po/nb_NO/sqm.po @@ -0,0 +1,202 @@ +msgid "" +msgstr "" +"Language: nb_NO\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/pl/sqm.po b/luci-app-sqm-autorate/po/pl/sqm.po new file mode 100755 index 000000000..63d080dce --- /dev/null +++ b/luci-app-sqm-autorate/po/pl/sqm.po @@ -0,0 +1,253 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-22 17:33+0000\n" +"Last-Translator: Matthaiks \n" +"Language-Team: Polish \n" +"Language: pl\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.7.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Zaawansowany łańcuch opcji, aby przejść do dyscyplin kolejkowania egress; " +"bez sprawdzania błędów, używaj bardzo ostrożnie." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Zaawansowany łańcuch opcji, aby przejść do dyscyplin kolejkowania ingress; " +"bez sprawdzania błędów, używaj bardzo ostrożnie." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Podstawowe ustawienia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Utwórz plik dziennika dla tej instancji SQM w /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Prędkość pobierania (kbit/s) (ingress) ustawiona na 0, aby selektywnie " +"wyłączyć kształtowanie ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Włącz SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Włącz tę instancję SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Status jawnego powiadomienia o przeciążeniu (ECN) na pakietach " +"przychodzących (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Status jawnego powiadomienia o przeciążeniu (ECN) na pakietach wychodzących " +"(egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Udziel dostępu UCI do luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Twardy limit kolejek egress; pozostawić puste dla ustawień domyślnych." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Twardy limit kolejek ingress; pozostawić puste dla ustawień domyślnych." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoruj DSCP przy ingress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nazwa interfejsu" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cel opóźnienia dla egress, np. 5ms [jednostki: s, ms lub us]; pozostaw puste " +"dla automatycznego wyboru, wpisz słowo default dla domyślnego qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Cel opóźnienia dla ingress, np. 5ms [jednostki: s, ms lub us]; pozostaw " +"puste dla automatycznego wyboru, wpisz słowo default dla domyślnego qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptacja warstwy połączenia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Maksymalny rozmiar do obliczeń wielkości i szybkości, tcMTU (bajt); musi " +"być> = interfejs MTU + narzut:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimalny rozmiar pakietu, MPU (bajt); musi wynosić> 0 dla tabel rozmiarów " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Liczba wpisów w tabelach wielkości/szybkości, TSIZE; dla ATM wybrać TSIZE = " +"(tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Narzut na pakiet (bajt):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Dyscyplina kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Skrypt konfiguracji kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Kolejki" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Dyscypliny kolejkowania przydatne w tym systemie. Po zainstalowaniu nowej " +"qdisc musisz ponownie uruchomić router, aby zobaczyć aktualizacje!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Pokaż zaawansowane opcje Linklayera (wymagane tylko, jeśli MTU>1500). Opcje " +"zaawansowane będą używane tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Pokaż i użyj konfiguracji zaawansowanej. Opcje zaawansowane będą używane " +"tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Pokaż i używaj niebezpiecznej konfiguracji. Niebezpieczne opcje będą używane " +"tylko tak długo, jak to pole jest zaznaczone." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Inteligentne zarządzanie kolejkami" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Squash DSCP na pakietach przychodzących (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI właśnie włączył w Twoim imieniu initscript sqm. Pamiętaj, aby " +"ręcznie wyłączyć skrypt initscript sqm w menu autostart, jeśli ta zmiana nie " +"była pożądana." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Usługa SQM wydaje się wyłączona. Proszę użyć przycisku poniżej, aby " +"aktywować tę usługę." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Prędkość wysyłania (kbit/s) (egress) ustawiona na 0, aby selektywnie " +"wyłączyć kształtowanie egress:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Szczegółowość danych wyjściowych SQM w dzienniku systemowym." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Którą warstwę łącza należy uwzględnić:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Którego mechanizmu dostosowania odtwarzacza linków należy użyć; tylko do " +"testowania" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Z SQM można włączyć " +"kształtowanie ruchu, lepsze mieszanie (Fair Queueing), aktywne zarządzanie " +"długością kolejki (AQM) i ustalanie priorytetów na jednym interfejsie " +"sieciowym." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "domyślna" diff --git a/luci-app-sqm-autorate/po/pt/sqm.po b/luci-app-sqm-autorate/po/pt/sqm.po new file mode 100755 index 000000000..ff2747104 --- /dev/null +++ b/luci-app-sqm-autorate/po/pt/sqm.po @@ -0,0 +1,256 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-04 20:24+0000\n" +"Last-Translator: ssantos \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançada para passar para as disciplinas de enfileiramento " +"de saída; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançada para passar para as disciplinas de enfileiramento " +"de entrada; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configurações Básicas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Criar ficheiro de log para esta instância de SQM em /var/run/sqm/" +"${Nome_da_Interface}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Velocidade de descarrega (kbit/s) (ingresso) configurada a 0 para desativar " +"seletivamente a forma de ingresso:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Ativar o SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ativar esta instância do SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Estado de notificação de congestionamento explícito (ECN) nos pacotes de " +"entrada (ingresso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Estado de notificação de congestionamento explícito (ECN) nos pacotes de " +"saída (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceder acesso UCI ao luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Limite rígido nas filas de espera de saída; deixe em branco para utilizar " +"valores predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limite rígido nas filas de espera de entrada; deixe em branco para utilizar " +"valores predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignore o DSCP na entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome da interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para saída, p.ex. 5ms [unidades: s, ms, ou us]; deixe vazio " +"para seleção automática, entre a palavra default para a predefinição do " +"qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para entrada, p.ex. 5ms [unidades: s, ms, ou us]; deixe " +"vazio para seleção automática, entre a palavra default para a predefinição " +"do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptação da Camada de Ligação" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamanho máximo para cálculos de tamanho e taxa, tcMTU (byte); deve ser >= " +"MTU da interface + sobrecarga:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamanho mínimo do pacote, MPU (byte); deve ser > 0 para tabelas de tamanho " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Quantidade de entradas nas tabelas de tamanho/taxa, TSIZE; para ATM escolha " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Sobrecarga por Pacote (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina de Fila de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuração da fila de espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Disciplinas de enfileiramento utilizáveis neste sistema. Depois de instalar " +"um novo qdisc, precisa reiniciar o roteador para ver as atualizações!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar Opções Avançadas da Camada de Ligações, (apenas necessário se MTU > " +"1500). As opções avançadas só serão usadas enquanto esta caixa estiver " +"marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Usar Configuração Avançada. As opções avançadas só serão usadas " +"enquanto esta caixa estiver marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Utilizar Configuração Perigosa. As opções perigosas só serão " +"usadas enquanto esta caixa estiver marcada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestão Inteligente de Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Esmagar DSCP em pacotes de entrada (ingresso):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"O GUI SQM acabou de ativar o initscript sqm em seu nome. Lembre-se de " +"desativar o initscript sqm manualmente no menu Início do Sistema no caso " +"desta alteração não ter sido desejada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"O serviço SQM parece estar desativado. Use o botão abaixo para ativar este " +"serviço." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidade de envio (kbit/s) (saída) definida como 0 para desativar " +"seletivamente a forma de saída:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbosidade da saída do SQM no log do sistema." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Que camada de ligação para a conta:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Utilizar qual mecanismo de adaptação da camada de ligação; apenas para testes" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Pode ativar a formação de tráfego com SQM, para melhor mistura (Fair Queueing), gestão ativa do " +"comprimento da fila de espera (AQM) e priorização numa interface de rede." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "padrão" diff --git a/luci-app-sqm-autorate/po/pt_BR/sqm.po b/luci-app-sqm-autorate/po/pt_BR/sqm.po new file mode 100755 index 000000000..ddcc9111b --- /dev/null +++ b/luci-app-sqm-autorate/po/pt_BR/sqm.po @@ -0,0 +1,258 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-22 17:33+0000\n" +"Last-Translator: Wellington Terumi Uemura \n" +"Language-Team: Portuguese (Brazil) \n" +"Language: pt_BR\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.7.1-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançadas passada para as disciplinas de enfileiramento de " +"saída; sem verificação de erros, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Cadeia de opções avançadas passada para as disciplinas de enfileiramento de " +"entrada; sem verificação de erro, use com muito cuidado." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Configurações Básicas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Criar um arquivo de registro log para esta instância SQM em /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Velocidade de Download (kbits/s) (entrada), defina como 0 para desativar " +"seletivamente a modelagem do tráfico de entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Ative o SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Ative esta instância do SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Status de notificação explicita de congestionamento (ECN) durante a entrada " +"de pacotes (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Status de notificação explicita de congestionamento (ECN) durante a saída de " +"pacotes (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Conceda acesso UCI ao luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Limite máximo nas filas de saída; deixe em branco para utilizar valores " +"predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limite máximo nas filas de entrada; deixe em branco para utilizar valores " +"predefinidos." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignore o DSCP na entrada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Nome da Interface" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para saída, por exemplo, 5ms [unidades: s, ms ou nós]; " +"deixe vazio para usar a seleção automática, coloque a palavra default para " +"utilizar os valores predefinidos do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Meta de latência para entrada, por exemplo, 5ms [unidades: s, ms ou nós]; " +"deixe vazio para usar a seleção automática, coloque a palavra default para " +"utilizar os valores predefinidos do qdisc." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptação da Camada do Link de Ligação" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Tamanho máximo para realizar os cálculos de tamanho e taxa, tcMTU (byte); " +"precisa ser >= interface MTU + sobrecarga:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Tamanho mínimo do pacote, MPU (byte); precisa ser > 0 para as tabelas de " +"tamanho ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Quantidade de entradas de tamanho/taxa nas tabelas, TSIZE; para o ATM, " +"escolha TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Por Sobrecarga de Pacote (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina da Fila" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configuração da fila" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Filas de espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"As disciplinas de enfileiramento utilizáveis neste sistema. Depois de " +"instalar um novo qdisc, você precisa reiniciar o roteador para ver as " +"atualizações!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Mostrar as Opções Avançadas da Camada do Link ( só é necessário caso MTU > " +"1500). As opções avançadas só serão usadas quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Exibir e Usar a Configuração Avançada. As opções avançadas só serão usadas " +"quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Mostrar e Usar as Configurações Perigosas. As opções perigosas só serão " +"usadas quando esta caixa for selecionada." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestão Inteligente das Filas de Espera" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Liquidar o DSCP durante a entrada dos pacotes (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"O GUI SQM acabou de ativar o initscript sqm em seu nome. Lembre-se de " +"desativar o initscript sqm manualmente no menu Inicio do Sistema caso esta " +"alteração não tenha sido requerida." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"O serviço SQM parece estar desativado. Use o botão abaixo para ativar este " +"serviço." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Velocidade de upload (kbit/s) (saída), defina como 0 para desativar " +"seletivamente a modelagem do tráfico de saída:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Prolixidade da saída do SQM's nos arquivos de registro log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Qual camada de link deve ser considerada:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Qual o mecanismo de adaptação de camadas do link para usar; para testes " +"apenas" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Com a SQM você " +"pode habilitar a modelagem de tráfego, ter uma melhor mistura (Fila Justa), " +"gerenciamento ativo de comprimento de fila (AQM) e priorização em uma " +"interface de rede." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Padrão" diff --git a/luci-app-sqm-autorate/po/ro/sqm.po b/luci-app-sqm-autorate/po/ro/sqm.po new file mode 100755 index 000000000..6b5dd6579 --- /dev/null +++ b/luci-app-sqm-autorate/po/ro/sqm.po @@ -0,0 +1,257 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-11-29 10:52+0000\n" +"Last-Translator: Simona Iacob \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" +"X-Generator: Weblate 4.10-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Șir de opțiuni avansate care trebuie transmise disciplinelor de coadă de " +"ieșire; nu se verifică erorile, se utilizează cu mare atenție." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Șir de opțiuni avansate care trebuie transmise disciplinelor de intrare în " +"coada de așteptare; fără verificare a erorilor, utilizați cu mare atenție." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Setări de bază" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Creați un fișier jurnal pentru această instanță SQM în /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Viteza de descărcare (kbit/s) (intrare) se setează la 0 pentru a dezactiva " +"selectiv modelarea intrării:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Activați SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Activează această instanță SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Starea ECN (Explicit congestion notification (notificare explicită de " +"congestie) pe pachetele de intrare (intrare):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" +"Starea ECN (Explicit congestion notification (notificare explicită de " +"congestie) pe pachetele de ieșire (egress)." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Acordă acces UCI pentru luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Limita dură a cozilor de ieșire; lăsați gol pentru valoarea implicită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Limita dură a cozilor de intrare; lăsați gol pentru valoarea implicită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Ignoră DSCP la intrare:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Numele interfeței" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Obiectivul de latență pentru ieșire, de exemplu, 5ms [unități: s, ms sau " +"us]; lăsați gol pentru selecția automată, introduceți cuvântul default " +"pentru valoarea implicită a qdiscului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Obiectivul de latență pentru intrare, de exemplu, 5ms [unități: s, ms sau " +"us]; lăsați gol pentru selecția automată, introduceți cuvântul default " +"pentru valoarea implicită a qdiscului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Adaptarea nivelului de legătură" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Dimensiunea maximă pentru calcularea mărimii și a ratei, tcMTU (byte); " +"trebuie să fie >= MTU al interfeței + overhead:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Dimensiunea minimă a pachetului, MPU (byte); trebuie să fie > 0 pentru " +"tabelele de dimensiuni ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Numărul de intrări în tabelele de mărime/taxe, TSIZE; pentru ATM, alegeți " +"TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Per Pachet Overhead (byte):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Disciplina cozii" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Script de configurare a cozilor de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Cozi de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Discipline de coadă de așteptare utilizabile pe acest sistem. După " +"instalarea unui nou qdisc, trebuie să reporniți routerul pentru a vedea " +"actualizările!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Afișează opțiunile avansate pentru Linklayer (necesar numai dacă MTU > 1500)" +". Opțiunile avansate vor fi utilizate numai atâta timp cât această casetă " +"este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Afișați și utilizați Configurație avansată. Opțiunile avansate vor fi " +"utilizate numai atât timp cât această casetă este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Afișare și utilizare Configurație periculoasă. Opțiunile periculoase vor fi " +"utilizate numai atât timp cât această casetă este bifată." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Gestionarea inteligentă a cozilor de așteptare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Zdrobiți DSCP pe pachetele de intrare (intrare):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"Interfața grafică SQM tocmai a activat initscriptul sqm în numele " +"dumneavoastră. Nu uitați să dezactivați manual sqm initscript în meniul " +"Pornire sistem în cazul în care această modificare nu a fost dorită." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Serviciul SQM pare să fie dezactivat. Vă rugăm să utilizați butonul de mai " +"jos pentru a activa acest serviciu." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Viteza de încărcare (kbit/s) (ieșire) se setează la 0 pentru a dezactiva " +"selectiv modelarea la ieșire:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Verbalitatea ieșirii SQM în jurnalul sistemului." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Ce strat de legătură trebuie luat în considerare:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" +"Ce mecanism de adaptare a linklayer-ului trebuie utilizat; numai pentru " +"testare" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"Cu SQM puteți activa modelarea " +"traficului, o mai bună amestecare (Fair Queueing), gestionarea activă a " +"lungimii cozilor de așteptare (AQM) și prioritizarea pe o singură interfață " +"de rețea." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "implicit" diff --git a/luci-app-sqm-autorate/po/ru/sqm.po b/luci-app-sqm-autorate/po/ru/sqm.po new file mode 100755 index 000000000..3aa81dd5a --- /dev/null +++ b/luci-app-sqm-autorate/po/ru/sqm.po @@ -0,0 +1,222 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-10-30 16:38+0000\n" +"Last-Translator: masta0f1eave \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.9-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Строка расширенных параметров для перехода к дисциплинам исходящей очереди; " +"нет проверки ошибок, используйте очень осторожно." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Строка расширенных параметров для перехода к входящим дисциплинам очередей; " +"нет проверки ошибок, используйте очень осторожно." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Основные настройки" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Создать файл журнала для этого экземпляра SQM в папке /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Включить SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Включите этот экземпляр SQM." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" +"Прямое уведомление о перегрузке сети (ECN) для входящих пакетов (ingress):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "Предоставить UCI доступ для luci-app-sqm" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" +"Жесткое ограничение на исходящие очереди; оставьте пустым для значения по " +"умолчанию." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" +"Жесткое ограничение на входящие очереди; оставьте пустым для значения по " +"умолчанию." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Адаптация канального уровня" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Минимальный размер пакета, MPU (байт); должен быть > 0 для таблиц размеров " +"Ethernet:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Скрипт настройки очереди" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Очереди" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Умное управление очередью" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "Детальность вывода SQM в системный журнал." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "по умолчанию" diff --git a/luci-app-sqm-autorate/po/sk/sqm.po b/luci-app-sqm-autorate/po/sk/sqm.po new file mode 100755 index 000000000..972333d16 --- /dev/null +++ b/luci-app-sqm-autorate/po/sk/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-12-06 14:03+0000\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Weblate 4.10-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Základné nastavenia" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/sv/sqm.po b/luci-app-sqm-autorate/po/sv/sqm.po new file mode 100755 index 000000000..fad4f0c12 --- /dev/null +++ b/luci-app-sqm-autorate/po/sv/sqm.po @@ -0,0 +1,216 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-01-31 14:55+0000\n" +"Last-Translator: Anders Jonsson \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.11-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avancerad alternativsträng för att överföra till utgångskö-disciplinerna; " +"inga felkontroller, använd mycket försiktigt." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Avancerad alternativsträng för att överföra till inträde till " +"utgångskö-disciplinerna; inga felkontroller, använd mycket försiktigt." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Grundinställningar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Skapa loggfil för denna SQM-instans under /var/run/sqm/" +"${Interface_name}.[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"Nerladdnings hastighet (kbit/s) (inträde) ställs in på 0 för att selektivt " +"inaktivera ingångs formning:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "Aktivera SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Aktivera denna SQM-instans." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Gränssnittets namn" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/templates/sqm.pot b/luci-app-sqm-autorate/po/templates/sqm.pot new file mode 100755 index 000000000..1ae5b9220 --- /dev/null +++ b/luci-app-sqm-autorate/po/templates/sqm.pot @@ -0,0 +1,265 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:207 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:204 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:75 +msgid "Autorate settings" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "Base download speed (kbit/s) (ingress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:110 +msgid "Base upload speed (kbit/s) (egress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:124 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:259 +msgid "Debug" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:90 +msgid "Enable SQM autorate" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:79 +msgid "Enable this SQM instance." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:178 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:192 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:188 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:166 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:93 +msgid "Interface name" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:200 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:196 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:227 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:105 +msgid "Maximum download speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:119 +msgid "Maximum upload speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:237 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "Minimum download speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:114 +msgid "Minimum upload speed (kbit/s):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Must be set to cake if autorate is used." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:232 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:287 +msgid "Number of seconds to wait on startup:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:255 +msgid "Output monitoring lines showing cake bandwidth changes" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:251 +msgid "Output monitoring lines showing processing stats" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:217 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:267 +msgid "Pingers numbers:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:144 +msgid "Queue setup script" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:263 +msgid "Reflector ping interval in seconds:" +msgstr "" + +#: luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:223 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:157 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:184 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:275 +msgid "Sleep functionnality" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:84 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:279 +msgid "Threshold in Kbit/s below which dl/ul is considered idle" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:283 +msgid "" +"Time threshold to put pingers to sleep on substained dl/ul achieved rate < " +"idle_threshold" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:127 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:211 +msgid "Which link layer to account for:" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:242 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:131 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:173 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:179 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:212 +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:243 +msgid "default" +msgstr "" + +#: luci-app-sqm-autorate/htdocs/luci-static/resources/view/network/sqm.js:271 +msgid "delay threshold in ms:" +msgstr "" diff --git a/luci-app-sqm-autorate/po/tr/sqm.po b/luci-app-sqm-autorate/po/tr/sqm.po new file mode 100755 index 000000000..c90ec8848 --- /dev/null +++ b/luci-app-sqm-autorate/po/tr/sqm.po @@ -0,0 +1,244 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-07-05 20:29+0000\n" +"Last-Translator: ToldYouThat \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Çıkış kuyruğu denetimleri için gelişmiş seçenek satırı; hata kontrolü " +"yoktur, dikkatli kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" +"Giriş kuyruğu denetimleri için gelişmiş seçenek satırı; hata kontrolü " +"yoktur, dikkatli kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "Temel Ayarlar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"Bu SQM örneği için /var/run/sqm/${Interface_name}.[start|stop]-sqm.log " +"konumda günlük dosyası oluşturun." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" +"İndirme hızı (kbit/s) (giriş) Şekillendirmeyi devre dışı bırakmak için 0 " +"olarak ayarlayın:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "SQM'i etkinleştir" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "Bu SQM örneğini etkinleştirin." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "Gelen paketlerde (giriş) açık tıkanıklık bildirimi (ECN) durumu:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "Giden paketlerde (çıkış) açık tıkanıklık bildirimi (ECN) durumu." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "luci-app-sqm için UCI erişimi verin" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "Çıkış kuyrukları için kesin sınır; varsayılan ayar için boş bırakın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "Giriş kuyrukları için kesin sınır; varsayılan ayar için boş bırakın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "Giriş kuyruğunda DSCP'yi yoksay:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Arayüz ismi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Çıkış için gecikme hedefi, örn. 5ms [birimler: s, ms, ya da us]; otomatik " +"seçim için boş bırakın, qdisc'in varsayılan ayarı için \"default\" yazın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"Giriş için gecikme hedefi, örn. 5ms [birimler: s, ms, ya da us]; otomatik " +"seçim için boş bırakın, qdisc'in varsayılan ayarı için \"default\" yazın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "Bağlantı Katmanı Uyarlaması" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" +"Boyut ve hız hesaplamaları için Maksimum Boyut, tcMTU (bayt); arayüzün MTU " +"değeri ve overhead toplamından büyük olması gerekir:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" +"Minimum paket boyutu, MPU (bayt); ethernet boyut tablosu için sıfırdan (0) " +"büyük olmalıdır:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" +"Boyut/hız tabloları için girdi sayıları, TSIZE; ATM için TSIZE = (tcMTU + " +"1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "Paket Başına Ek Yük (bayt):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "Kuyruk Denetimi" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "Kuyruk kurulum betiği" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "Kuyruklar" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" +"Bu sistemde kuyruk denetimleri kullanılabilir. Yeni bir qdisc yükledikten " +"sonra, devreye girmesi için yönlendiriciyi yeniden başlatmanız gerekir." + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"Gelişmiş bağlantı katmanı ayarlarını göster, (sadece MTU 1500'den büyükse " +"gereklidir). Gelişmiş seçenekler yalnızca bu kutu işaretliyken kullanılır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" +"Gelişmiş Ayarları Göster ve kullan. Gelişmiş seçenekler yalnızca bu kutu " +"işaretliyken kullanılır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" +"Tehlikeli Ayarları Göster ve Kullan. Tehlikeli olabilecek seçenekler " +"yalnızca bu kutu işaretliyken kullanılacaktır." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "Akıllı Kuyruk Yönetimi (SQM)" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "Gelen paketlerde (giriş) DSCP'yi sıkıştır:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"SQM GUI, sizin adınıza sqm initscript'i etkinleştirdi. Bu değişikliğin " +"istenmemesi durumunda sqm initscript'i System Startup menüsünden manuel " +"olarak devre dışı bırakmayı unutmayın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" +"Bu SQM servisi devre dışı görünüyor. Servisi aktif etmek için lütfen alttaki " +"butonu kullanın." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" +"Yükleme hızı (kbit/s) (çıkış) Şekillendirmeyi devre dışı bırakmak için 0 " +"olarak ayarlayın:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM çıktısının sistem günlüğü ayrıntısı." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "Bağlantı katmanı seçimi:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "Bağlantı katmanı uyarlama tekniği; yalnızca test için" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"SQM ile; trafik şekillendirme, " +"daha iyi sıkıştırma (Adil Kuyruklama), etkin kuyruk uzunluğu yönetimi (AQM) " +"ve bir ağ arayüzünü önceliklendirme gibi işlemler yapabilirsiniz." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "varsayılan" diff --git a/luci-app-sqm-autorate/po/uk/sqm.po b/luci-app-sqm-autorate/po/uk/sqm.po new file mode 100755 index 000000000..086b3c30c --- /dev/null +++ b/luci-app-sqm-autorate/po/uk/sqm.po @@ -0,0 +1,209 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-04-07 18:07+0000\n" +"Last-Translator: Yurii Petrashko \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" +"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.0-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "Назва інтерфейсу" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "" diff --git a/luci-app-sqm-autorate/po/vi/sqm.po b/luci-app-sqm-autorate/po/vi/sqm.po new file mode 100755 index 000000000..da12d68ad --- /dev/null +++ b/luci-app-sqm-autorate/po/vi/sqm.po @@ -0,0 +1,208 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-11-21 12:21+0000\n" +"Last-Translator: Darias \n" +"Language-Team: Vietnamese \n" +"Language: vi\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.4-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "Mặc định" diff --git a/luci-app-sqm-autorate/po/zh_Hans/sqm.po b/luci-app-sqm-autorate/po/zh_Hans/sqm.po new file mode 100755 index 000000000..45eda0b1b --- /dev/null +++ b/luci-app-sqm-autorate/po/zh_Hans/sqm.po @@ -0,0 +1,217 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-04-22 07:14+0000\n" +"Last-Translator: 王攀 <41330784@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "传递到出站队列规则的高级选项字符串;不会进行错误检查,请谨慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "传递到入站队列规则的高级选项字符串;不会进行错误检查,请谨慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本设置" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "" +"在此 /var/run/sqm/${Interface_name} 下为此 SQM 实例创建日志文件。[start|stop]-sqm.log." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "下载速度(kbit/s)(入口) 设为 0 时,有选择地禁用入口整形:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "启用 SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "启用此 SQM 实例." + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "入站数据包的显式拥塞通知(ECN)状态:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "出站数据包的显式拥塞通知(ECN)状态." + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "授予 UCI 访问 luci-app-sqm 的权限" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "出口队列的硬限制; 默认留空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "入口队列的硬限制; 默认留空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "在入口忽略 DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "接口名称" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "出口的延迟目标,例如 5ms [单位:s、ms或us]; " +"为自动选择留空,为qdisc的默认值输入单词default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "入口的延迟目标,例如 5ms [单位:s、ms 或 us]; " +"为自动选择留空,为qdisc的默认值输入单词default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "链路层适应" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "大小和速率计算的最大大小,tcMTU(字节); 需要 >= 接口 MTU + 开销:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "最小数据包大小,MPU(byte); 在以太网中需要 >0 :" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "大小/费率表中的条目数,TSIZE; 对于 ATM,选择 TSIZE = (tcMTU + 1) / 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "每个数据包开销(字节):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "列队规则" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "队列设置脚本" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "队列" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "队列规则(需要重启路由器)!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "服务质量管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"显示高级链路选项,(仅在MTU> 1500时才需要)。 只有选中此框时,才会使用高级选" +"项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "显示和使用高级配置。 只有在选中此框时,只会使用高级选项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "显示和使用危险配置。 只要选中此框,就会使用危险选项。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "智能队列管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "在入站数据包(入口)上压缩 DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"你刚刚开启了SQM随机启动功能,如果你不希望SQM随机启动,可以在系统启动菜单下手" +"动禁用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "SQM服务似乎已被禁用。请使用下面的按钮来激活这项服务。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "上传速度 (kbit/s)(出口)设置为 0 以选择性地禁用出口整形:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "SQM 输出到系统日志的详细程度。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "要考虑哪个链路层:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "使用哪个链路适应机制; 仅用于测试" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"使用 SQM 你可以启用流量整形,更好的混合" +"(公平列队)主动列队管理(AQM) 并设置网络接口优先级。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "默认" diff --git a/luci-app-sqm-autorate/po/zh_Hant/sqm.po b/luci-app-sqm-autorate/po/zh_Hant/sqm.po new file mode 100755 index 000000000..33dc43351 --- /dev/null +++ b/luci-app-sqm-autorate/po/zh_Hant/sqm.po @@ -0,0 +1,218 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-08-14 14:43+0000\n" +"Last-Translator: Hulen \n" +"Language-Team: Chinese (Traditional) \n" +"Language: zh_Hant\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.8-dev\n" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:183 +msgid "" +"Advanced option string to pass to the egress queueing disciplines; no error " +"checking, use very carefully." +msgstr "傳遞到出站佇列規則的進階選項字串,沒有錯誤檢查,請謹慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:180 +msgid "" +"Advanced option string to pass to the ingress queueing disciplines; no error " +"checking, use very carefully." +msgstr "傳遞到入站佇列規則的進階選項字串,沒有錯誤檢查,請謹慎使用。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:72 +msgid "Basic Settings" +msgstr "基本設定" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:100 +msgid "" +"Create log file for this SQM instance under /var/run/sqm/${Interface_name}." +"[start|stop]-sqm.log." +msgstr "建立日誌檔案 (/var/run/sqm/${Interface_name}.[start|stop]-sqm.log)。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:92 +msgid "" +"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress " +"shaping:" +msgstr "下載速度 (kbit/s) (0-無限制):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:58 +msgid "Enable SQM" +msgstr "啟用 SQM" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:78 +msgid "Enable this SQM instance." +msgstr "啟用 SQM。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:148 +msgid "" +"Explicit congestion notification (ECN) status on inbound packets (ingress):" +msgstr "傳入封包(入口)上的顯式擁塞通知 (ECN)狀態:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:154 +msgid "" +"Explicit congestion notification (ECN) status on outbound packets (egress)." +msgstr "傳出封包(出口)上的顯式擁塞通知(ECN)狀態。" + +#: applications/luci-app-sqm/root/usr/share/rpcd/acl.d/luci-app-sqm.json:3 +msgid "Grant UCI access for luci-app-sqm" +msgstr "授予 luci-app-sqm 擁有 UCI 存取的權限" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:168 +msgid "Hard limit on egress queues; leave empty for default." +msgstr "嚴格限制出口隊列;預設保留為空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:164 +msgid "Hard limit on ingress queues; leave empty for default." +msgstr "對入口隊列的硬限制;預設保留為空。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:142 +msgid "Ignore DSCP on ingress:" +msgstr "在進入時忽略DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:89 +msgid "Interface name" +msgstr "介面名稱" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:176 +msgid "" +"Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"出口的延遲目標,例如5ms [單位: s、ms、或us];留空以進行自動選擇,在qdisc的預" +"設值中輸入default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:172 +msgid "" +"Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for " +"automatic selection, put in the word default for the qdisc's default." +msgstr "" +"進入的延遲目標,例如5ms [單位: s、ms、或us];留空以進行自動選擇,在qdisc的預" +"設值中輸入default。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:74 +msgid "Link Layer Adaptation" +msgstr "連結層適應" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:203 +msgid "" +"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= " +"interface MTU + overhead:" +msgstr "用於大小和速率計算的最大大小,tcMTU (位元組);需要≧介面MTU +開銷:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:213 +msgid "" +"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:" +msgstr "最小封包大小,MPU(位元組);對於乙太網大小表,必須>0:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:208 +msgid "" +"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU " +"+ 1) / 16:" +msgstr "大小/費率表中的條目數,TSIZE;對於ATM,選擇TSIZE = (tcMTU + 1)/ 16:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:193 +msgid "Per Packet Overhead (byte):" +msgstr "每個封包開銷(位元組):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:73 +msgid "Queue Discipline" +msgstr "佇列規則" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:120 +msgid "Queue setup script" +msgstr "佇列設定指令碼" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:71 +msgid "Queues" +msgstr "佇列" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:112 +msgid "" +"Queuing disciplines useable on this system. After installing a new qdisc, " +"you need to restart the router to see updates!" +msgstr "安裝新的佇列規則後,需要重新啟動路由器!" + +#: applications/luci-app-sqm/root/usr/share/luci/menu.d/luci-app-sqm.json:3 +msgid "SQM QoS" +msgstr "SQM QoS頻寬管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:199 +msgid "" +"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced " +"options will only be used as long as this box is checked." +msgstr "" +"顯示 高級連接層選項 , (僅當MTU> 1500時才需要)。僅在選中此框時,才使用高級選" +"項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:133 +msgid "" +"Show and Use Advanced Configuration. Advanced options will only be used as " +"long as this box is checked." +msgstr "顯示使用進階選項,只有選取此選取框時,才會使用進階選項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:160 +msgid "" +"Show and Use Dangerous Configuration. Dangerous options will only be used as " +"long as this box is checked." +msgstr "顯示和使用危險組態。僅在選中此復選框後,才會使用危險選項。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:64 +msgid "Smart Queue Management" +msgstr "智慧隊列管理" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:136 +msgid "Squash DSCP on inbound packets (ingress):" +msgstr "在傳入封包(入口)上壓縮DSCP:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:83 +msgid "" +"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to " +"disable the sqm initscript manually under System Startup menu in case this " +"change was not wished for." +msgstr "" +"此 SQM GUI 剛剛代表您啟用了sqm初始化指令碼。切記在「系統啟動」選單下,手動停" +"用sqm初始化指令碼,以防意外變更。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:48 +msgid "" +"The SQM service seems to be disabled. Please use the button below to " +"activate this service." +msgstr "SQM 服務似乎已被停用。請使用下面的按鈕來啟動這項服務。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:96 +msgid "" +"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress " +"shaping:" +msgstr "上傳速度 (kbit/s) (0-無限制):" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:103 +msgid "Verbosity of SQM's output into the system log." +msgstr "日誌等級。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:187 +msgid "Which link layer to account for:" +msgstr "連結層:" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:218 +msgid "Which linklayer adaptation mechanism to use; for testing only" +msgstr "使用哪種連接層適配機制;僅用於測試" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:65 +msgid "" +"With SQM you can enable " +"traffic shaping, better mixing (Fair Queueing), active queue length " +"management (AQM) and prioritisation on one network interface." +msgstr "" +"使用 SQM 您可以啟用流量整形,更" +"好的混合 (公平佇列),主動佇列管理 (AQM) 並設定網路介面優先順序。" + +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:107 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:149 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:155 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:188 +#: applications/luci-app-sqm/htdocs/luci-static/resources/view/network/sqm.js:219 +msgid "default" +msgstr "預設" diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate new file mode 100755 index 000000000..3f2d5c87d --- /dev/null +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -0,0 +1,62 @@ +#!/bin/sh /etc/rc.common +# shellcheck disable=SC2039 +# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 : +# Copyright (C) 2018-2022 Ycarus (Yannick Chabanois) +# Released under GPL 3. See LICENSE for the full terms. + +# shellcheck disable=SC2034 +{ + START=90 + STOP=10 + USE_PROCD=1 +} + +. /usr/lib/unbound/iptools.sh +. /lib/functions/network.sh + +_config_autorate() { + logger -t "SQM-autorate" "Set config for $1" + config_get enabled "$1" enabled + [ "${enabled}" != "1" ] && return + config_get autorate "$1" autorate + [ "${autorate}" != "1" ] && return + + config_get min_download "$1" min_download "0" + config_get download "$1" download "0" + config_get max_download "$1" max_download "0" + [ "${min_download}" == "0" ] || [ "${max_download}" == "0" ] || [ "${download}" == "0" ] && return + config_get min_upload "$1" min_upload "0" + config_get upload "$1" upload "0" + config_get max_upload "$1" max_upload "0" + [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return +# config_get interface "$1" interface +# cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh + cp /usr/share/sqm-autorate/config_template.sh /usr/share/sqm-autorate/config.$1.sh +} + +_launch_autorate() { + logger -t "SQM-autorate" "Launch..." + procd_open_instance + # shellcheck disable=SC2086 + procd_set_param command /usr/share/sqm-autorate/launcher.sh + procd_set_param limits nofile="51200 51200" + procd_set_param respawn 0 10 0 + procd_set_param stderr 1 + procd_close_instance +} + +start_service() { + rm -f /usr/share/sqm-autorate/config.*.sh + config_load sqm + config_foreach _config_autorate queue + _launch_autorate +} + +reload_service() { + stop + start +} + +service_triggers() { + procd_add_reload_trigger sqm +} \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm new file mode 100755 index 000000000..7f472f725 --- /dev/null +++ b/luci-app-sqm-autorate/root/etc/uci-defaults/50-luci-sqm @@ -0,0 +1,17 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@sqm[-1] + add ucitrack sqm + set ucitrack.@sqm[-1].init=sqm + del_list ucitrack.@firewall[0].affects=sqm + add_list ucitrack.@firewall[0].affects=sqm + delete ucitrack.@sqm-autorate[-1] + add ucitrack sqm-autorate + set ucitrack.@sqm-autorate[-1].init=sqm-autorate + del_list ucitrack.@firewall[0].affects=sqm-autorate + add_list ucitrack.@firewall[0].affects=sqm-autorate + commit ucitrack +EOF + +exit 0 diff --git a/luci-app-sqm-autorate/root/root/cake-autorate b/luci-app-sqm-autorate/root/root/cake-autorate new file mode 120000 index 000000000..66f5d6886 --- /dev/null +++ b/luci-app-sqm-autorate/root/root/cake-autorate @@ -0,0 +1 @@ +../usr/share/sqm-autorate \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json b/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json new file mode 100755 index 000000000..6c5ff4fa6 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/luci/menu.d/luci-app-sqm.json @@ -0,0 +1,13 @@ +{ + "admin/network/sqm": { + "title": "SQM QoS", + "order": 59, + "action": { + "type": "view", + "path": "network/sqm" + }, + "depends": { + "acl": [ "luci-app-sqm" ] + } + } +} diff --git a/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json b/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json new file mode 100755 index 000000000..810d91b83 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/rpcd/acl.d/luci-app-sqm.json @@ -0,0 +1,23 @@ +{ + "luci-app-sqm": { + "description": "Grant UCI access for luci-app-sqm", + "read": { + "file": { + "/var/run/sqm/available_qdiscs": [ "list" ], + "/usr/lib/sqm/*.qos.help": [ "read" ], + "/etc/init.d/sqm enable" : [ "exec" ], + "/etc/init.d/sqm start" : [ "exec" ], + "/etc/init.d/sqm-autorate enable" : [ "exec" ], + "/etc/init.d/sqm-autorate start" : [ "exec" ] + }, + "uci": [ "sqm" ], + "ubus": { + "file": [ "read", "list" ], + "luci": [ "setInitAction" ] + } + }, + "write": { + "uci": [ "sqm" ] + } + } +} diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh new file mode 100755 index 000000000..6067cdca8 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -0,0 +1,2270 @@ +#!/bin/bash + +# cake-autorate automatically adjusts CAKE bandwidth(s) +# in dependence on: a) receive and transmit transfer rates; and b) latency +# (or can just be used to monitor and log transfer rates and latency) + +# requires: bash; and one of the supported ping binaries + +# each cake-autorate instance must be configured using a corresponding config file + +# Project homepage: https://github.com/lynxthecat/cake-autorate +# Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md + +# Author and maintainer: lynxthecat +# Contributors: rany2; moeller0; richb-hanover + +cake_autorate_version="2.0.0" + +## cake-autorate uses multiple asynchronous processes including: +## main - main process +## monitor_achieved_rates - monitor network transfer rates +## maintain_pingers - manage pingers and active reflectors +## parse_${pinger_binary} - control and parse ping responses +## parse_preprocessor - prepend field for parse_${pinger_binary} +## maintain_log_file - maintain and rotate log file +## +## IPC is facilitated via FIFOs in the form of anonymous pipes +## accessible via fds in the form: ${process_name_fd} +## thereby to enable transferring instructions and data between processes + +# Initialize file descriptors +## -1 signifies that the log file fd will not be used and +## that the log file will be written to directly +log_fd=-1 +exec {main_fd}<> <(:) +exec {monitor_achieved_rates_fd}<> <(:) +exec {maintain_pingers_fd}<> <(:) +# pinger_fds are set below in dependence upon ping binary and number of pingers + +# process pids are stored below in the form +# proc_pids['process_identifier']=${!} +declare -A proc_pids + +# Bash correctness options +## Disable globbing (expansion of *). +set -f +## Forbid using unset variables. +set -u +## The exit status of a pipeline is the status of the last +## command to exit with a non-zero status, or zero if no +## command exited with a non-zero status. +set -o pipefail + +## Errors are intercepted via intercept_stderr below +## and sent to the log file and system log + +# Possible performance improvement +export LC_ALL=C + +# Set PREFIX +PREFIX=/root/cake-autorate + +# shellcheck source=lib.sh +. "${PREFIX}/lib.sh" +# shellcheck source=defaults.sh +. "${PREFIX}/defaults.sh" +# get valid config overrides +mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') + +trap cleanup_and_killall INT TERM EXIT + +cleanup_and_killall() +{ + # Do not fail on error for this critical cleanup code + set +e + + trap true INT TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + log_msg "INFO" "Stopping cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + log_msg "INFO" "Killing all background processes and cleaning up temporary files." + + printf "TERMINATE\n" >&"${maintain_pingers_fd}" + printf "TERMINATE\n" >&"${monitor_achieved_rates_fd}" + + [[ -d "${run_path}" ]] && rm -r "${run_path}" + rmdir /var/run/cake-autorate 2>/dev/null + + # give some time for processes to gracefully exit + sleep_s 1 + + # terminate any processes that remain, save for main and intercept_stderr + unset "proc_pids[main]" + intercept_stderr_pid="${proc_pids[intercept_stderr]:-}" + if [[ -n "${intercept_stderr_pid}" ]] + then + unset "proc_pids[intercept_stderr]" + fi + terminate "${proc_pids[@]}" + + # restore original stderr, and terminate intercept_stderr + if [[ -n "${intercept_stderr_pid}" ]] + then + exec 2>&"${original_stderr_fd}" + terminate "${intercept_stderr_pid}" + fi + + log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" + + trap - INT TERM EXIT + exit +} + +log_msg() +{ + # send logging message to terminal, log file fifo, log file and/or system logger + + local type="${1}" + local msg="${2}" + local instance_id="${instance_id:-"unknown"}" + local log_timestamp=${EPOCHREALTIME} + + case ${type} in + + DEBUG) + ((debug == 0)) && return # skip over DEBUG messages where debug disabled + ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + ERROR) + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" + ;; + + SYSLOG) + ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" + ;; + + *) + ;; + esac + + # Output to the log file fifo if available (for rotation handling) + # else output directly to the log file + if (( log_fd >= 0 )) + then + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" + else + ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" + fi + + ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" +} + +print_headers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + header="DATA_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; DL_LOAD_PERCENT; UL_LOAD_PERCENT; RTT_TIMESTAMP; REFLECTOR; SEQUENCE; DL_OWD_BASELINE; DL_OWD_US; DL_OWD_DELTA_EWMA_US; DL_OWD_DELTA_US; DL_ADJ_DELAY_THR; UL_OWD_BASELINE; UL_OWD_US; UL_OWD_DELTA_EWMA_US; UL_OWD_DELTA_US; UL_ADJ_DELAY_THR; SUM_DL_DELAYS; SUM_UL_DELAYS; DL_LOAD_CONDITION; UL_LOAD_CONDITION; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="LOAD_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; DL_ACHIEVED_RATE_KBPS; UL_ACHIEVED_RATE_KBPS; CAKE_DL_RATE_KBPS; CAKE_UL_RATE_KBPS" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" + + header="REFLECTOR_HEADER; LOG_DATETIME; LOG_TIMESTAMP; PROC_TIME_US; REFLECTOR; MIN_SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_US; SUM_OWD_BASELINES_DELTA_US; SUM_OWD_BASELINES_DELTA_THR_US; MIN_DL_DELTA_EWMA_US; DL_DELTA_EWMA_US; DL_DELTA_EWMA_DELTA_US; DL_DELTA_EWMA_DELTA_THR; MIN_UL_DELTA_EWMA_US; UL_DELTA_EWMA_US; UL_DELTA_EWMA_DELTA_US; UL_DELTA_EWMA_DELTA_THR" + ((log_to_file)) && printf '%s\n' "${header}" >> "${log_file_path}" + ((terminal)) && printf '%s\n' "${header}" +} + +# MAINTAIN_LOG_FILE + HELPER FUNCTIONS + +rotate_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if [[ -f ${log_file_path} ]] + then + cat "${log_file_path}" > "${log_file_path}.old" + true > "${log_file_path}" + fi + + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes +} + +reset_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + rm -f "${log_file_path}.old" + true > "${log_file_path}" + + ((output_processing_stats)) && print_headers + t_log_file_start_us=${EPOCHREALTIME/./} + get_log_file_size_bytes +} + +generate_log_file_scripts() +{ + cat > "${run_path}/log_file_export" <<- EOT + #!/bin/bash + + timeout_s=\${1:-20} + + if kill -USR1 "${proc_pids['maintain_log_file']}" + then + printf "Successfully signalled maintain_log_file process to request log file export.\n" + else + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + rm -f "${run_path}/last_log_file_export" + + read_try=0 + + while [[ ! -f "${run_path}/last_log_file_export" ]] + do + sleep 1 + if (( ++read_try >= \${timeout_s} )) + then + printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 + exit 1 + fi + done + + read -r log_file_export_path < "${run_path}/last_log_file_export" + + printf "Log file export complete.\n" + + printf "Log file available at location: " + printf "\${log_file_export_path}\n" + EOT + + cat > "${run_path}/log_file_reset" <<- EOT + #!/bin/bash + + if kill -USR2 "${proc_pids['maintain_log_file']}" + then + printf "Successfully signalled maintain_log_file process to request log file reset.\n" + else + printf "ERROR: Failed to signal maintain_log_file process.\n" >&2 + exit 1 + fi + EOT + + chmod +x "${run_path}/log_file_export" "${run_path}/log_file_reset" +} + +export_log_file() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + printf -v log_file_export_datetime '%(%Y_%m_%d_%H_%M_%S)T' + log_file_export_path="${log_file_path/.log/_${log_file_export_datetime}.log}" + log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" + + # Now export with or without compression to the appropriate export path + if ((log_file_export_compress)) + then + log_file_export_path="${log_file_export_path}.gz" + if [[ -f "${log_file_path}.old" ]] + then + gzip -c "${log_file_path}.old" > "${log_file_export_path}" + gzip -c "${log_file_path}" >> "${log_file_export_path}" + else + gzip -c "${log_file_path}" > "${log_file_export_path}" + fi + else + if [[ -f "${log_file_path}.old" ]] + then + cp "${log_file_path}.old" "${log_file_export_path}" + cat "${log_file_path}" >> "${log_file_export_path}" + else + cp "${log_file_path}" "${log_file_export_path}" + fi + fi + + printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" +} + +flush_log_fd() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + while read -r -t 0 -u "${log_fd}" + do + read -r -u "${log_fd}" log_line + printf '%s\n' "${log_line}" >> "${log_file_path}" + done +} + +get_log_file_size_bytes() +{ + log_file_size_bytes=$(wc -c "${log_file_path}" 2>/dev/null | awk '{print $1}') + log_file_size_bytes=${log_file_size_bytes:-0} +} + +kill_maintain_log_file() +{ + trap - TERM EXIT + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + flush_log_fd + exit +} + +maintain_log_file() +{ + trap '' INT + trap 'kill_maintain_log_file' TERM EXIT + trap 'export_log_file' USR1 + trap 'reset_log_file_signalled=1' USR2 + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + reset_log_file_signalled=0 + t_log_file_start_us=${EPOCHREALTIME/./} + + get_log_file_size_bytes + + while read -r -u "${log_fd}" log_line + do + + printf '%s\n' "${log_line}" >> "${log_file_path}" + + # Verify log file size < configured maximum + # The following two lines with costly call to 'du': + # read log_file_size_bytes< <(du -b ${log_file_path}/cake-autorate.log) + # log_file_size_bytes=${log_file_size_bytes//[!0-9]/} + # can be more efficiently handled with this line: + ((log_file_size_bytes=log_file_size_bytes+${#log_line}+1)) + + # Verify log file time < configured maximum + if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) + then + + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( log_file_size_bytes > log_file_max_size_bytes )) + then + log_file_size_KB=$((log_file_size_bytes/1024)) + log_msg "DEBUG" "log file size: ${log_file_size_KB} KB has exceeded configured maximum: ${log_file_max_size_KB} KB so flushing and rotating log file." + flush_log_fd + rotate_log_file + elif (( reset_log_file_signalled )) + then + log_msg "DEBUG" "received log file reset signal so flushing and resetting log file." + flush_log_fd + reset_log_file + reset_log_file_signalled=0 + fi + + done +} + +update_shaper_rate() +{ + local direction="${1}" # 'dl' or 'ul' + + case "${load_condition["${direction}"]}" in + + # upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period + ul*sss) + shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" + ;; + # download Starlink satelite switching compensation, so drop down to base rate for download through switching period + dl*sss) + shaper_rate_kbps["${direction}"]=$(( shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"] ? base_shaper_rate_kbps["${direction}"] : shaper_rate_kbps["${direction}"] )) + ;; + # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period + *bb*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then + adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) + adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) + shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) + t_last_bufferbloat_us["${direction}"]="${EPOCHREALTIME/./}" + fi + ;; + # high load, so increase rate providing not inside bufferbloat refractory period + *high*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then + shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) + fi + ;; + # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate + *low*|*idle*) + if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )) + then + + if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])) + then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) + elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])) + then + decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) + shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) + fi + + t_last_decay_us["${direction}"]="${EPOCHREALTIME/./}" + fi + ;; + *) + log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate" + kill $$ 2>/dev/null + ;; + esac + # make sure to only return rates between cur_min_rate and cur_max_rate + ((shaper_rate_kbps["${direction}"] < min_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${min_shaper_rate_kbps[${direction}]}" + ((shaper_rate_kbps["${direction}"] > max_shaper_rate_kbps["${direction}"])) && shaper_rate_kbps["${direction}"]="${max_shaper_rate_kbps[${direction}]}" +} + +monitor_achieved_rates() +{ + trap '' INT + + # track rx and tx bytes transfered and divide by time since last update + # to determine achieved dl and ul transfer rates + + local rx_bytes_path="${1}" + local tx_bytes_path="${2}" + local monitor_achieved_rates_interval_us="${3}" # (microseconds) + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + compensated_monitor_achieved_rates_interval_us="${monitor_achieved_rates_interval_us}" + + [[ -f "${rx_bytes_path}" ]] && { read -r prev_rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || prev_rx_bytes=0 + [[ -f "${tx_bytes_path}" ]] && { read -r prev_tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || prev_tx_bytes=0 + + sleep_duration_s=0 + t_start_us=0 + + declare -A achieved_rate_kbps + declare -A load_percent + + while true + do + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${monitor_achieved_rates_fd}" + do + unset command + read -r -u "${monitor_achieved_rates_fd}" -a command + case "${command[0]:-}" in + + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done + + # If rx/tx bytes file exists, read it in, otherwise set to prev_bytes + # This addresses interfaces going down and back up + [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" + [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" + + achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + + ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 + ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 + + printf "SET_ARRAY_ELEMENT achieved_rate_kbps dl %s\n" "${achieved_rate_kbps[dl]}" >&"${main_fd}" + printf "SET_ARRAY_ELEMENT achieved_rate_kbps ul %s\n" "${achieved_rate_kbps[ul]}" >&"${main_fd}" + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + for pinger_fd in "${pinger_fds[@]:?}" + do + printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" + printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" + done + + if ((output_load_stats)) + then + + printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" + log_msg "LOAD" "${load_stats}" + fi + + prev_rx_bytes="${rx_bytes}" + prev_tx_bytes="${tx_bytes}" + + compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) + + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" + + done +} + + +classify_load() +{ + # classify the load according to high/low/idle and add _delayed if delayed + # thus ending up with high_delayed, low_delayed, etc. + local direction="${1}" + + if (( load_percent["${direction}"] > high_load_thr_percent )) + then + load_condition["${direction}"]="high" + elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )) + then + load_condition["${direction}"]="low" + else + load_condition["${direction}"]="idle" + fi + + ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" + + if ((sss_compensation)) + then + # shellcheck disable=SC2154 + for sss_time_us in "${sss_times_us[@]}" + do + ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) + if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )) + then + load_condition["${direction}"]="${load_condition[${direction}]}_sss" + break + fi + done + fi + + load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" +} + +# MAINTAIN PINGERS + ASSOCIATED HELPER FUNCTIONS + +parse_preprocessor() +{ + # prepend REFLECTOR_RESPONSE and append timestamp as a checksum + while read -r timestamp remainder + do + printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" + done +} + +parse_tsping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + local reflectors=("${@:2}") + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + for (( reflector=0; reflector >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + # accommodate present tsping interval/sleep handling to prevent ping flood with only one pinger + tsping_sleep_time=$(( no_pingers == 1 ? ping_response_interval_ms : 0 )) + ${ping_prefix_string} tsping ${ping_extra_args} --print-timestamps --machine-readable=' ' --sleep-time "${tsping_sleep_time}" --target-spacing "${ping_response_interval_ms}" "${reflectors[@]:0:${no_pingers}}" 2>/dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + for (( reflector=0; reflector 50 mins, immediately reset the baselines to the new dl_owd_us and ul_owd_us. + # + # Happilly, the sum of dl_owd_baseline_us and ul_owd_baseline_us will roughly equal rtt_baseline_us. + # And since Transmit is approximately equal to Received, RTT is approximately equal to Finished - Originate. + # And thus the sum of dl_owd_baseline_us and ul_owd_baseline_us should not be affected by the rollover/compensation. + # Hence working with this sum, rather than the individual components, is useful for the reflector health check in maintain_pingers(). + + if (( (${dl_owd_delta_us#-} + ${ul_owd_delta_us#-}) < 3000000000 )) + then + + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + ul_alpha=$(( ul_owd_us >= ul_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ewma_iteration "${ul_owd_us}" "${ul_alpha}" "ul_owd_baselines_us[${reflector}]" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us=$(( ul_owd_us - ul_owd_baselines_us[${reflector}] )) + else + dl_owd_baselines_us[${reflector}]=${dl_owd_us} + ul_owd_baselines_us[${reflector}]=${ul_owd_us} + + dl_owd_delta_us=0 + ul_owd_delta_us=0 + fi + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ewma_iteration "${ul_owd_delta_us}" "${alpha_delta_ewma}" "ul_owd_delta_ewmas_us[${reflector}]" + fi + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} + +parse_fping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + local parse_id="${1}" + + local reflectors=("${@:2}") + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + for (( reflector=0; reflector >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} fping ${ping_extra_args} --timestamp --loop --period "${reflector_ping_interval_ms}" --interval "${ping_response_interval_ms}" --timeout 10000 "${reflectors[@]:0:${no_pingers}}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTORS) + + read -r -a reflectors <<< "${command[@]:1}" + log_msg "DEBUG" "Read in new reflectors: ${reflectors[*]}" + for (( reflector=0; reflector= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us="${dl_owd_delta_us}" + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi + + timestamp="${timestamp//[\[\]]}0" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} +# IPUTILS-PING FUNCTIONS +parse_ping() +{ + trap '' INT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + + # ping reflector, maintain baseline and output deltas to a common fifo + + local parse_id="${1}" + local reflector="${2}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + + dl_owd_baselines_us["${reflector}"]=100000 + ul_owd_baselines_us["${reflector}"]=100000 + dl_owd_delta_ewmas_us["${reflector}"]=0 + ul_owd_delta_ewmas_us["${reflector}"]=0 + + declare -A load_percent + load_percent[dl]=0 + load_percent[ul]=0 + + while true + do + unset command + read -r -u "${pinger_fds[pinger]}" -a command + if [[ "${command-}" ]] + then + case "${command[0]}" in + + REFLECTOR_RESPONSE) + + read -r timestamp _ _ _ reflector seq_rtt <<< "${command[@]:1}" + checksum="${command[*]: -1}" + ;; + + START_PINGER) + + exec {parse_preprocessor_fd}> >(parse_preprocessor) + parse_preprocessor_pid="${!}" + printf "SET_PROC_PID %s %s\n" "proc_pids ${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" + ${ping_prefix_string} ping ${ping_extra_args} -D -i "${reflector_ping_interval_s}" "${reflector}" 2> /dev/null >&"${parse_preprocessor_fd}" & + pinger_pid="${!}" + printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_pinger" "${pinger_pid}" >&"${main_fd}" + continue + ;; + + KILL_PINGER) + + terminate "${pinger_pid}" "${parse_preprocessor_pid}" + exec {parse_preprocessor_fd}>&- + continue + ;; + + SET_REFLECTOR) + + if [[ "${#command[@]}" -eq 2 ]] + then + reflector="${command[1]}" + log_msg "DEBUG" "Read in new reflector: ${reflector}" + dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" + ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" + dl_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]:-0}" + ul_owd_delta_ewmas_us["${reflector}"]="${ul_owd_delta_ewmas_us[${reflector}]:-0}" + continue + fi + ;; + + SET_VAR) + + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + continue + ;; + + SET_ARRAY_ELEMENT) + + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + continue + ;; + + TERMINATE) + + log_msg "DEBUG" "Terminating parse_ping." + exit + ;; + + *) + + continue + ;; + + esac + fi + + if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] + then + [[ "${checksum}" == "${timestamp}" ]] + # If no match then skip onto the next one + [[ "${seq_rtt}" =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue + + reflector=${reflector//:/} + + seq=${BASH_REMATCH[1]} + + rtt_us=${BASH_REMATCH[3]}000 + rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) + + dl_owd_us=$((rtt_us/2)) + ul_owd_us="${dl_owd_us}" + + dl_alpha=$(( dl_owd_us >= dl_owd_baselines_us[${reflector}] ? alpha_baseline_increase : alpha_baseline_decrease )) + + ewma_iteration "${dl_owd_us}" "${dl_alpha}" "dl_owd_baselines_us[${reflector}]" + ul_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]}" + + dl_owd_delta_us=$(( dl_owd_us - dl_owd_baselines_us[${reflector}] )) + ul_owd_delta_us="${dl_owd_delta_us}" + + if (( load_percent[dl] < high_load_thr_percent && load_percent[ul] < high_load_thr_percent)) + then + ewma_iteration "${dl_owd_delta_us}" "${alpha_delta_ewma}" "dl_owd_delta_ewmas_us[${reflector}]" + ul_owd_delta_ewmas_us["${reflector}"]="${dl_owd_delta_ewmas_us[${reflector}]}" + fi + + timestamp="${timestamp//[\[\]]}" + + printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" + + timestamp_us="${timestamp//[.]}" + + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" + + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" + fi + done +} + +# END OF IPUTILS-PING FUNCTIONS + +# GENERIC PINGER START AND STOP FUNCTIONS + +start_pinger() +{ + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${pinger_binary} in + + tsping|fping) + pinger=0 + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" + ;; + ping) + sleep_until_next_pinger_time_slot "${pinger}" + printf "START_PINGER\n" >&"${pinger_fds[pinger]}" + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +start_pingers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${pinger_binary} in + + tsping|fping) + start_pinger 0 + ;; + ping) + for ((pinger=0; pinger < no_pingers; pinger++)) + do + start_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +sleep_until_next_pinger_time_slot() +{ + # wait until next pinger time slot and start pinger in its slot + # this allows pingers to be stopped and started (e.g. during sleep or reflector rotation) + # whilst ensuring pings will remain spaced out appropriately to maintain granularity + + local pinger="${1}" + + t_start_us=${EPOCHREALTIME/./} + time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) + sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" +} + +kill_pinger() +{ + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${pinger_binary}" in + tsping|fping) + pinger=0 + ;; + + *) + ;; + esac + + printf "KILL_PINGER\n" >&"${pinger_fds[pinger]}" +} + +kill_pingers() +{ + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${pinger_binary}" in + + tsping|fping) + log_msg "DEBUG" "Killing ${pinger_binary} instance." + kill_pinger 0 + ;; + ping) + for (( pinger=0; pinger < no_pingers; pinger++)) + do + log_msg "DEBUG" "Killing pinger instance: ${pinger}" + kill_pinger "${pinger}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac +} + +replace_pinger_reflector() +{ + # pingers always use reflectors[0]..[no_pingers-1] as the initial set + # and the additional reflectors are spare reflectors should any from initial set go stale + # a bad reflector in the initial set is replaced with ${reflectors[no_pingers]} + # ${reflectors[no_pingers]} is then unset + # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) + # and finally the indices for ${reflectors} are updated to reflect the new order + + local pinger="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + if ((no_reflectors > no_pingers)) + then + log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." + kill_pinger "${pinger}" + bad_reflector=${reflectors[pinger]} + # overwrite the bad reflector with the reflector that is next in the queue (the one after 0..${no_pingers}-1) + reflectors[pinger]=${reflectors[no_pingers]} + # remove the new reflector from the list of additional reflectors beginning from ${reflectors[no_pingers]} + unset "reflectors[no_pingers]" + # bad reflector goes to the back of the queue + reflectors+=("${bad_reflector}") + # reset array indices + mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) + # set up the new pinger with the new reflector and retain pid + case ${pinger_binary} in + + tsping|fping) + printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" + ;; + ping) + printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + start_pinger "${pinger}" + else + log_msg "DEBUG" "No additional reflectors specified so just retaining: ${reflectors[pinger]}." + fi + + log_msg "DEBUG" "Resetting reflector offences associated with reflector: ${reflectors[pinger]}." + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i&"${pinger_fds[0]}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + printf "TERMINATE\n" >&"${pinger_fds[pinger]}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + + exit +} + +change_state_maintain_pingers() +{ + local maintain_pingers_next_state="${1:-unset}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case "${maintain_pingers_next_state}" in + + START|STOP|PAUSED|RUNNING) + + if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]] + then + log_msg "ERROR" "Received request to change maintain_pingers state to existing state." + return + fi + + log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" + maintain_pingers_state=${maintain_pingers_next_state} + ;; + + *) + + log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." + kill $$ 2>/dev/null + ;; + esac +} + +maintain_pingers() +{ + # this initiates the pingers and monitors reflector health, rotating reflectors as necessary + + trap '' INT + trap 'kill_maintain_pingers' TERM EXIT + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + declare -A dl_owd_baselines_us + declare -A ul_owd_baselines_us + declare -A dl_owd_delta_ewmas_us + declare -A ul_owd_delta_ewmas_us + declare -A last_timestamp_reflectors_us + + err_silence=0 + reflector_offences_idx=0 + pingers_active=0 + + pingers_t_start_us="${EPOCHREALTIME/./}" + t_last_reflector_replacement_us="${EPOCHREALTIME/./}" + t_last_reflector_comparison_us="${EPOCHREALTIME/./}" + + for ((reflector=0; reflector < no_reflectors; reflector++)) + do + last_timestamp_reflectors_us["${reflectors[reflector]}"]="${pingers_t_start_us}" + done + + # For each pinger initialize record of offences + for ((pinger=0; pinger < no_pingers; pinger++)) + do + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + for ((i=0; i&"${main_fd}" + ;; + fping) + parse_fping "parse_fping" "${reflectors[@]:0:${no_pingers}}" & + printf "SET_PROC_PID proc_pids parse_fping %s\n" "${!}" >&"${main_fd}" + ;; + ping) + for((pinger=0; pinger < no_pingers; pinger++)) + do + parse_ping "parse_ping_${pinger}" "${reflectors[pinger]}" & + printf "SET_PROC_PID proc_pids %s %s\n" "parse_ping_${pinger}" "${!}" >&"${main_fd}" + done + ;; + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + kill $$ 2>/dev/null + ;; + esac + + + # Reflector maintenance loop - verifies reflectors have not gone stale and rotates reflectors as necessary + while true + do + t_start_us="${EPOCHREALTIME/./}" + + while read -r -t 0 -u "${maintain_pingers_fd}" + do + unset command + read -r -u "${maintain_pingers_fd}" -a command + case "${command[0]:-}" in + + CHANGE_STATE) + if [[ "${#command[@]}" -eq 2 ]] + then + change_state_maintain_pingers "${command[1]}" + # break out of reading any new IPC commands to handle next state + # if pingers need to be started or stopped + case "${command[1]}" in + START|STOP) + break + ;; + *) + : + ;; + esac + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + TERMINATE) + log_msg "DEBUG" "Terminating monitor_achieved_rates." + exit + ;; + *) + : + ;; + esac + done + + case "${maintain_pingers_state}" in + + START) + if ((pingers_active==0)) + then + start_pingers + pingers_active=1 + fi + change_state_maintain_pingers "RUNNING" + ;; + + STOP) + if ((pingers_active)) + then + kill_pingers + pingers_active=0 + fi + change_state_maintain_pingers "PAUSED" + ;; + + PAUSED) + ;; + + RUNNING) + + if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) + then + pinger=$((RANDOM%no_pingers)) + log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." + replace_pinger_reflector "${pinger}" + t_last_reflector_replacement_us=${EPOCHREALTIME/./} + continue + fi + + if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )) + then + + t_last_reflector_comparison_us=${EPOCHREALTIME/./} + + [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue + + min_sum_owd_baselines_us=$(( dl_owd_baselines_us[${reflectors[0]}] + ul_owd_baselines_us[${reflectors[0]}] )) + min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[0]}]}" + min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[0]}]}" + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + [[ "${dl_owd_baselines_us[${reflectors[pinger]}]:-}" && "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" && "${ul_owd_baselines_us[${reflectors[pinger]}]:-}" && "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]:-}" ]] || continue 2 + + sum_owd_baselines_us[pinger]=$(( dl_owd_baselines_us[${reflectors[pinger]}] + ul_owd_baselines_us[${reflectors[pinger]}] )) + (( sum_owd_baselines_us[pinger] < min_sum_owd_baselines_us )) && min_sum_owd_baselines_us="${sum_owd_baselines_us[pinger]}" + (( dl_owd_delta_ewmas_us[${reflectors[pinger]}] < min_dl_owd_delta_ewma_us )) && min_dl_owd_delta_ewma_us="${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" + (( ul_owd_delta_ewmas_us[${reflectors[pinger]}] < min_ul_owd_delta_ewma_us )) && min_ul_owd_delta_ewma_us="${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" + done + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + + sum_owd_baselines_delta_us=$(( sum_owd_baselines_us[pinger] - min_sum_owd_baselines_us )) + dl_owd_delta_ewma_delta_us=$(( dl_owd_delta_ewmas_us[${reflectors[pinger]}] - min_dl_owd_delta_ewma_us )) + ul_owd_delta_ewma_delta_us=$(( ul_owd_delta_ewmas_us[${reflectors[pinger]}] - min_ul_owd_delta_ewma_us )) + + if ((output_reflector_stats)) + then + printf -v reflector_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${reflectors[pinger]}" "${min_sum_owd_baselines_us}" "${sum_owd_baselines_us[pinger]}" "${sum_owd_baselines_delta_us}" "${reflector_sum_owd_baselines_delta_thr_us}" "${min_dl_owd_delta_ewma_us}" "${dl_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${dl_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" "${min_ul_owd_delta_ewma_us}" "${ul_owd_delta_ewmas_us[${reflectors[pinger]}]}" "${ul_owd_delta_ewma_delta_us}" "${reflector_owd_delta_ewma_delta_thr_us}" + log_msg "REFLECTOR" "${reflector_stats}" + fi + + if (( sum_owd_baselines_delta_us > reflector_sum_owd_baselines_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} sum_owd_baselines_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( dl_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} dl_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + + if (( ul_owd_delta_ewma_delta_us > reflector_owd_delta_ewma_delta_thr_us )) + then + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} ul_owd_delta_ewma_us exceeds the minimum by set threshold." + replace_pinger_reflector "${pinger}" + continue 2 + fi + done + + fi + + replace_pinger_reflector_enabled=1 + + for ((pinger=0; pinger < no_pingers; pinger++)) + do + # shellcheck disable=SC2178 + declare -n reflector_offences="reflector_${pinger}_offences" + + (( reflector_offences[reflector_offences_idx] )) && ((sum_reflector_offences[pinger]--)) + # shellcheck disable=SC2154 + reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) + + if (( reflector_offences[reflector_offences_idx] )) + then + ((sum_reflector_offences[pinger]++)) + log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" + log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" + fi + + if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )) + then + + log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." + if ((replace_pinger_reflector_enabled)) + then + replace_pinger_reflector "${pinger}" + replace_pinger_reflector_enabled=0 + else + log_msg "DEBUG" "Warning: skipping replacement of reflector: ${reflectors[pinger]} given prior replacement within this reflector health check cycle." + fi + fi + done + ((reflector_offences_idx=(reflector_offences_idx+1)%reflector_misbehaving_detection_window)) + ;; + *) + log_msg "ERROR" "Unrecognized maintain pingers state: ${maintain_pingers_state}." + log_msg "ERROR" "Setting state to RUNNING" + maintain_pingers_next_state="RUNNING" + change_maintain_pingers_state + ;; + esac + + sleep_remaining_tick_time "${t_start_us}" "${reflector_health_check_interval_us}" + done +} + +set_shaper_rate() +{ + # fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction + + local direction="${1}" # 'dl' or 'ul' + + if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] )) + then + ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit" + + if ((adjust_shaper_rate["${direction}"])) + then + tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null + else + ((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call." + fi + + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}" + last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}" + + update_max_wire_packet_compensation + fi +} + +set_min_shaper_rates() +{ + log_msg "DEBUG" "Enforcing minimum shaper rates." + shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} + shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} + set_shaper_rate "dl" + set_shaper_rate "ul" +} + +get_max_wire_packet_size_bits() +{ + local interface="${1}" + local -n max_wire_packet_size_bits="${2}" + + read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu" + [[ $(tc qdisc show dev "${interface}") =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]] + max_wire_packet_size_bits=$(( 8*(max_wire_packet_size_bits+BASH_REMATCH[2]) )) + # atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits + [[ "${BASH_REMATCH[1]:-}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*((max_wire_packet_size_bits+376)/384) )) +} + +update_max_wire_packet_compensation() +{ + # Compensate for delays imposed by active traffic shaper + # This will serve to increase the delay thr at rates below around 12Mbit/s + + # compensated OWD delay thresholds in microseconds + compensated_dl_delay_thr_us=$(( dl_delay_thr_us + (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] )) + compensated_ul_delay_thr_us=$(( ul_delay_thr_us + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) + + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + printf "SET_VAR compensated_dl_delay_thr_us %s\n" "${compensated_dl_delay_thr_us}" >&"${maintain_pingers_fd}" + + max_wire_packet_rtt_us=$(( (1000*dl_max_wire_packet_size_bits)/shaper_rate_kbps[dl] + (1000*ul_max_wire_packet_size_bits)/shaper_rate_kbps[ul] )) + + printf "SET_VAR max_wire_packet_rtt_us %s\n" "${max_wire_packet_rtt_us}" >&"${maintain_pingers_fd}" +} + +verify_ifs_up() +{ + # Check the rx/tx paths exist and give extra time for ifb's to come up if needed + # This will block if ifs never come up + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + while [[ ! -f ${rx_bytes_path} || ! -f ${tx_bytes_path} ]] + do + [[ ! -f ${rx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured download interface: '${dl_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + [[ ! -f ${tx_bytes_path} ]] && log_msg "DEBUG" "Warning: The configured upload interface: '${ul_if}' does not appear to be present. Waiting ${if_up_check_interval_s} seconds for the interface to come up." + sleep_s "${if_up_check_interval_s}" + done +} + +ewma_iteration() +{ + local value="${1}" + local alpha="${2}" # alpha must be scaled by factor of 1000000 + local -n ewma="${3}" + + prev_ewma=${ewma} + ewma=$(( (alpha*value+(1000000-alpha)*prev_ewma)/1000000 )) +} + +change_state_main() +{ + local main_next_state="${1}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + case ${main_next_state} in + + RUNNING|IDLE|STALL) + + if [[ "${main_state}" != "${main_next_state}" ]] + then + log_msg "DEBUG" "Changing main state from: ${main_state} to: ${main_next_state}" + main_state=${main_next_state} + else + log_msg "ERROR" "Received request to change main state to existing state." + fi + ;; + + *) + + log_msg "ERROR" "Received unrecognized main state change request: ${main_next_state}. Exiting now." + kill $$ 2>/dev/null + ;; + esac +} + +intercept_stderr() +{ + # send stderr to log_msg and exit cake-autorate + # use with redirection: exec 2> >(intercept_stderr) + + while read -r error + do + log_msg "ERROR" "${error}" + kill $$ 2>/dev/null + done +} + +# Debug command wrapper +# Inspired by cmd_wrapper of sqm-script +debug_cmd() +{ + # Usage: debug_cmd debug_msg err_silence cmd arg1 arg2, etc. + + # Error messages are output as log_msg ERROR messages + # Or set error_silence=1 to output errors as log_msg DEBUG messages + + local debug_msg="${1}" + local err_silence="${2}" + local cmd="${3}" + + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + + shift 3 + + local args=("${@}") + + local caller_id + local err_type + + local ret + local stderr + + err_type="ERROR" + + if ((err_silence)) + then + err_type="DEBUG" + fi + + stderr=$(${cmd} "${args[@]}" 2>&1) + ret=${?} + + caller_id=$(caller) + + if ((ret==0)) + then + log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" + else + [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR + + log_msg "${err_type}" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=FAILURE (${ret})" + log_msg "${err_type}" "debug_cmd: LAST ERROR (${stderr})" + + frame=1 + while caller_output=$(caller "${frame}") + do + log_msg "${err_type}" "debug_cmd: CALL CHAIN: ${caller_output}" + ((++frame)) + done + fi +} + +# shellcheck disable=SC1090,SC2311 +validate_config_entry() { + # Must be called before loading config_path into the global scope. + # + # When the entry is invalid, two types are returned with the first type + # being the invalid user type and second type is the default type with + # the user needing to adapt the config file so that the entry uses the + # default type. + # + # When the entry is valid, one type is returned and it will be the + # the type of either the default or user type. However because in that + # case they are both valid. It doesn't matter as they'd both have the + # same type. + + local config_path="${1}" + + local user_type + local valid_type + + user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}") + valid_type=$(typeof "${2}") + + if [[ "${user_type}" != "${valid_type}" ]] + then + printf '%s' "${user_type} ${valid_type}" + return + elif [[ "${user_type}" != "string" ]] + then + printf '%s' "${valid_type}" + return + fi + + # extra validation for string, check for empty string + local -n default_value=${2} + local user_value + user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}") + + # if user is empty but default is not, invalid entry + if [[ -z "${user_value}" && -n "${default_value}" ]] + then + printf '%s' "${user_type} ${valid_type}" + else + printf '%s' "${valid_type}" + fi +} + +# ======= Start of the Main Routine ======== + +[[ -t 1 ]] && terminal=1 || terminal=0 + +type logger &> /dev/null && use_logger=1 || use_logger=0 # only perform the test once. + +log_file_path=/var/log/cake-autorate.log + +# *** WARNING: take great care if attempting to alter the run_path! *** +# *** cake-autorate issues mkdir -p ${run_path} and rm -r ${run_path} on exit. *** +run_path=/var/run/cake-autorate/ + +# cake-autorate first argument is config file path +if [[ -n "${1-}" ]] +then + config_path="${1}" +else + config_path="${PREFIX}/config.primary.sh" +fi + +if [[ ! -f "${config_path}" ]] +then + log_msg "ERROR" "No config file found. Exiting now." + exit 1 +fi + +# validate config entries before loading +mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') +config_error_count=0 +for key in "${user_config[@]}" +do + # Despite the fact that config_file_check is no longer required, + # we make an exemption just in this case as that variable in + # particular does not have any real impact to the operation + # of the script. + [[ "${key}" == "config_file_check" ]] && continue + + # shellcheck disable=SC2076 + if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]] + then + ((config_error_count++)) + log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry." + else + # shellcheck disable=SC2311 + read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")" + if [[ -n "${supposed}" ]] + then + error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'." + + case "${user}" in + negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;; + *) ;; + esac + + log_msg "ERROR" "${error_msg}" + unset error_msg + + ((config_error_count++)) + fi + unset user supposed + fi +done +if ((config_error_count)) +then + log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now." + exit 1 +fi +unset valid_config_entries user_config config_error_count key + +# shellcheck source=config.primary.sh +. "${config_path}" + +if [[ ${config_path} =~ config\.(.*)\.sh ]] +then + instance_id="${BASH_REMATCH[1]}" + run_path="/var/run/cake-autorate/${instance_id}" +else + log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now." + exit 1 +fi + +if [[ -n "${log_file_path_override-}" ]] +then + if [[ ! -d ${log_file_path_override} ]] + then + broken_log_file_path_override=${log_file_path_override} + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log + log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." + exit + fi + log_file_path=${log_file_path_override}/cake-autorate${instance_id:+.${instance_id}}.log +else + log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log +fi + +rotate_log_file # rotate here to force header prints at top of log file + +# save stderr fd, redirect stderr to intercept_stderr +# intercept_stderr sends stderr to log_msg and exits cake-autorate +exec {original_stderr_fd}>&2 2> >(intercept_stderr) + +proc_pids['intercept_stderr']=${!} + +log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +# ${run_path}/ is used to store temporary files +# it should not exist on startup so if it does exit, else create the directory +if [[ -d "${run_path}" ]] +then + if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] + then + log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." + trap - INT TERM EXIT + exit + else + log_msg "DEBUG" "${run_path} already exists but no instance is running. Removing and recreating." + rm -r "${run_path}" + mkdir -p "${run_path}" + fi +else + mkdir -p "${run_path}" +fi + +proc_pids['main']="${BASHPID}" + +no_reflectors=${#reflectors[@]} + +# Check ping binary exists +command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } + +# Check no_pingers <= no_reflectors +(( no_pingers > no_reflectors )) && { log_msg "ERROR" "number of pingers cannot be greater than number of reflectors. Exiting script."; exit; } + +# Check dl/if interface not the same +[[ "${dl_if}" == "${ul_if}" ]] && { log_msg "ERROR" "download interface and upload interface are both set to: '${dl_if}', but cannot be the same. Exiting script."; exit; } + +# Check bufferbloat detection threshold not greater than window length +(( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } + +# Passed error checks + +if ((log_to_file)) +then + log_file_max_time_us=$((log_file_max_time_mins*60000000)) + log_file_max_size_bytes=$((log_file_max_size_KB*1024)) + exec {log_fd}<> <(:) + maintain_log_file & + proc_pids['maintain_log_file']=${!} +fi + +# test if stdout is a tty (terminal) +if ! ((terminal)) +then + echo "stdout not a terminal so redirecting output to: ${log_file_path}" + ((log_to_file)) && exec 1>&"${log_fd}" +fi + +# Initialize rx_bytes_path and tx_bytes_path if not set +if [[ -z "${rx_bytes_path-}" ]] +then + case "${dl_if}" in + veth*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + ifb*) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + *) + rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" + ;; + esac +fi +if [[ -z "${tx_bytes_path-}" ]] +then + case "${ul_if}" in + veth*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + ifb*) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" + ;; + *) + tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes" + ;; + esac +fi + +if ((debug)) +then + log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" + log_msg "DEBUG" "config_path: ${config_path}" + log_msg "DEBUG" "run_path: ${run_path}" + log_msg "DEBUG" "log_file_path: ${log_file_path}" + log_msg "DEBUG" "pinger_binary:${pinger_binary}" + log_msg "DEBUG" "download interface: ${dl_if} (${min_dl_shaper_rate_kbps} / ${base_dl_shaper_rate_kbps} / ${max_dl_shaper_rate_kbps})" + log_msg "DEBUG" "upload interface: ${ul_if} (${min_ul_shaper_rate_kbps} / ${base_ul_shaper_rate_kbps} / ${max_ul_shaper_rate_kbps})" + log_msg "DEBUG" "rx_bytes_path: ${rx_bytes_path}" + log_msg "DEBUG" "tx_bytes_path: ${tx_bytes_path}" +fi + +# Check interfaces are up and wait if necessary for them to come up +verify_ifs_up + +# Initialize variables + +# Convert human readable parameters to values that work with integer arithmetic + +printf -v dl_delay_thr_us %.0f "${dl_delay_thr_ms}e3" +printf -v ul_delay_thr_us %.0f "${ul_delay_thr_ms}e3" +printf -v alpha_baseline_increase %.0f "${alpha_baseline_increase}e6" +printf -v alpha_baseline_decrease %.0f "${alpha_baseline_decrease}e6" +printf -v alpha_delta_ewma %.0f "${alpha_delta_ewma}e6" +printf -v achieved_rate_adjust_down_bufferbloat %.0f "${achieved_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_down_bufferbloat %.0f "${shaper_rate_adjust_down_bufferbloat}e3" +printf -v shaper_rate_adjust_up_load_high %.0f "${shaper_rate_adjust_up_load_high}e3" +printf -v shaper_rate_adjust_down_load_low %.0f "${shaper_rate_adjust_down_load_low}e3" +printf -v shaper_rate_adjust_up_load_low %.0f "${shaper_rate_adjust_up_load_low}e3" +printf -v high_load_thr_percent %.0f "${high_load_thr}e2" +printf -v reflector_ping_interval_ms %.0f "${reflector_ping_interval_s}e3" +printf -v reflector_ping_interval_us %.0f "${reflector_ping_interval_s}e6" +printf -v reflector_health_check_interval_us %.0f "${reflector_health_check_interval_s}e6" +printf -v monitor_achieved_rates_interval_us %.0f "${monitor_achieved_rates_interval_ms}e3" +printf -v sustained_idle_sleep_thr_us %.0f "${sustained_idle_sleep_thr_s}e6" +printf -v reflector_response_deadline_us %.0f "${reflector_response_deadline_s}e6" +printf -v reflector_sum_owd_baselines_delta_thr_us %.0f "${reflector_sum_owd_baselines_delta_thr_ms}e3" +printf -v reflector_owd_delta_ewma_delta_thr_us %.0f "${reflector_owd_delta_ewma_delta_thr_ms}e3" +printf -v startup_wait_us %.0f "${startup_wait_s}e6" +printf -v global_ping_response_timeout_us %.0f "${global_ping_response_timeout_s}e6" +printf -v bufferbloat_refractory_period_us %.0f "${bufferbloat_refractory_period_ms}e3" +printf -v decay_refractory_period_us %.0f "${decay_refractory_period_ms}e3" + +for (( i=0; i<${#sss_times_s[@]}; i++ )); +do + printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6" +done +printf -v sss_compensation_pre_duration_us %.0f "${sss_compensation_pre_duration_ms}e3" +printf -v sss_compensation_post_duration_us %.0f "${sss_compensation_post_duration_ms}e3" + +ping_response_interval_us=$(( reflector_ping_interval_us/no_pingers )) +ping_response_interval_ms=$(( ping_response_interval_us/1000 )) + +stall_detection_timeout_us=$(( stall_detection_thr*ping_response_interval_us )) +stall_detection_timeout_s=000000${stall_detection_timeout_us} +stall_detection_timeout_s=$(( 10#${stall_detection_timeout_s::-6})).${stall_detection_timeout_s: -6} + +declare -A bufferbloat_detected +declare -A load_percent +declare -A load_condition +declare -A t_last_bufferbloat_us +declare -A t_last_decay_us +declare -A shaper_rate_kbps +declare -A last_shaper_rate_kbps +declare -A base_shaper_rate_kbps +declare -A min_shaper_rate_kbps +declare -A max_shaper_rate_kbps +declare -A interface +declare -A adjust_shaper_rate + +base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +min_shaper_rate_kbps[dl]="${min_dl_shaper_rate_kbps}" +min_shaper_rate_kbps[ul]="${min_ul_shaper_rate_kbps}" + +max_shaper_rate_kbps[dl]="${max_dl_shaper_rate_kbps}" +max_shaper_rate_kbps[ul]="${max_ul_shaper_rate_kbps}" + +shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" +shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" + +last_shaper_rate_kbps[dl]=0 +last_shaper_rate_kbps[ul]=0 + +interface[dl]="${dl_if}" +interface[ul]="${ul_if}" + +adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}" +adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}" + +dl_max_wire_packet_size_bits=0 +ul_max_wire_packet_size_bits=0 +get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits +get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits + +set_shaper_rate "dl" +set_shaper_rate "ul" + +update_max_wire_packet_compensation + +main_state="RUNNING" + +t_start_us="${EPOCHREALTIME/./}" +t_end_us="${EPOCHREALTIME/./}" + +t_last_bufferbloat_us[dl]="${t_start_us}" +t_last_bufferbloat_us[ul]="${t_start_us}" +t_last_decay_us[dl]="${t_start_us}" +t_last_decay_us[ul]="${t_start_us}" + +t_sustained_connection_idle_us=0 +reflectors_last_timestamp_us="${EPOCHREALTIME/./}" + +mapfile -t dl_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) +mapfile -t ul_delays < <(for ((i=1; i <= bufferbloat_detection_window; i++)); do echo 0; done) + +delays_idx=0 +sum_dl_delays=0 +sum_ul_delays=0 + +if ((debug)) +then + if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )) + then + log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." + log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." + log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." + fi + if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )) + then + log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" + log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." + fi +fi + +# Randomize reflectors array providing randomize_reflectors set to 1 +((randomize_reflectors)) && randomize_array reflectors + +# Wait if ${startup_wait_s} > 0 +if ((startup_wait_us>0)) +then + log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." + sleep_us "${startup_wait_us}" +fi + +case "${pinger_binary}" in + + tsping|fping) + exec {pinger_fds[0]}<> <(:) + ;; + + ping) + for ((pinger=0; pinger<=no_pingers; pinger++)) + do + exec {pinger_fds[pinger]}<> <(:) + done + ;; + + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit + ;; +esac + +monitor_achieved_rates "${rx_bytes_path}" "${tx_bytes_path}" "${monitor_achieved_rates_interval_us}" & +proc_pids['monitor_achieved_rates']="${!}" + +maintain_pingers & +proc_pids['maintain_pingers']="${!}" + +generate_log_file_scripts + +log_msg "INFO" "Started cake-autorate with PID: ${BASHPID} and config: ${config_path}" + +while true +do + unset command + read -r -u "${main_fd}" -a command + + if [[ "${command-}" ]] + then + + case "${command[0]}" in + + REFLECTOR_RESPONSE) + + read -r timestamp reflector seq dl_owd_baseline_us dl_owd_us dl_owd_delta_ewma_us dl_owd_delta_us ul_owd_baseline_us ul_owd_us ul_owd_delta_ewma_us ul_owd_delta_us <<< "${command[@]:1}" + ;; + + SET_VAR) + if [[ "${#command[@]}" -eq 3 ]] + then + export -n "${command[1]}=${command[2]}" + fi + ;; + SET_ARRAY_ELEMENT) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; + SET_PROC_PID) + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + true > "${run_path}/proc_pids" + for proc_pid in "${!proc_pids[@]}" + do + printf "%s=%s\n" "${proc_pid}" "${proc_pids[${proc_pid}]}" >> "${run_path}/proc_pids" + done + ;; + *) + ;; + esac + + fi + case "${main_state}" in + + RUNNING) + + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" && "${reflector-}" && "${seq-}" && "${dl_owd_baseline_us-}" && "${dl_owd_us-}" && "${dl_owd_delta_ewma_us-}" && "${dl_owd_delta_us-}" && "${ul_owd_baseline_us-}" && "${ul_owd_us-}" && "${ul_owd_delta_ewma_us-}" && "${ul_owd_delta_us-}" ]] + then + + t_start_us=${EPOCHREALTIME/./} + + reflectors_last_timestamp_us="${timestamp//[.]}" + + if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )) + then + log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." + continue + fi + + # Keep track of number of delays across detection window + # .. for download: + (( dl_delays[delays_idx] )) && ((sum_dl_delays--)) + dl_delays[delays_idx]=$(( dl_owd_delta_us > compensated_dl_delay_thr_us ? 1 : 0 )) + ((dl_delays[delays_idx])) && ((sum_dl_delays++)) + # .. for upload + (( ul_delays[delays_idx] )) && ((sum_ul_delays--)) + ul_delays[delays_idx]=$(( ul_owd_delta_us > compensated_ul_delay_thr_us ? 1 : 0 )) + ((ul_delays[delays_idx])) && ((sum_ul_delays++)) + # .. and move index on + (( delays_idx=(delays_idx+1)%bufferbloat_detection_window )) + + bufferbloat_detected[dl]=$(( sum_dl_delays >= bufferbloat_detection_thr ? 1 : 0 )) + bufferbloat_detected[ul]=$(( sum_ul_delays >= bufferbloat_detection_thr ? 1 : 0 )) + + load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) + load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) + + classify_load "dl" + classify_load "ul" + + update_shaper_rate "dl" + update_shaper_rate "ul" + + set_shaper_rate "dl" + set_shaper_rate "ul" + + if (( output_processing_stats )) + then + printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" + log_msg "DATA" "${processing_stats}" + fi + + # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) + if (( enable_sleep_function )) + then + if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]] + then + ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) + if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) + then + change_state_main "IDLE" + + log_msg "DEBUG" "Connection idle. Waiting for minimum load." + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + + # update maintain_pingers state + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + + # reset idle timer + t_sustained_connection_idle_us=0 + fi + else + # reset timer + t_sustained_connection_idle_us=0 + fi + fi + elif (( (${EPOCHREALTIME/./} - reflectors_last_timestamp_us) > stall_detection_timeout_us )) + then + + log_msg "DEBUG" "Warning: no reflector response within: ${stall_detection_timeout_s} seconds. Checking loads." + + log_msg "DEBUG" "load check is: (( ${achieved_rate_kbps[dl]} kbps > ${connection_stall_thr_kbps} kbps for download && ${achieved_rate_kbps[ul]} kbps > ${connection_stall_thr_kbps} kbps for upload ))" + + # non-zero load so despite no reflector response within stall interval, the connection not considered to have stalled + # and therefore resume normal operation + if (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then + + log_msg "DEBUG" "load above connection stall threshold so resuming normal operation." + else + change_state_main "STALL" + + printf "CHANGE_STATE PAUSED\n" >&"${maintain_pingers_fd}" + + t_connection_stall_time_us="${EPOCHREALTIME//.}" + global_ping_response_timeout=0 + fi + + fi + + t_end_us="${EPOCHREALTIME/./}" + + ;; + IDLE) + if (( achieved_rate_kbps[dl] > connection_active_thr_kbps || achieved_rate_kbps[ul] > connection_active_thr_kbps )) + then + log_msg "DEBUG" "dl achieved rate: ${achieved_rate_kbps[dl]} kbps or ul achieved rate: ${achieved_rate_kbps[ul]} kbps exceeded connection active threshold: ${connection_active_thr_kbps} kbps. Resuming normal operation." + change_state_main "RUNNING" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" + t_sustained_connection_idle_us=0 + # Give some time to enable pingers to get set up + reflectors_last_timestamp_us=$(( "${EPOCHREALTIME/./}" + 2*reflector_ping_interval_us )) + fi + ;; + STALL) + + [[ "${command[0]}" == "REFLECTOR_RESPONSE" && "${timestamp-}" ]] && reflectors_last_timestamp_us=${timestamp//[.]} + + if [[ "${command[0]}" == "REFLECTOR_RESPONSE" ]] || (( achieved_rate_kbps[dl] > connection_stall_thr_kbps && achieved_rate_kbps[ul] > connection_stall_thr_kbps )) + then + + log_msg "DEBUG" "Connection stall ended. Resuming normal operation." + printf "CHANGE_STATE RUNNING\n" >&"${maintain_pingers_fd}" + change_state_main "RUNNING" + + fi + + if (( global_ping_response_timeout==0 && ${EPOCHREALTIME/./} > (t_connection_stall_time_us + global_ping_response_timeout_us - stall_detection_timeout_us) )) + then + global_ping_response_timeout=1 + ((min_shaper_rates_enforcement)) && set_min_shaper_rates + log_msg "SYSLOG" "Warning: Configured global ping response timeout: ${global_ping_response_timeout_s} seconds exceeded." + log_msg "DEBUG" "Restarting pingers." + printf "CHANGE_STATE STOP\n" >&"${maintain_pingers_fd}" + printf "CHANGE_STATE START\n" >&"${maintain_pingers_fd}" + fi + ;; + *) + + log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." + exit 1 + ;; + esac + +done diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh new file mode 100755 index 000000000..509dee635 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# config.sh sets up defaults for CAKE-autorate + +# config.sh is a part of CAKE-autorate +# CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) +# Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: +# * Get configuration via uci + +INTERFACE=$1 + +# *** OUTPUT OPTIONS *** + +#output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats +output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo "0") +#output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo "0") +#debug=0 # enable (1) or disable (0) out of debug lines +#debug=$(uci -q get sqm.common.debug || echo "0") +debug=1 + +# *** STANDARD CONFIGURATION OPTIONS *** + +#dl_if=ifb4eth1 # download interface +#dl_if=$(uci -q get sqm.${INTERFACE}.download_interface) +dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) +#ul_if=eth1 # upload interface +#ul_if=$(uci -q get sqm.${INTERFACE}.upload_interface) +ul_if=$(uci -q get sqm.${INTERFACE}.interface) + +#reflector_ping_interval_s=0.2 # (seconds, e.g. 0.2s or 2s) +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.2") + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +#reflectors=("1.1.1.1" "1.0.0.1" "8.8.8.8" "8.8.4.4" "9.9.9.9" "9.9.9.10") +reflectors=($(uci get omr-tracker.defaults.hosts)) +no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") + +# delay threshold in ms is the extent of RTT increase to classify as a delay +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +#delay_thr_ms=25 # (milliseconds) +delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "25") + +#min_dl_shaper_rate_kbps=10000 # minimum bandwidth for download (Kbit/s) +min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download) +#base_dl_shaper_rate_kbps=100000 # steady state bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download) +#max_dl_shaper_rate_kbps=200000 # maximum bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download) + +#min_ul_shaper_rate_kbps=10000 # minimum bandwidth for upload (Kbit/s) +min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload) +#base_ul_shaper_rate_kbps=100000 # steady state bandwidth for upload (KBit/s) +base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload) +#max_ul_shaper_rate_kbps=200000 # maximum bandwidth for upload (Kbit/s) +max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +#enable_sleep_function=1 # enable (1) or disable (0) sleep functonality +enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") +#connection_active_thr_kbps=500 # threshold in Kbit/s below which dl/ul is considered idle +connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kbps || echo "500") +#sustained_idle_sleep_thr_s=60 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) +sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.substained_idle_sleep_thr_s || echo "60") + +#startup_wait_s=0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) +startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60") + +# *** ADVANCED CONFIGURATION OPTIONS *** + +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=100 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=4 # number of samples to retain in detection window +bufferbloat_detection_thr=2 # number of delayed samples for bufferbloat detection + +# RTT baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +# and held the same on load medium +achieved_rate_adjust_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_load_low=0.98 # how rapidly to return to base shaper rate upon idle or low load detected + +# the load is categoried as low if < medium_load_thr, medium if > medium_load_thr and high if > high_load_thr relative to the current shaper rate +medium_load_thr=0.25 # % of currently set bandwidth for detecting medium load +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state) + diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh new file mode 100755 index 000000000..04a366a63 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh @@ -0,0 +1,214 @@ +#!/bin/bash + +# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# cake-autorate_config.sh is a script that sets up defaults for cake-autorate + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +INTERFACE=$(basename "$1" | cut -d. -f2) + +#cake_autorate_version="2.0.0" + +# *** OUTPUT AND LOGGING OPTIONS *** + +output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads +output_reflector_stats=$(uci -q get sqm.${INTERFACE}.output_reflector_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing reflector stats +output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines + +# This can generate a LOT of records so be careful: +log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. + +# ** Take care with these settings to ensure you won't run into OOM issues on your router *** +# every write the cumulative write time and bytes associated with each log line are checked +# and if either exceeds the configured values below, the log log file is rotated +log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) +log_file_max_time_mins=10000 # maximum time between log file rotations +log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations + +# log file path defaults to /var/log/ +# or, if set below, then ${log_file_path_override} +log_file_path_override="" + +# *** STANDARD CONFIGURATION OPTIONS *** + +### For multihomed setups, it is the responsibility of the user to ensure that the probes +### sent by this instance of cake-autorate actually travel through these interfaces. +### See ping_extra_args and ping_prefix_string + +dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) # download interface +ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface + +# pinger selection can be any of: +# fping - round robin pinging (rtts) +# ping - (iputils-ping) individual pinging (rtts) +# hping3 - individidual pinging (owds) +pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping') + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +#reflectors=$(uci -q get omr-tracker.defaults.hosts) +reflectors=( +"1.1.1.1" "1.0.0.1" # Cloudflare +"8.8.8.8" "8.8.4.4" # Google +"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +"185.228.168.9" "185.228.168.10" # CleanBrowsing +) + +randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup + +# Think carefully about the following settings +# to avoid excessive CPU use (proportional with ping interval / number of pingers) +# and to avoid abusive network activity (excessive ICMP frequency to one reflector) +# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G +no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") # number of pingers to maintain +reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.5") # (seconds, e.g. 0.2s or 2s) + +# delay threshold in ms is the extent of OWD increase to classify as a delay +# these are automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) || $(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo 100 # (milliseconds) +ul_delay_thr_ms=${dl_delay_thr_ms} + +# Set either of the below to 0 to adjust one direction only +# or alternatively set both to 0 to simply use cake-autorate to monitor a connection +adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate +adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate + +min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download || echo "5000") # minimum bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download || echo "40000") # steady state bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download || echo "80000") # maximum bandwidth for download (Kbit/s) + +min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload || echo "5000") # minimum bandwidth for upload (Kbit/s) +base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload || echo "20000") # steady state bandwidth for upload (KBit/s) +max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload || echo "35000") # maximum bandwidth for upload (Kbit/s) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") # enable (1) or disable (0) sleep functonality +connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kpbs || echo "1000") # threshold in Kbit/s below which dl/ul is considered idle +sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.sustained_idle_sleep_thr || echo "150.0") # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) + +min_shaper_rates_enforcement=$(uci -q get sqm.${INTERFACE}.min_shaper_rates_enforcement || echo "0") # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall + +startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "0.0") # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) + +# *** ADVANCED CONFIGURATION OPTIONS *** + +log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename + +### In multi-homed setups, it is mandatory to use either ping_extra_args +### or ping_prefix_string to direct the pings through $dl_if and $ul_if. +### No universal recommendation exists, because there are multiple +### policy-routing packages available (e.g. vpn-policy-routing and mwan3). +### Typically they either react to a firewall mark set on the pings, or +### provide a convenient wrapper. +### +### In a traditional single-homed setup, there is usually no need for these parameters. +### +### These arguments can also be used for any other purpose - e.g. for setting a +### particular QoS mark. + +# extra arguments for ping or fping +# e.g., here is how you can set the correct outgoing interface and +# the firewall mark for ping: +# ping_extra_args="-I wwan0 -m $((0x300))" +# Unfortunately, fping does not offer a command line switch to set +# the firewall mark. +# WARNING: no error checking so use at own risk! +#ping_extra_args="-B -I ${INTERFACE}" +ping_extra_args="-i ${ul_if} -e" + +# a wrapper for ping binary - used as a prefix for the real command +# e.g., when using mwan3, it is recommended to set it like this: +# ping_prefix_string="mwan3 use gpon exec" +# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. +# Running ping or fping as a subprocess will lead to problems stopping it. +# WARNING: no error checking - so use at own risk! +ping_prefix_string="" +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=200 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=6 # number of samples to retain in detection window +bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection + +# OWD baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# OWD delta from baseline is tracked using ewma with alpha set below +alpha_delta_ewma=0.095 + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected +shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected + +# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +# the bufferbloat refractory period should be greater than the +# average time it would take to replace the bufferbloat +# detection window with new samples upon a bufferbloat event +bufferbloat_refractory_period_ms=2000 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1.0 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=2.0 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list + +reflector_comparison_interval_mins=1 # how often to compare reflectors +#reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated + +# stall is detected when the following two conditions are met: +# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and +# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr +stall_detection_thr=5 +connection_stall_thr_kbps=10 + +global_ping_response_timeout_s=100.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) + +# Starlink satellite switch (sss) compensation options +sss_compensation=$(uci -q get sqm.${INTERFACE}.sss_compensation || echo "0") # enable (1) or disable (0) Starlink handling +# satellite switch compensation start times in seconds of each minute +sss_times_s=("12.0" "27.0" "42.0" "57.0") +sss_compensation_pre_duration_ms=300 +sss_compensation_post_duration_ms=200 + +config_file_check="cake-autorate" \ No newline at end of file diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh new file mode 100755 index 000000000..1ef1af429 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh @@ -0,0 +1,209 @@ +#!/bin/bash + +# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT + +# cake-autorate_config.sh is a script that sets up defaults for cake-autorate + +# Author: @Lynx (OpenWrt forum) +# Inspiration taken from: @moeller0 (OpenWrt forum) + +INTERFACE="" + +# *** OUTPUT AND LOGGING OPTIONS *** + +output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats +output_load_stats=1 # enable (1) or disable (0) output monitoring lines showing achieved loads +output_reflector_stats=1 # enable (1) or disable (0) output monitoring lines showing reflector stats +output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes +debug=1 # enable (1) or disable (0) out of debug lines + +# This can generate a LOT of records so be careful: +log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log. + +# ** Take care with these settings to ensure you won't run into OOM issues on your router *** +# every write the cumulative write time and bytes associated with each log line are checked +# and if either exceeds the configured values below, the log log file is rotated +log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log) +log_file_max_time_mins=10 # maximum time between log file rotations +log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations + +# log file path defaults to /var/log/ +# or, if set below, then ${log_file_path_override} +log_file_path_override="" + +# *** STANDARD CONFIGURATION OPTIONS *** + +### For multihomed setups, it is the responsibility of the user to ensure that the probes +### sent by this instance of cake-autorate actually travel through these interfaces. +### See ping_extra_args and ping_prefix_string + +dl_if=ifb-wan # download interface +ul_if=wan # upload interface + +# pinger selection can be any of: +# fping - round robin pinging (rtts) +# ping - (iputils-ping) individual pinging (rtts) +# hping3 - individidual pinging (owds) +pinger_binary=fping + +# list of reflectors to use and number of pingers to initiate +# pingers will be initiated with reflectors in the order specified in the list +# additional reflectors will be used to replace any reflectors that go stale +# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially +# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad +# a bad reflector will go to the back of the queue on reflector rotation +reflectors=( +"1.1.1.1" "1.0.0.1" # Cloudflare +"8.8.8.8" "8.8.4.4" # Google +"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9 +"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard +"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar +"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS +"185.228.168.9" "185.228.168.10" # CleanBrowsing +) + +randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup + +# Think carefully about the following settings +# to avoid excessive CPU use (proportional with ping interval / number of pingers) +# and to avoid abusive network activity (excessive ICMP frequency to one reflector) +# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G +no_pingers=6 # number of pingers to maintain +reflector_ping_interval_s=0.3 # (seconds, e.g. 0.2s or 2s) + +# delay threshold in ms is the extent of OWD increase to classify as a delay +# these are automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +dl_delay_thr_ms=30 # (milliseconds) +ul_delay_thr_ms=30 # (milliseconds) + +# Set either of the below to 0 to adjust one direction only +# or alternatively set both to 0 to simply use cake-autorate to monitor a connection +adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate +adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate + +min_dl_shaper_rate_kbps=5000 # minimum bandwidth for download (Kbit/s) +base_dl_shaper_rate_kbps=20000 # steady state bandwidth for download (Kbit/s) +max_dl_shaper_rate_kbps=80000 # maximum bandwidth for download (Kbit/s) + +min_ul_shaper_rate_kbps=5000 # minimum bandwidth for upload (Kbit/s) +base_ul_shaper_rate_kbps=20000 # steady state bandwidth for upload (KBit/s) +max_ul_shaper_rate_kbps=35000 # maximum bandwidth for upload (Kbit/s) + +# sleep functionality saves unecessary pings and CPU cycles by +# pausing all active pingers when connection is not in active use +enable_sleep_function=1 # enable (1) or disable (0) sleep functonality +connection_active_thr_kbps=1000 # threshold in Kbit/s below which dl/ul is considered idle +sustained_idle_sleep_thr_s=60.0 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) + +min_shaper_rates_enforcement=0 # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall + +startup_wait_s=0.0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) + +# *** ADVANCED CONFIGURATION OPTIONS *** + +log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename + +### In multi-homed setups, it is mandatory to use either ping_extra_args +### or ping_prefix_string to direct the pings through $dl_if and $ul_if. +### No universal recommendation exists, because there are multiple +### policy-routing packages available (e.g. vpn-policy-routing and mwan3). +### Typically they either react to a firewall mark set on the pings, or +### provide a convenient wrapper. +### +### In a traditional single-homed setup, there is usually no need for these parameters. +### +### These arguments can also be used for any other purpose - e.g. for setting a +### particular QoS mark. + +# extra arguments for ping or fping +# e.g., here is how you can set the correct outgoing interface and +# the firewall mark for ping: +# ping_extra_args="-I wwan0 -m $((0x300))" +# Unfortunately, fping does not offer a command line switch to set +# the firewall mark. +# WARNING: no error checking so use at own risk! +ping_extra_args="" + +# a wrapper for ping binary - used as a prefix for the real command +# e.g., when using mwan3, it is recommended to set it like this: +# ping_prefix_string="mwan3 use gpon exec" +# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess. +# Running ping or fping as a subprocess will lead to problems stopping it. +# WARNING: no error checking - so use at own risk! +ping_prefix_string="" + +# interval in ms for monitoring achieved rx/tx rates +# this is automatically adjusted based on maximum on the wire packet size +# (adjustment significant at sub 12Mbit/s rates, else negligible) +monitor_achieved_rates_interval_ms=200 # (milliseconds) + +# bufferbloat is detected when (bufferbloat_detection_thr) samples +# out of the last (bufferbloat detection window) samples are delayed +bufferbloat_detection_window=6 # number of samples to retain in detection window +bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection + +# OWD baseline against which to measure delays +# the idea is that the baseline is allowed to increase slowly to allow for path changes +# and slowly enough such that bufferbloat will be corrected well before the baseline increases, +# but it will decrease very rapidly to ensure delays are measured against the shortest path +alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase +alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease + +# OWD delta from baseline is tracked using ewma with alpha set below +alpha_delta_ewma=0.095 + +# rate adjustment parameters +# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate +# to exploit that transfer rates during bufferbloat provide an indication of line capacity +# otherwise shaper rate is adjusted up on load high, and down on load idle or low +achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat +shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat +shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected +shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected +shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected + +# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate +high_load_thr=0.75 # % of currently set bandwidth for detecting high load + +# refractory periods between successive bufferbloat/decay rate changes +# the bufferbloat refractory period should be greater than the +# average time it would take to replace the bufferbloat +# detection window with new samples upon a bufferbloat event +bufferbloat_refractory_period_ms=300 # (milliseconds) +decay_refractory_period_ms=1000 # (milliseconds) + +# interval for checking reflector health +reflector_health_check_interval_s=1.0 # (seconds) +# deadline for reflector response not to be classified as an offence against reflector +reflector_response_deadline_s=1.0 # (seconds) + +# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples +# out of the last (reflector misbehaving detection window) samples are offences +# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to +# 3 offences within the last 60s +reflector_misbehaving_detection_window=60 +reflector_misbehaving_detection_thr=3 + +reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list + +reflector_comparison_interval_mins=1 # how often to compare reflectors +reflector_sum_owd_baselines_delta_thr_ms=20 # max increase from min sum owd baselines before reflector rotated +reflector_owd_delta_ewma_delta_thr_ms=10 # max increase from min delta ewma before reflector rotated + +# stall is detected when the following two conditions are met: +# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and +# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr +stall_detection_thr=5 +connection_stall_thr_kbps=10 + +global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds) + +if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery) + +# Starlink satellite switch (sss) compensation options +sss_compensation=0 # enable (1) or disable (0) Starlink handling +# satellite switch compensation start times in seconds of each minute +sss_times_s=("12.0" "27.0" "42.0" "57.0") +sss_compensation_pre_duration_ms=300 +sss_compensation_post_duration_ms=200 diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh new file mode 100755 index 000000000..7cb3567df --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +cake_instances=(/root/cake-autorate/config.*.sh) +cake_instance_pids=() + +trap kill_cake_instances INT TERM EXIT + +kill_cake_instances() +{ + trap - INT TERM EXIT + + echo "Killing all instances of cake one-by-one now." + + for ((cake_instance=0; cake_instance<${#cake_instances[@]}; cake_instance++)) + do + kill "${cake_instance_pids[${cake_instance}]}" 2>/dev/null || true + done + wait +} + +for cake_instance in "${cake_instances[@]}" +do + /root/cake-autorate/cake-autorate.sh "${cake_instance}" & + cake_instance_pids+=(${!}) +done +wait diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh new file mode 100755 index 000000000..19141fc74 --- /dev/null +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh @@ -0,0 +1,149 @@ +#!/bin/bash + +# lib.sh -- common functions for use by cake-autorate.sh +# +# This file is part of cake-autorate. + +__set_e=0 +if [[ ! ${-} =~ e ]] +then + set -e + __set_e=1 +fi + +if [[ -z "${__sleep_fd:-}" ]] +then + exec {__sleep_fd}<> <(:) +fi + +typeof() { + # typeof -- returns the type of a variable + + local type_sig + type_sig=$(declare -p "${1}" 2>/dev/null) + if [[ "${type_sig}" =~ "declare --" ]] + then + str_type "${1}" + elif [[ "${type_sig}" =~ "declare -a" ]] + then + printf "array" + elif [[ "${type_sig}" =~ "declare -A" ]] + then + printf "map" + else + printf "none" + fi +} + +str_type() { + # str_type -- returns the type of a string + + local -n str="${1}" + + if [[ "${str}" =~ ^[0-9]+$ ]] + then + printf "integer" + elif [[ "${str}" =~ ^[0-9]*\.[0-9]+$ ]] + then + printf "float" + elif [[ "${str}" =~ ^-[0-9]+$ ]] + then + printf "negative-integer" + elif [[ "${str}" =~ ^-[0-9]*\.[0-9]+$ ]] + then + printf "negative-float" + else + # technically not validated, user is just trusted to call + # this function with valid strings + printf "string" + fi +} + +sleep_s() +{ + # Calling the external sleep binary could be rather slow, + # especially as it is called very frequently and typically on mediocre hardware. + # + # bash's loadable sleep module is not typically available + # in OpenWRT and most embedded systems, and use of the bash + # read command with a timeout offers performance that is + # at least on a par with bash's sleep module. + # + # For benchmarks, check the following links: + # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460057382 + # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 + + local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true +} + +sleep_us() +{ + local sleep_duration_us=${1} # (microseconds) + + sleep_duration_s=000000${sleep_duration_us} + sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} + sleep_s "${sleep_duration_s}" +} + +sleep_remaining_tick_time() +{ + # sleeps until the end of the tick duration + + local t_start_us=${1} # (microseconds) + local tick_duration_us=${2} # (microseconds) + + # shellcheck disable=SC2154 + sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} )) + + if (( sleep_duration_us > 0 )); then + sleep_us "${sleep_duration_us}" + fi +} + +randomize_array() +{ + # randomize the order of the elements of an array + + local -n array=${1} + + subset=("${array[@]}") + array=() + for ((set=${#subset[@]}; set>0; set--)) + do + idx=$((RANDOM%set)) + array+=("${subset[idx]}") + unset "subset[idx]" + subset=("${subset[@]}") + done +} + +terminate() +{ + # Send regular kill to processes and monitor terminations; + # return as soon as all of the active processes terminate; + # if any processes remain active after one second, kill with fire using kill -9; + # and, finally, call wait on all processes to reap any zombie processes. + + local pids=("${@:-}") + + kill "${pids[@]}" 2> /dev/null + + for((i=0; i<10; i++)) + do + for process in "${!pids[@]}" + do + kill -0 "${pids[${process}]}" 2> /dev/null || unset "pids[${process}]" + done + [[ "${pids[*]}" ]] || return + sleep_s 0.1 + done + + kill -9 "${pids[@]}" 2> /dev/null +} + +if (( __set_e == 1 )) +then + set +e +fi +unset __set_e diff --git a/luci-app-sysupgrade/Makefile b/luci-app-sysupgrade/Makefile new file mode 100755 index 000000000..3b5ccc6dc --- /dev/null +++ b/luci-app-sysupgrade/Makefile @@ -0,0 +1,11 @@ +# See /LICENSE for more information. +# This is free software, licensed under the GNU General Public License v2. + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for sysupgrades +LUCI_DEPENDS:=+luci-base +uhttpd-mod-ubus +rpcd +rpcd-mod-rpcsys +cgi-io + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-sysupgrade/luasrc/view/sysupgrade.htm b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm new file mode 100755 index 000000000..a7706bc79 --- /dev/null +++ b/luci-app-sysupgrade/luasrc/view/sysupgrade.htm @@ -0,0 +1,126 @@ +<% +-- all lua code provided by https://github.com/jow-/ +-- thank you very much! + + function apply_acls(filename, session) + local json = require "luci.jsonc" + local util = require "luci.util" + local fs = require "nixio.fs" + + local grants = { } + + local acl = json.parse(fs.readfile(filename)) + if type(acl) ~= "table" then + return + end + + local group, perms + for group, perms in pairs(acl) do + local perm, scopes + for perm, scopes in pairs(perms) do + if type(scopes) == "table" then + local scope, objects + for scope, objects in pairs(scopes) do + if type(objects) == "table" then + if not grants[scope] then + grants[scope] = { } + end + + if next(objects) == 1 then + local _, object + for _, object in ipairs(objects) do + if not grants[scope][object] then + grants[scope][object] = { } + end + table.insert(grants[scope][object], perm) + end + else + local object, funcs + for object, funcs in pairs(objects) do + if type(funcs) == "table" then + local _, func + for _, func in ipairs(funcs) do + if not grants[scope][object] then + grants[scope][object] = { } + end + table.insert(grants[scope][object], func) + end + end + end + end + end + end + end + end + end + + local _, scope, object, func + for scope, _ in pairs(grants) do + local objects = { } + for object, _ in pairs(_) do + for _, func in ipairs(_) do + table.insert(objects, { object, func }) + end + end + + util.ubus("session", "grant", { + ubus_rpc_session = session, + scope = scope, objects = objects + }) + end + end + + apply_acls("/usr/share/rpcd/acl.d/sysupgrade.json", luci.dispatcher.context.authsession) +%> +<%+header%> +

<%:Sysupgrade%>

+
+ <%:Easily search and install new releases and package upgrades.%> +
+ + +

+ +

+
+
+
+ + + + +
+
+ +
+
+
+
+
+ + +<%+footer%> diff --git a/luci-app-sysupgrade/po/fr/sysupgrade.po b/luci-app-sysupgrade/po/fr/sysupgrade.po new file mode 100755 index 000000000..8195816c5 --- /dev/null +++ b/luci-app-sysupgrade/po/fr/sysupgrade.po @@ -0,0 +1,97 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" +"Cochez \"Conserver les paramètres\" pour conserver la configuration actuelle." + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "Téléchargement du micrologiciel dans la mémoire du navigateur Web" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "" +"Recherchez et installez facilement les nouvelles versions et les mises à " +"niveau des paquets." + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "Modifier les packages installés" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "Mise à jour du micrologiciel. Ne débranchez pas l'appareil" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "Version installée :" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "Conserver les paramètres :" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "Pas de mise à jour disponible" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "Redémarrage de l'appareil - veuillez patienter !" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "Demander le micrologiciel" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "Rechercher des mises à jour" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "Recherche des mises à jour" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "Serveur :" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "Succès ! Veuillez recharger l'interface Web" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "Mise à jour système" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" +"Le téléchargement du micrologiciel a échoué, veuillez réessayer en " +"rechargeant l'interface Web" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "Téléchargement du micrologiciel sur l'appareil" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "" +"L'interface Web n'a pas pu se reconnecter à votre appareil. Recharger " +"l'interface" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "Mise à jour système via rpcd et luci" diff --git a/luci-app-sysupgrade/po/ru/sysupgrade.po b/luci-app-sysupgrade/po/ru/sysupgrade.po new file mode 100755 index 000000000..742b59652 --- /dev/null +++ b/luci-app-sysupgrade/po/ru/sysupgrade.po @@ -0,0 +1,94 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" +"Поставьте \"Сохранить настройки\", чтобы сохранить текущую конфигурацию." + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "Загружаем ПО в память вашего браузера" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "Легко ищите и устанавливайте новые версии ПО и обновления пакетов." + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "Редактировать список установленных пакетов" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "Обновляем ПО маршрутизатора. Не выключайте питание вашего устройства" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "Установленная версия:" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "Сохранить настройки:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "Обновления не найдены" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "Перезагружаем роутер, пожалуйста подождите!" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "Загрузить ПО" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "Поиск обновлений" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "Поиск обновлений" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "Сервер:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "Успешно! Пожалуйста обновите страницу" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "sysupgrade" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" +"Ошибка при загрузке обновлений ПО. Для продолжения, пожалуйста обновите " +"страницу" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "Загружаем обновления ПО в память роутера" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "Проблема при подключении к роутеру. Пожалуйста обновите страницу" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "sysupgrade с использованием RPCd и LUCI" diff --git a/luci-app-sysupgrade/po/templates/sysupgrade.pot b/luci-app-sysupgrade/po/templates/sysupgrade.pot new file mode 100755 index 000000000..1ebb8dc2e --- /dev/null +++ b/luci-app-sysupgrade/po/templates/sysupgrade.pot @@ -0,0 +1,81 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "" diff --git a/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po new file mode 100755 index 000000000..e68dec985 --- /dev/null +++ b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po @@ -0,0 +1,90 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-03 07:27+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "勾选保持当前配置。" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "下载固件到网页浏览器内存" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "轻松搜索和安装新版本升级固件包。" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "编辑安装包" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "设备升级中。请不要断开电源" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "安装的版本:" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "保持设置:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "没有升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "正在重启设备-请稍候!" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "请求固件" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "服务器:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "成功!请重新加载web界面" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "系统升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "轻松搜索和安装新版本的系统进行升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "上传固件到设备" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "网络界面无法重新连接到您的设备。请重新加载web界面或手动检查设备" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "通过RPCD和luci进行升级" diff --git a/luci-app-sysupgrade/root/etc/init.d/sysupgrade b/luci-app-sysupgrade/root/etc/init.d/sysupgrade new file mode 100755 index 000000000..9ffc3c537 --- /dev/null +++ b/luci-app-sysupgrade/root/etc/init.d/sysupgrade @@ -0,0 +1,20 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2020-2021 Ycarus (Yannick Chabanois) +# Released under GPL 3. See LICENSE for the full terms. + +{ + START=99 + STOP=10 + USE_PROCD=1 +} + +start_service() +{ + if [ -f /etc/backup/installed_packages.txt ]; then + if [ "$(opkg -V0 update 2>&1)" = "" ]; then + grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg -V0 install + rm /etc/backup/installed_packages.txt + fi + fi +} + diff --git a/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade b/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade new file mode 100755 index 000000000..a5ef66fe8 --- /dev/null +++ b/luci-app-sysupgrade/root/etc/uci-defaults/40_luci-sysupgrade @@ -0,0 +1,20 @@ +#!/bin/sh + +/etc/init.d/uhttpd restart +/etc/init.d/rpcd reload + +[ -e /etc/config/sysupgrade ] && return 0 + +touch /etc/config/sysupgrade + +uci -q batch < + ubus_call("uci", "get", option, option["option"]) +} + +ubus_counter = 0; +ubus_closed = 0; + +function ubus_call(command, argument, params, variable) { + var request_data = {}; + request_data.jsonrpc = "2.0"; + request_data.id = ubus_counter; + request_data.method = "call"; + request_data.params = [data.ubus_rpc_session, command, argument, params] + var request_json = JSON.stringify(request_data) + ubus_counter++; + var request = new XMLHttpRequest(); + request.open("POST", ubus_url, true); + request.setRequestHeader("Content-type", "application/json"); + request.onload = function(event) { + if (request.status === 200) { + var response = JSON.parse(request.responseText) + if (!("error" in response) && "result" in response) { + if (response.result.length === 2) { + if (command === "uci") { + data[variable] = response.result[1].value + } else { + data[variable] = response.result[1][variable] + } + } + } else { + set_status("danger", "Ubus call failed:
Request: " + request_json + "
Response: " + JSON.stringify(response)) + } + ubus_closed++; + } + } + request.send(request_json); +} + +function set_status(type, message, loading, show_log) { + $("#status_box").className = "alert-message " + type; + var loading_image = ''; + if (loading) { + loading_image = 'Loading '; + } + if (data.buildlog_url && show_log) { + message += '

Build log

' + } + $("#status_box").innerHTML = loading_image + message; + show("#status_box") +} + +function upgrade_check() { + var current_version = data.release.version.toLowerCase(); + var current_branch = current_version.split('-')[0].split('.').slice(0, 2).join('.') + var candidates = [] + hide("#status_box"); + hide("#server_div"); + set_status("info", _("Searching for upgrades"), true); + fetch(data.url + "/api/versions?v=" + Date.now()) + .then(response => response.json()) + .then(response => { + var branches = response["branches"] + for (i in branches) { + // handle snapshots in a special way - as always + if (current_version == "snapshot" && branches[i]["latest"] == "snapshot") { + candidates.unshift(branches[i]) + break + } + + if (current_version == branches[i]["latest"]) { + break + } + if (current_branch != branches[i]["name"]) { + branches[i]["warn_branch_jump"] = true + } + candidates.unshift(branches[i]) + if (current_branch == branches[i]["name"]) { + // don't offer branches older than the current + break + } + } + + if (candidates.length > 0) { + var info_output = "

New release " + candidates[0].latest + " available

" + info_output += _('Installed version:') + " " + data.release.version + + // tell server the currently installed version + request_dict.current_version = request_dict.version; + // tell server what version to install + request_dict.version = candidates[0].latest; + // tell server to diff the requested packages with the default packages + // this allows to not automatically re-install default packages which + // where dropped in later releases + request_dict.diff_packages = true; + + set_status("success", info_output) + + if (data.advanced_mode == 1) { + show("#edit_button"); + } + var upgrade_button = $("#upgrade_button") + upgrade_button.value = _("Request firmware"); + upgrade_button.style.display = "block"; + upgrade_button.disabled = false; + upgrade_button.onclick = upgrade_request; + + } else { + set_status("success", _("No upgrades available")) + + } + }); + +} + +function upgrade_request() { + // Request firmware using the following parameters + // distro, version, target, board_name, packages + $("#upgrade_button").disabled = true; + hide("#edit_packages"); + hide("#edit_button"); + hide("#keep_container"); + + // add board info to let server determine profile + request_dict.target = data.release.target + request_dict.profile = data.board_name + request_dict.rootfs = data.format + request_dict.efi = data.efi_enabled + + if (data.edit_packages == true) { + request_dict.packages = $("#edit_packages").value.split("\n") + } else { + request_dict.packages = Object.keys(data.packages); + } + server_request() +} + +function upgrade_request_callback(response) { + var sysupgrade_file = ""; + console.log(response) + for (i in response.images) { + if (response.images[i].type == "sysupgrade") { + sysupgrade_file = response.images[i].name; + } + } + if (sysupgrade_file != "") { + data.sysupgrade_url = data.url + '/release/' + response.bin_dir + '/' + sysupgrade_file + var info_output = '

Firmware searched

File: ' + sysupgrade_file + '

' + set_status("success", info_output, false, true); + + show("#keep_container"); + var upgrade_button = $("#upgrade_button") + upgrade_button.disabled = false; + upgrade_button.style.display = "block"; + upgrade_button.value = "Flash firmware"; + upgrade_button.onclick = download_image; + } else { + set_status("danger", "Device not sysupgrade compatible!") + } +} + +function flash_image() { + // Flash image via rpc-sys upgrade_start + set_status("warning", _("Flashing firmware. Don't unpower device"), true) + ubus_call("rpc-sys", "upgrade_start", { + "keep": $("#keep").checked + }, 'message'); + ping_max = 3600; // in seconds + setTimeout(ping_ubus, 10000) +} + +function ping_ubus() { + // Tries to connect to ubus. If the connection fails the device is likely still rebooting. + // If more time than ping_max passes update may failed + if (ping_max > 0) { + ping_max--; + var request = new XMLHttpRequest(); + request.open("GET", ubus_url, true); + request.addEventListener('error', function(event) { + set_status("warning", _("Rebooting device - please wait!"), true); + setTimeout(ping_ubus, 5000) + }); + request.addEventListener('load', function(event) { + set_status("success", _("Success! Please reload web interface")); + $("#upgrade_button").value = "Reload page"; + show("#upgrade_button"); + $("#upgrade_button").disabled = false; + $("#upgrade_button").onclick = function() { + location.reload(); + } + }); + request.send(); + } else { + set_status("danger", _("Web interface could not reconnect to your device. Please reload web interface or check device manually")) + } +} + +function upload_image(blob) { + // Uploads received blob data to the server using cgi-io + set_status("info", _("Uploading firmware to device"), true); + var request = new XMLHttpRequest(); + var form_data = new FormData(); + + form_data.append("sessionid", data.ubus_rpc_session) + form_data.append("filename", "/tmp/firmware.bin") + form_data.append("filemode", 755) // insecure? + form_data.append("filedata", blob) + + request.addEventListener('load', function(event) { + request_json = JSON.parse(request.responseText) + flash_image(); + }); + + request.addEventListener('error', function(event) { + set_status("danger", _("Upload of firmware failed, please retry by reloading web interface")) + }); + + request.open('POST', origin + '/cgi-bin/cgi-upload'); + request.send(form_data); +} + + +function download_image() { + // Download image from server once the url was received by upgrade_request + hide("#keep_container"); + hide("#upgrade_button"); + var download_request = new XMLHttpRequest(); + download_request.open("GET", data.sysupgrade_url); + download_request.responseType = "arraybuffer"; + + download_request.onload = function() { + if (this.status === 200) { + var blob = new Blob([download_request.response], { + type: "application/octet-stream" + }); + upload_image(blob) + } + }; + set_status("info", _("Downloading firmware to web browser memory"), true); + download_request.send(); +} + +function server_request() { + fetch(data.url + "/api/build?v=" + Date.now(), { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(request_dict) + }) + .then(response => { + switch (response.status) { + case 200: + response.json() + .then(response => { + upgrade_request_callback(response) + }); + break; + case 202: + set_status("info", "Processing request", true); + setTimeout(function() { + server_request() + }, 5000) + break; + case 400: // bad request + case 422: // bad package + case 500: // build failed + console.log('error (' + response.status + ')'); + response.json() + .then(response => { + if (response.buildlog) { + data.buildlog_url = data.url + '/' + response.bin_dir + '/buildlog.txt'; + } + set_status("danger", response.message); + }); + break; + } + }); +} + +request_dict = {} +document.onload = setup() diff --git a/luci-base/po/oc/base.po b/luci-base/po/oc/base.po new file mode 100755 index 000000000..28f4b510f --- /dev/null +++ b/luci-base/po/oc/base.po @@ -0,0 +1,7620 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-19 09:37+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:929 +msgid "%.1f dB" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:114 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:261 +msgid "%d Bit" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3689 +msgid "%d invalid field(s)" +msgstr "%d camp(s) invalid(s)" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:35 +msgid "%s is untagged in multiple VLANs!" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:294 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:403 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:270 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:307 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:325 +msgid "(%d minute window, %d second interval)" +msgstr "(fenèstra de %d minuta,interval de %d segonda)" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:118 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:124 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:258 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:282 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:88 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:91 +msgid "(empty)" +msgstr "(void)" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:351 +#: modules/luci-compat/luasrc/view/cbi/network_netinfo.htm:23 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:58 +msgid "(no interfaces attached)" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:48 +msgid "-- Additional Field --" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/cbi.js:275 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3372 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3704 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:767 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1005 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1974 +#: modules/luci-compat/luasrc/view/cbi/header.htm:8 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:88 +msgid "-- Please choose --" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/cbi.js:276 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1006 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1975 +#: modules/luci-compat/luasrc/view/cbi/header.htm:9 +msgid "-- custom --" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:270 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:379 +msgid "-- match by label --" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:256 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:362 +msgid "-- match by uuid --" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:27 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:44 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:23 +msgid "-- please select --" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:54 +msgctxt "sstp log level value" +msgid "0" +msgstr "0" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:939 +msgid "0 = not using RSSI threshold, 1 = do not change driver default" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:55 +msgctxt "sstp log level value" +msgid "1" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:231 +msgid "1 Minute Load:" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:251 +msgid "15 Minute Load:" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:56 +msgctxt "sstp log level value" +msgid "2" +msgstr "2" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:57 +msgctxt "sstp log level value" +msgid "3" +msgstr "3" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:58 +msgctxt "sstp log level value" +msgid "4" +msgstr "4" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1442 +msgid "4-character hexadecimal ID" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:18 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:11 +msgid "464XLAT (CLAT)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:241 +msgid "5 Minute Load:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1471 +msgid "6-octet identifier as a hex string - no colons" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1431 +msgid "802.11r Fast Transition" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1619 +msgid "802.11w Association SA Query maximum timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1626 +msgid "802.11w Association SA Query retry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1607 +msgid "802.11w Management Frame Protection" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1619 +msgid "802.11w maximum timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1626 +msgid "802.11w retry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:956 +msgid "BSSID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:326 +msgid "DNS query port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:317 +msgid "DNS server port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:260 +msgid "" +"DNS servers will be queried in the " +"order of the resolvfile" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:945 +msgid "ESSID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:475 +msgid "IPv4-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:42 +msgid "IPv4-Gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:603 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:36 +msgid "IPv4-Netmask" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +msgid "" +"IPv6-Address or Network " +"(CIDR)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:42 +msgid "IPv6-Gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:504 +msgid "IPv6-Suffix (hex)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:58 +msgid "LED Configuration" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:69 +msgid "LED Name" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:431 +msgid "MAC-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:498 +msgid "DUID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:335 +msgid "" +"Max. DHCP leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:344 +msgid "" +"Max. EDNS0 packet size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:353 +msgid "Max. concurrent queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:29 +msgid "" +"
Note: you need to manually restart the cron service if the crontab file " +"was empty before editing." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2720 +msgid "A directory with the same name already exists." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2670 +msgid "A new login is required since the authentication session expired." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:909 +msgid "A43C + J43 + A43" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:910 +msgid "A43C + J43 + A43 + V43" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:922 +msgid "ADSL" +msgstr "ADSL" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:898 +msgid "ANSI T1.413" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:94 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:93 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:86 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:67 +msgid "APN" +msgstr "APN" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:197 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:352 +msgid "ARP" +msgstr "ARP" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:365 +msgid "ARP IP Targets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:357 +msgid "ARP Interval" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:381 +msgid "ARP Validation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:373 +msgid "ARP mode to consider a slave as being up" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:77 +msgid "ARP monitoring is not supported for the selected policy!" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:175 +msgid "ARP retry threshold" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:917 +msgid "ATM (Asynchronous Transfer Mode)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:938 +msgid "ATM Bridges" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:970 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:66 +msgid "ATM Virtual Channel Identifier (VCI)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:971 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:70 +msgid "ATM Virtual Path Identifier (VPI)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:938 +msgid "" +"ATM bridges expose encapsulated ethernet in AAL5 connections as virtual " +"Linux network interfaces which can be used in conjunction with DHCP or PPP " +"to dial into the provider network." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:977 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:62 +msgid "ATM device number" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:37 +msgid "ATU-C System Vendor ID" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:265 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:543 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:547 +msgid "Absent Interface" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:47 +msgid "Access Concentrator" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:927 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1032 +msgid "Access Point" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:360 +msgid "Actions" +msgstr "Accions" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:200 +msgid "Active IPv4-Routes" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:206 +msgid "Active IPv6-Routes" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:81 +msgid "Active Connections" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:33 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:92 +msgid "Active DHCP Leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:52 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:94 +msgid "Active DHCPv6 Leases" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:203 +msgid "Active-Backup policy (active-backup, 1)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3666 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:929 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:23 +msgid "Ad-Hoc" +msgstr "Ad-Hoc" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:208 +msgid "Adaptive load balancing (balance-alb, 6)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:207 +msgid "Adaptive transmit load balancing (balance-tlb, 5)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2167 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2170 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2184 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2185 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3170 +#: modules/luci-compat/luasrc/view/cbi/nsection.htm:25 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:189 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:197 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:39 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:47 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:54 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:827 +msgid "Add" +msgstr "Ajustar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:942 +msgid "Add ATM Bridge" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:92 +msgid "Add IPv4 address…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:207 +msgid "Add IPv6 address…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:65 +msgid "Add LED action" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:219 +msgid "Add VLAN" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:15 +msgid "Add instance" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:146 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:152 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:247 +msgid "Add key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:248 +msgid "Add local domain suffix to names served from hosts files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:311 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:757 +msgid "Add new interface..." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:125 +msgid "Add peer" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:200 +msgid "Additional Hosts files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:255 +msgid "Additional servers file" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:34 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:35 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:36 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:37 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:38 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:39 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:40 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:41 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:42 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:43 +msgid "Address" +msgstr "Adreça" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:151 +msgid "Address to access local relay bridge" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:285 +msgid "Addresses" +msgstr "Adreças" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:3 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:15 +msgid "Administration" +msgstr "Administracion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:164 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:324 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:553 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:968 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:25 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:866 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:924 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:241 +msgid "Advanced Settings" +msgstr "Paramètres avançats" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:28 +msgid "Aggregate Transmit Power (ACTATP)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:258 +msgid "Aggregation Selection Logic" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:261 +msgid "Aggregator: All slaves down or has no slaves (stable, 0)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:263 +msgid "" +"Aggregator: Chosen by the largest number of ports + slave added/removed or " +"state changes (count, 2)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:262 +msgid "Aggregator: Slave added/removed or state changes (bandwidth, 1)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:171 +msgid "Alert" +msgstr "Alèrta" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2871 +#: modules/luci-compat/luasrc/model/network.lua:1417 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:61 +msgid "Alias Interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:145 +msgid "Alias of \"%s\"" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:263 +msgid "All Servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:209 +msgid "" +"Allocate IP addresses sequentially, starting from the lowest available " +"address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:208 +msgid "Allocate IP sequentially" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:25 +msgid "Allow SSH password authentication" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1112 +msgid "Allow AP mode to disconnect STAs based on low ACK condition" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1016 +msgid "Allow all except listed" +msgstr "" + +#: modules/luci-compat/root/usr/share/rpcd/acl.d/luci-compat.json:3 +msgid "Allow full UCI access for legacy applications" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:892 +msgid "Allow legacy 802.11b rates" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1015 +msgid "Allow listed only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:300 +msgid "Allow localhost" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:157 +msgid "Allow rebooting the device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:36 +msgid "Allow remote hosts to connect to local SSH forwarded ports" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:31 +msgid "Allow root logins with password" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:3 +msgid "Allow system feature probing" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:31 +msgid "Allow the root user to login with password" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:301 +msgid "" +"Allow upstream responses in the 127.0.0.0/8 range, e.g. for RBL services" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:148 +msgid "Allowed IPs" +msgstr "IP autorizadas" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:654 +msgid "Always announce default router" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/none.js:5 +msgid "Always off (kernel: none)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:6 +msgid "Always on (kernel: default-on)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:907 +msgid "" +"Always use 40MHz channels even if the secondary channel overlaps. Using this " +"option does not comply with IEEE 802.11n-2009!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:603 +msgid "An error occurred while saving the form:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:890 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:20 +msgid "Annex" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:891 +msgid "Annex A + L + M (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:899 +msgid "Annex A G.992.1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:900 +msgid "Annex A G.992.2" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:901 +msgid "Annex A G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:902 +msgid "Annex A G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:892 +msgid "Annex B (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:895 +msgid "Annex B G.992.1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:896 +msgid "Annex B G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:897 +msgid "Annex B G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:893 +msgid "Annex J (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:903 +msgid "Annex L G.992.3 POTS 1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:894 +msgid "Annex M (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:904 +msgid "Annex M G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:905 +msgid "Annex M G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:654 +msgid "Announce as default router even if no public prefix is available." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:659 +msgid "Announced DNS domains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:658 +msgid "Announced DNS servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1596 +msgid "Anonymous Identity" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:162 +msgid "Anonymous Mount" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:158 +msgid "Anonymous Swap" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:84 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:174 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:195 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:60 +msgid "Any zone" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:119 +msgid "Apply backup?" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4276 +msgid "Apply request failed with status %h" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2181 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4142 +msgid "Apply unchecked" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4215 +msgid "Applying configuration changes… %ds" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:56 +msgid "Architecture" +msgstr "Arquitectura" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:184 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:27 +msgid "" +"Assign a part of given length of every public IPv6-prefix to this interface" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:189 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:31 +msgid "" +"Assign prefix parts using this hexadecimal subprefix ID for this interface." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2078 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:245 +msgid "Associated Stations" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:46 +msgid "Associations" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:154 +msgid "Attempt to enable configured mount points for attached devices" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:104 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:64 +msgid "Auth Group" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1535 +msgid "Authentication" +msgstr "Autentificacion" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:96 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:70 +msgid "Authentication Type" +msgstr "Tipe d’autentificacion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:172 +msgid "Authoritative" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:17 +msgid "Authorization Required" +msgstr "" + +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:196 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:197 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:241 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:244 +msgid "Auto Refresh" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:106 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:18 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:24 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:98 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:50 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:94 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:81 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:55 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:68 +msgid "Automatic" +msgstr "Automatic" + +#: modules/luci-compat/luasrc/model/network/proto_hnet.lua:7 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:7 +msgid "Automatic Homenet (HNCP)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:174 +msgid "Automatically check filesystem for errors before mounting" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:170 +msgid "Automatically mount filesystems on hotplug" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:166 +msgid "Automatically mount swap on hotplug" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:170 +msgid "Automount Filesystem" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:166 +msgid "Automount Swap" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:193 +msgid "Available" +msgstr "Disponible" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:268 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:278 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:329 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:339 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:349 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:234 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:244 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:254 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:263 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:273 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:291 +msgid "Average:" +msgstr "Mejana :" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:911 +msgid "B43 + B43C" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:912 +msgid "B43 + B43C + V43" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:48 +msgid "BR / DMR / AFTR" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:158 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:182 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1665 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:44 +msgid "BSSID" +msgstr "BSSID" + +#: modules/luci-compat/luasrc/view/cbi/footer.htm:14 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:48 +msgid "Back to Overview" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:48 +msgid "Back to configuration" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:363 +msgid "Backup" +msgstr "Salvagarda" + +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:114 +msgid "Backup / Flash Firmware" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:323 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:12 +msgid "Backup file list" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:158 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:451 +msgid "Band" +msgstr "Grop" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:910 +msgid "Beacon Interval" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:324 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:46 +msgid "" +"Below is the determined list of files to backup. It consists of changed " +"configuration files marked by opkg, essential base files and the user " +"defined backup patterns." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:395 +msgid "" +"Bind dynamically to interfaces rather than wildcard address (recommended as " +"linux default)" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:52 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:62 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:48 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:55 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:57 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:52 +msgid "Bind interface" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:52 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:62 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:48 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:55 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:57 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:52 +msgid "Bind the tunnel to this interface (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:188 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:63 +msgid "Bitrate" +msgstr "Debit" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:266 +msgid "Bogus NX Domain Override" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:199 +msgid "Bonding Policy" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2877 +#: modules/luci-compat/luasrc/model/network.lua:1421 +msgid "Bridge" +msgstr "Pont" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:416 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:730 +msgid "Bridge interfaces" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:978 +msgid "Bridge unit number" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:412 +msgid "Bring up on boot" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:205 +msgid "Broadcast policy (broadcast, 3)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2810 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3799 +msgid "Browse…" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:37 +msgid "Buffered" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:138 +msgid "CA certificate; if empty it will be saved after the first connection." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:7 +msgid "CLAT configuration failed" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:72 +msgid "CPU usage (%)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:41 +msgid "Cached" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:53 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:53 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:21 +msgid "Call failed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2903 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3808 +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:14 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:52 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:187 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:763 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1952 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:128 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:272 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:184 +msgid "Cancel" +msgstr "Anullar" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:17 +msgid "Category" +msgstr "Categoria" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1519 +msgid "Certificate constraint (Domain)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1516 +msgid "Certificate constraint (SAN)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1513 +msgid "Certificate constraint (Subject)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1522 +msgid "Certificate constraint (Wildcard)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1513 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1571 +msgid "" +"Certificate constraint substring - e.g. /CN=wifi.mycompany.com
See " +"`logread -f` during handshake for actual values" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1519 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1577 +msgid "" +"Certificate constraint(s) against DNS SAN values (if available)
or " +"Subject CN (exact match)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1522 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1580 +msgid "" +"Certificate constraint(s) against DNS SAN values (if available)
or " +"Subject CN (suffix match)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1516 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1574 +msgid "" +"Certificate constraint(s) via Subject Alternate Name values
(supported " +"attributes: EMAIL, DNS, URI) - e.g. DNS:wifi.mycompany.com" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:200 +msgid "Chain" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4028 +msgid "Changes" +msgstr "Diferéncias" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4311 +msgid "Changes have been reverted." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:46 +msgid "Changes the administrator password for accessing the device" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:162 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:128 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:184 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:460 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1663 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:62 +msgid "Channel" +msgstr "Canal" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:174 +msgid "Check filesystems before mount" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1914 +msgid "Check this option to delete the existing networks from this radio." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:110 +msgid "Checking archive…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:193 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:195 +msgid "Checking image…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:399 +msgid "Choose mtdblock" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:491 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1942 +msgid "" +"Choose the firewall zone you want to assign to this interface. Select " +"unspecified to remove the interface from the associated zone or " +"fill out the custom field to define a new zone and attach the " +"interface to it." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:959 +msgid "" +"Choose the network(s) you want to attach to this wireless interface or fill " +"out the custom field to define a new network." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1148 +msgid "Cipher" +msgstr "Cipher" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:91 +msgid "Cisco UDP encapsulation" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:363 +msgid "" +"Click \"Generate archive\" to download a tar archive of the current " +"configuration files." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:396 +msgid "" +"Click \"Save mtdblock\" to download specified mtdblock file. (NOTE: THIS " +"FEATURE IS FOR PROFESSIONALS! )" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3665 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:928 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1033 +msgid "Client" +msgstr "Client" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:52 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:47 +msgid "Client ID to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:148 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:154 +msgid "Close" +msgstr "Tampar" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:157 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:141 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:115 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:138 +msgid "" +"Close inactive connection after the given amount of seconds, use 0 to " +"persist connection" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:49 +msgid "Close list..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:42 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:61 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2076 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:389 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:317 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:320 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:204 +msgid "Collecting data..." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:71 +msgid "Command" +msgstr "Comanda" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:401 +msgid "Command OK" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:33 +msgid "Command failed" +msgstr "La comanda a fracassat" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:72 +msgid "Comment" +msgstr "Comentari" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1634 +msgid "" +"Complicates key reinstallation attacks on the client side by disabling " +"retransmission of EAPOL-Key frames that are used to install keys. This " +"workaround might cause interoperability issues and reduced robustness of key " +"negotiation especially in environments with heavy traffic load." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:96 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:98 +msgid "Compute outgoing checksum (optional)." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4028 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:426 +msgid "Configuration" +msgstr "Configuracion" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4190 +msgid "Configuration changes applied." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4128 +msgid "Configuration changes have been rolled back!" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:63 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:21 +msgid "Configuration failed" +msgstr "Fracàs de la configuracion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:175 +msgid "Confirm disconnect" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:55 +msgid "Confirmation" +msgstr "Confirmacion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:51 +msgid "Connected" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:9 +#: modules/luci-compat/luasrc/model/network.lua:27 +msgid "Connection attempt failed" +msgstr "Ensag de connexion pas capitat" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:40 +msgid "Connection attempt failed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:411 +msgid "Connection lost" +msgstr "Connexion perduda" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:117 +msgid "Connections" +msgstr "Connexions" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:377 +msgid "Consider the slave up when all ARP IP targets are reachable (all, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:376 +msgid "Consider the slave up when any ARP IP target is reachable (any, 0)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:18 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:340 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:55 +msgid "Contents have been saved." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:742 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:132 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:264 +msgid "Continue" +msgstr "Contunhar" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4164 +msgid "" +"Could not regain access to the device after applying the configuration " +"changes. You might need to reconnect if you modified network related " +"settings such as the IP address or wireless security credentials." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:189 +msgid "Country" +msgstr "País" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:889 +msgid "Country Code" +msgstr "Còde de país" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:491 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1942 +msgid "Create / Assign firewall-zone" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:798 +msgid "Create interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:416 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:730 +msgid "Creates a bridge over specified interface(s)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:170 +msgid "Critical" +msgstr "Critic" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:174 +msgid "Cron Log Level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:533 +msgid "Current power" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:568 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:570 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:51 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:53 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:82 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:83 +msgid "Custom Interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:36 +msgid "Custom delegated IPv6-prefix" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:382 +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:6 +msgid "Custom flash interval (kernel: timer)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:59 +msgid "" +"Customizes the behaviour of the device LEDs if possible." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1353 +msgid "DAE-Client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1358 +msgid "DAE-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1363 +msgid "DAE-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:327 +msgid "DHCP Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:155 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:50 +msgid "DHCP and DNS" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1982 +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:16 +#: modules/luci-compat/luasrc/model/network.lua:969 +msgid "DHCP client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:619 +msgid "DHCP-Options" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_dhcpv6.lua:7 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:7 +msgid "DHCPv6 client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:646 +msgid "DHCPv6-Mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:631 +msgid "DHCPv6-Service" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:45 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:47 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:48 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:49 +msgid "DNS" +msgstr "DNS" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:277 +msgid "DNS forwardings" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:37 +msgid "DNS-Label / FQDN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:228 +msgid "DNSSEC" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:232 +msgid "DNSSEC check unsigned" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:99 +msgid "DPD Idle Timeout" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:41 +msgid "DS-Lite AFTR address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:887 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:45 +msgid "DSL" +msgstr "DSL" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:14 +msgid "DSL Status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:920 +msgid "DSL line mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1088 +msgid "DTIM Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:57 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:58 +msgid "DUID" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:22 +msgid "Data Rate" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:165 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:176 +msgid "Debug" +msgstr "Desbugatge" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1328 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1343 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1358 +msgid "Default %d" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:107 +msgid "Default Route" +msgstr "Rota per defaut" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:48 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:85 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:65 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:49 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:67 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:80 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:108 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:150 +msgid "Default gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:646 +msgid "Default is stateless + stateful" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:11 +msgid "Default state" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:619 +msgid "" +"Define additional DHCP options, for example " +"\"6,192.168.2.1,192.168.2.2\" which advertises different DNS " +"servers to clients." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2237 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2662 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2666 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3154 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2872 +#: modules/luci-compat/luasrc/view/cbi/nsection.htm:11 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:162 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:16 +msgid "Delete" +msgstr "Suprimir" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:180 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:186 +msgid "Delete key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2769 +msgid "Delete request failed: %s" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:847 +msgid "Delete this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1088 +msgid "Delivery Traffic Indication Message Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:340 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:134 +msgid "Description" +msgstr "Descripcion" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2868 +msgid "Deselect" +msgstr "Deseleccionar" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:220 +msgid "Design" +msgstr "Concepcion" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:384 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:70 +msgid "Destination" +msgstr "Destinacion" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:48 +msgid "Destination port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:59 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:165 +msgid "Destination zone" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:67 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:191 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:43 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:80 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:55 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:12 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:247 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:280 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:356 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:392 +msgid "Device" +msgstr "Periferic" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:861 +msgid "Device Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:132 +msgid "Device is not active" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:224 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:599 +msgid "Device is restarting…" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:45 +msgid "Device not managed by ModemManager." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4163 +msgid "Device unreachable!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:53 +msgid "Device unreachable! Still waiting for device..." +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:88 +msgid "Diagnostics" +msgstr "Diagnostics" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:101 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:93 +msgid "Dial number" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2665 +msgid "Directory" +msgstr "Direccion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:839 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:879 +msgid "Disable" +msgstr "Desactivar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:579 +msgid "" +"Disable DHCP for " +"this interface." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:373 +msgid "Disable DNS lookups" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:93 +msgid "Disable Encryption" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1098 +msgid "Disable Inactivity Polling" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:837 +msgid "Disable this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1608 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:66 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:107 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:99 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:51 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:95 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:82 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:69 +msgid "Disabled" +msgstr "Desactivat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1112 +msgid "Disassociate On Low Acknowledgement" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:294 +msgid "Discard upstream RFC1918 responses" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:197 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:665 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:231 +msgid "Disconnect" +msgstr "Se desconnectar" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:64 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:22 +msgid "Disconnection attempt failed" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:48 +msgid "Disconnection attempt failed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:606 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2861 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3309 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4045 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4134 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1688 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:330 +msgid "Dismiss" +msgstr "Far desaparéisser" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:895 +msgid "Distance Optimization" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:895 +msgid "Distance to farthest network member in meters." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:155 +msgid "" +"Dnsmasq is a combined DHCP-Server and DNS-" +"Forwarder for NAT " +"firewalls" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:252 +msgid "Do not cache negative replies, e.g. for not existing domains" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:79 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:81 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:86 +msgid "Do not create host route to peer (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:219 +msgid "Do not forward requests that cannot be answered by public name servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:214 +msgid "Do not forward reverse lookups for local networks" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:25 +msgid "Do not send a hostname" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2755 +msgid "Do you really want to delete \"%s\" ?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:181 +msgid "Do you really want to delete the following SSH key?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:94 +msgid "Do you really want to erase all settings?" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2753 +msgid "Do you really want to recursively delete the directory \"%s\" ?" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:168 +msgid "Domain required" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:307 +msgid "Domain whitelist" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:81 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:67 +msgid "Don't Fragment" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:169 +msgid "" +"Don't forward DNS-Requests without " +"DNS-Name" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:152 +msgid "Down" +msgstr "Bas" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:402 +msgid "Down Delay" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:366 +msgid "Download backup" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:404 +msgid "Download mtdblock" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:925 +msgid "Downstream SNR offset" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2620 +msgid "Drag to reorder" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:341 +msgid "Drop Duplicate Frames" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:12 +msgid "Dropbear Instance" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:10 +msgid "" +"Dropbear offers SSH network shell access " +"and an integrated SCP server" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:14 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:11 +msgid "Dual-Stack Lite (RFC6333)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:595 +msgid "Dynamic DHCP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:60 +msgid "Dynamic tunnel" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:595 +msgid "" +"Dynamically allocate DHCP addresses for clients. If disabled, only clients " +"having static leases will be served." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:67 +msgid "EA-bits length" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1491 +msgid "EAP-Method" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2640 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2643 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3017 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:154 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:160 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:339 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:844 +msgid "Edit" +msgstr "Editar" + +#: modules/luci-compat/luasrc/view/cbi/error.htm:13 +msgid "" +"Edit the raw configuration data above to fix any error and hit \"Save\" to " +"reload the page." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:842 +msgid "Edit this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:793 +msgid "Edit wireless network" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:172 +msgid "Emergency" +msgstr "Urgéncia" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:839 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:879 +msgid "Enable" +msgstr "Activar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:462 +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:460 +msgid "Enable STP" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:367 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:373 +msgid "Enable DNS lookups" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:292 +msgid "Enable Dynamic Shuffling Of Flows" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:60 +msgid "Enable HE.net dynamic endpoint update" +msgstr "" + +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:89 +msgid "Enable IPv6 negotiation" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:49 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:80 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:54 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:67 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:93 +msgid "Enable IPv6 negotiation on the PPP link" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:192 +msgid "Enable Jumbo Frame passthrough" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:240 +msgid "Enable NTP client" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:96 +msgid "Enable Single DES" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:368 +msgid "Enable TFTP server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:184 +msgid "Enable VLAN functionality" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1638 +msgid "Enable WPS pushbutton, requires WPA(2)-PSK/WPA3-SAE" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1634 +msgid "Enable key reinstallation (KRACK) countermeasures" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:187 +msgid "Enable learning and aging" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:198 +msgid "Enable mirroring of incoming packets" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:199 +msgid "Enable mirroring of outgoing packets" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:882 +msgid "" +"Enable packet steering across all CPUs. May help or hinder network speed." +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:80 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:75 +msgid "Enable rx checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:81 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:67 +msgid "Enable the DF (Don't Fragment) flag of the encapsulating packets." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:837 +msgid "Enable this network" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:84 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:79 +msgid "Enable tx checksum" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:243 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:352 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:66 +msgid "Enabled" +msgstr "Activat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:462 +msgid "Enables IGMP snooping on this bridge" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1431 +msgid "" +"Enables fast roaming among access points that belong to the same Mobility " +"Domain" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:460 +msgid "Enables the Spanning Tree Protocol on this bridge" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:59 +msgid "Encapsulation limit" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:915 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:973 +msgid "Encapsulation mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:159 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:183 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1117 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1666 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:45 +msgid "Encryption" +msgstr "Chiframent" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:161 +msgid "Endpoint Host" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:165 +msgid "Endpoint Port" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/dropdown.htm:16 +msgid "Enter custom value" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/dropdown.htm:16 +msgid "Enter custom values" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:97 +msgid "Erasing..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:104 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:105 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:106 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:169 +msgid "Error" +msgstr "Error" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:30 +msgid "Errored seconds (ES)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2889 +#: modules/luci-compat/luasrc/model/network.lua:1433 +msgid "Ethernet Adapter" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2880 +#: modules/luci-compat/luasrc/model/network.lua:1423 +msgid "Ethernet Switch" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:270 +msgid "Every 30 seconds (slow, 0)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:271 +msgid "Every second (fast, 1)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:406 +msgid "Exclude interfaces" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:247 +msgid "Expand hosts" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:198 +msgid "Expecting a hexadecimal assignment hint" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:64 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:73 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:107 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:121 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:125 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:132 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:136 +msgid "Expecting: %s" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:48 +msgid "Expecting: non-empty value" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:50 +msgid "Expires" +msgstr "Expira" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:591 +msgid "" +"Expiry time of leased addresses, minimum is 2 minutes (2m)." +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:19 +msgid "External" +msgstr "Extèrne" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1482 +msgid "External R0 Key Holder List" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1486 +msgid "External R1 Key Holder List" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:146 +msgid "External system log server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:151 +msgid "External system log server port" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:156 +msgid "External system log server protocol" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:79 +msgid "Extra SSH command options" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:83 +msgid "Extra pppd options" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:81 +msgid "Extra sstpc options" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1456 +msgid "FT over DS" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1457 +msgid "FT over the Air" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1454 +msgid "FT protocol" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:87 +msgid "Failed to change the system password." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4122 +msgid "Failed to confirm apply within %ds, waiting for rollback…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:37 +msgid "Failed to execute \"/etc/init.d/%s %s\" action: %s" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2673 +msgid "File" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2620 +msgid "File not accessible" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2811 +msgid "Filename" +msgstr "Nom de fichièr" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:381 +msgid "Filename of the boot image advertised to clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:191 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:314 +msgid "Filesystem" +msgstr "Sistèma de fichièrs" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:213 +msgid "Filter private" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:218 +msgid "Filter useless" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:388 +msgid "Filtering for all slaves, no validation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:389 +msgid "Filtering for all slaves, validation only for active slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:390 +msgid "Filtering for all slaves, validation only for backup slaves" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:65 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:23 +msgid "Finalizing failed" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:150 +msgid "" +"Find all currently attached filesystems and swap and replace configuration " +"with defaults based on what was detected" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:820 +msgid "Find and join network" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:9 +msgid "Finish" +msgstr "Acabar" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:15 +msgid "Firewall" +msgstr "Parafuòc" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:102 +msgid "Firewall Mark" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:326 +msgid "Firewall Settings" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:297 +msgid "Firewall Status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:932 +msgid "Firmware File" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:57 +msgid "Firmware Version" +msgstr "Version del microcòdi" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:327 +msgid "Fixed source port for outbound DNS queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:283 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:421 +msgid "Flash image..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:279 +msgid "Flash image?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:411 +msgid "Flash new firmware image" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:356 +msgid "Flash operations" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:288 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:290 +msgid "Flashing…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:598 +msgid "Force" +msgstr "Fòrça" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:907 +msgid "Force 40MHz mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1158 +msgid "Force CCMP (AES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:598 +msgid "Force DHCP on this network even if another server is detected." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1159 +msgid "Force TKIP" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1160 +msgid "Force TKIP and CCMP (AES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:864 +msgid "Force link" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:255 +msgid "Force upgrade" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:90 +msgid "Force use of NAT-T" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:8 +msgid "Form token mismatch" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:164 +msgid "Forward DHCP traffic" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:29 +msgid "Forward Error Correction Seconds (FECS)" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:161 +msgid "Forward broadcast traffic" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:934 +msgid "Forward mesh peer traffic" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:980 +msgid "Forwarding mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:899 +msgid "Fragmentation Threshold" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:115 +msgid "" +"Further information about WireGuard interfaces and peers at wireguard.com." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:128 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:184 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:62 +msgid "GHz" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:91 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:77 +msgid "GPRS only" +msgstr "solament GPRS" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:10 +msgid "GRE tunnel over IPv4" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:10 +msgid "GRE tunnel over IPv6" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:10 +msgid "GRETAP tunnel over IPv4" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:10 +msgid "GRETAP tunnel over IPv6" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:44 +msgid "Gateway" +msgstr "Palanca" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:36 +msgid "Gateway Ports" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:11 +#: modules/luci-compat/luasrc/model/network.lua:29 +msgid "Gateway address is invalid" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:124 +msgid "Gateway metric" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:161 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:323 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:24 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:240 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:108 +msgid "General Settings" +msgstr "Paramètres generals" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:552 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:967 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:865 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:921 +msgid "General Setup" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:150 +msgid "Generate Config" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:66 +msgid "Generate Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1460 +msgid "Generate PMK locally" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:368 +msgid "Generate archive" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:79 +msgid "Given password confirmation did not match, password not changed!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:146 +msgid "Global Settings" +msgstr "Configuracion generala" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:875 +msgid "Global network options" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:57 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:215 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:58 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:82 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:284 +msgid "Go to password configuration..." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2562 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3336 +#: modules/luci-compat/luasrc/view/cbi/full_valueheader.htm:4 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:58 +msgid "Go to relevant configuration page" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:33 +msgid "Grant access to DHCP configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:102 +msgid "Grant access to DHCP status display" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:111 +msgid "Grant access to DSL status display" +msgstr "" + +#: protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json:3 +msgid "Grant access to LuCI OpenConnect procedures" +msgstr "" + +#: protocols/luci-proto-wireguard/root/usr/share/rpcd/acl.d/luci-wireguard.json:3 +msgid "Grant access to LuCI Wireguard procedures" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:19 +msgid "Grant access to SSH configuration" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:12 +msgid "Grant access to basic LuCI procedures" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:64 +msgid "Grant access to crontab configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:60 +msgid "Grant access to firewall status" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:116 +msgid "Grant access to flash operations" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:86 +msgid "Grant access to main status display" +msgstr "" + +#: protocols/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json:3 +msgid "Grant access to mmcli" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:84 +msgid "Grant access to mount configuration" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:3 +msgid "Grant access to network configuration" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:46 +msgid "Grant access to network diagnostic tools" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:36 +msgid "Grant access to network status information" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:13 +msgid "Grant access to process status" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:3 +msgid "Grant access to realtime statistics" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:42 +msgid "Grant access to startup configuration" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:3 +msgid "Grant access to system configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:30 +msgid "Grant access to system logs" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:47 +msgid "Grant access to the system route status" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:120 +msgid "Grant access to wireless status display" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:66 +msgid "Group Password" +msgstr "Senhal del grop" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:22 +msgid "Guest" +msgstr "Convidat" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:81 +msgid "HE.net password" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:73 +msgid "HE.net username" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:46 +msgid "Hang Up" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:34 +msgid "Header Error Code Errors (HEC)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/heartbeat.js:5 +msgid "Heartbeat interval (kernel: heartbeat)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:100 +msgid "" +"Here you can configure the basic aspects of your device like its hostname or " +"the timezone." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1066 +msgid "Hide ESSID" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:264 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:303 +msgid "Hide empty chains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:55 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2070 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:140 +msgid "Host" +msgstr "Òste" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:22 +msgid "Host entries" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:171 +msgid "Host expiry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +msgid "Host-IP or Network" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:102 +msgid "Host-Uniq tag content" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:36 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:419 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:27 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:54 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:29 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:121 +msgid "Hostname" +msgstr "Nom d'òste" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:22 +msgid "Hostname to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:20 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:63 +msgid "Hostnames" +msgstr "Noms d'òstes" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:24 +msgid "Hybrid" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:48 +msgid "ID used to uniquely identify the VXLAN" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:206 +msgid "IEEE 802.3ad Dynamic link aggregation (802.3ad, 4)" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:75 +msgid "IKE DH Group" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:83 +msgid "IP Addresses" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:80 +msgid "IP Protocol" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:114 +msgid "IP Type" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:31 +msgid "IP address" +msgstr "Adreça IP" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:10 +#: modules/luci-compat/luasrc/model/network.lua:28 +msgid "IP address is invalid" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:13 +#: modules/luci-compat/luasrc/model/network.lua:31 +msgid "IP address is missing" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:85 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:86 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:87 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:88 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:89 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:82 +msgid "IPv4" +msgstr "IPv4" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:316 +msgid "IPv4 Firewall" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:29 +msgid "IPv4 Upstream" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:178 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:162 +msgid "IPv4 address" +msgstr "Adreça IPv4" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:33 +msgid "IPv4 assignment length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:181 +msgid "IPv4 broadcast" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:180 +msgid "IPv4 gateway" +msgstr "Palanca IPv4" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:179 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:168 +msgid "IPv4 netmask" +msgstr "Masqueta ret IPv4" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:291 +msgid "IPv4 network in address/netmask notation" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:116 +msgid "IPv4 only" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:52 +msgid "IPv4 prefix" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:55 +msgid "IPv4 prefix length" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:83 +msgid "IPv4+IPv6" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:37 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:30 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:154 +msgid "IPv4-Address" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:164 +msgid "IPv4-Gateway" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ipip.lua:9 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:10 +msgid "IPv4-in-IPv4 (RFC2003)" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:115 +msgid "IPv4/IPv6 (both - defaults to IPv4)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:90 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:91 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:92 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:93 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:94 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:95 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:96 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:97 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:98 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:99 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:84 +msgid "IPv6" +msgstr "IPv6" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:319 +msgid "IPv6 Firewall" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:203 +msgid "IPv6 Neighbours" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:554 +msgid "IPv6 Settings" +msgstr "Paramètres IPv6" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:879 +msgid "IPv6 ULA-Prefix" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:29 +msgid "IPv6 Upstream" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:205 +msgid "IPv6 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:189 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:31 +msgid "IPv6 assignment hint" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:184 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:27 +msgid "IPv6 assignment length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:210 +msgid "IPv6 gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:296 +msgid "IPv6 network in address/netmask notation" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:117 +msgid "IPv6 only" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:59 +msgid "IPv6 prefix" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:63 +msgid "IPv6 prefix length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:214 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:57 +msgid "IPv6 routed prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:218 +msgid "IPv6 suffix" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:51 +msgid "IPv6 support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:57 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:172 +msgid "IPv6-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:100 +msgid "IPv6-PD" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:13 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:10 +msgid "IPv6-in-IPv4 (RFC4213)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:17 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:9 +msgid "IPv6-over-IPv4 (6rd)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:15 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:9 +msgid "IPv6-over-IPv4 (6to4)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1593 +msgid "Identity" +msgstr "Identitat" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:96 +msgid "If checked, 1DES is enabled" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:51 +msgid "If checked, adds \"+ipv6\" to the pppd options" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:93 +msgid "If checked, encryption is disabled" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:254 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:360 +msgid "" +"If specified, mount the device by its UUID instead of a fixed device node" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:267 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:376 +msgid "" +"If specified, mount the device by the partition label instead of a fixed " +"device node" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:37 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:116 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:48 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:85 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:65 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:49 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:33 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:67 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:80 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:108 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:150 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:74 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:61 +msgid "If unchecked, no default route is configured" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:40 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:124 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:39 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:116 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:68 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:59 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:103 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:77 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:100 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:69 +msgid "If unchecked, the advertised DNS server addresses are ignored" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:339 +msgid "" +"If your physical memory is insufficient unused data can be temporarily " +"swapped to a swap-device resulting in a higher amount of usable RAM. Be aware that swapping data is a very " +"slow process as the swap-device cannot be accessed with the high datarates " +"of the RAM." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:197 +msgid "Ignore /etc/hosts" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:579 +msgid "Ignore interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:185 +msgid "Ignore resolve file" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:419 +msgid "Image" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:67 +msgid "In" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:13 +msgid "" +"In order to prevent unauthorized access to the system, your request has been " +"blocked. Click \"Continue »\" below to return to the previous page." +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:157 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:141 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:115 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:138 +msgid "Inactivity timeout" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:265 +msgid "Inbound:" +msgstr "Dintrant :" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:90 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:97 +msgid "Incoming checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:82 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:87 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:89 +msgid "Incoming key" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:97 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:94 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:99 +msgid "Incoming serialization" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:166 +msgid "Info" +msgstr "Info" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:101 +msgid "Information" +msgstr "Informacion" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:67 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:25 +msgid "Initialization failure" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:77 +msgid "Initscript" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:111 +msgid "Initscripts" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1577 +msgid "Inner certificate constraint (Domain)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1574 +msgid "Inner certificate constraint (SAN)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1571 +msgid "Inner certificate constraint (Subject)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1580 +msgid "Inner certificate constraint (Wildcard)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:268 +msgid "Install protocol extensions..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1938 +msgid "" +"Instead of joining any network with a matching SSID, only connect to the " +"BSSID %h." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/map.htm:43 +msgid "Insufficient permissions to read UCI configuration." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:464 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:471 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:735 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:739 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:27 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:156 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:174 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:17 +msgid "Interface" +msgstr "Interfàcia" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:62 +msgid "Interface %q device auto-migrated from %q to %q." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:917 +msgid "Interface Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:110 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:151 +msgid "Interface has %d pending changes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:92 +msgid "Interface is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:64 +msgid "Interface is marked for deletion" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:209 +msgid "Interface is reconnecting..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:193 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:203 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:209 +msgid "Interface is shutting down..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:253 +msgid "Interface is starting..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:256 +msgid "Interface is stopping..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1079 +msgid "Interface name" +msgstr "Nom de l’interfàcia" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:122 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:272 +msgid "Interface not present or not connected yet." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:308 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:335 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:38 +msgid "Interfaces" +msgstr "Interfàcias" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:20 +msgid "Internal" +msgstr "Intèrne" + +#: modules/luci-base/luasrc/view/error500.htm:8 +msgid "Internal Server Error" +msgstr "Error intèrna de servidor" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:283 +msgid "Interval For Sending Learning Packets" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:192 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:42 +msgid "Invalid" +msgstr "Invalid" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:19 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:22 +msgid "Invalid Base64 key string" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:285 +msgid "Invalid VLAN ID given! Only IDs between %d and %d are allowed." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:294 +msgid "Invalid VLAN ID given! Only unique IDs are allowed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:403 +msgid "Invalid argument" +msgstr "Argument invalid" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:46 +msgid "" +"Invalid bearer list. Possibly too many bearers created. This protocol " +"supports one and only one bearer." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:402 +msgid "Invalid command" +msgstr "Comanda invalida" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:106 +msgid "Invalid hexadecimal value" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:12 +msgid "Invalid username and/or password! Please try again." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:71 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:81 +msgid "Invalid value" +msgstr "La valor es pas valida" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1075 +msgid "Isolate Clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:231 +msgid "" +"It appears that you are trying to flash an image that does not fit into the " +"flash memory, please verify the image file!" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:64 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:222 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:72 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:291 +msgid "JavaScript required!" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1746 +msgid "Join Network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1680 +msgid "Join Network: Wireless Scan" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1946 +msgid "Joining Network: %q" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:223 +msgid "Keep settings and retain the current configuration" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/dmesg.js:20 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:51 +msgid "Kernel Log" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:58 +msgid "Kernel Version" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1369 +msgid "Key" +msgstr "Clau" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1397 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1398 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1399 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1400 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1412 +msgid "Key #%d" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:82 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:87 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:89 +msgid "Key for incoming packets (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:86 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:88 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:93 +msgid "Key for outgoing packets (optinal)." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:54 +msgid "Kill" +msgstr "Tuar" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:21 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:10 +msgid "L2TP" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:40 +msgid "L2TP Server" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:267 +msgid "LACPDU Packets" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:131 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:102 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:89 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:112 +msgid "LCP echo failure threshold" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:144 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:102 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:125 +msgid "LCP echo interval" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:101 +msgid "LED Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:974 +msgid "LLC" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:267 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:376 +msgid "Label" +msgstr "Etiqueta" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:209 +msgid "Language" +msgstr "Lenga" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:111 +msgid "Language and Style" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:24 +msgid "Latency" +msgstr "Laténcia" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:21 +msgid "Leaf" +msgstr "Fuèlha" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:495 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:591 +msgid "Lease time" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:39 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:58 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:32 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:59 +msgid "Lease time remaining" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:181 +msgid "Leasefile" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:41 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:47 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:50 +msgid "Leave empty to autodetect" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:45 +msgid "Leave empty to use the current WAN address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4030 +msgid "Legend:" +msgstr "Legenda :" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:586 +msgid "Limit" +msgstr "Limit" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:389 +msgid "Limit DNS service to subnets interfaces on which we are serving DNS." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:402 +msgid "Limit listening to these interfaces, and loopback." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:25 +msgid "Line Attenuation (LATN)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:18 +msgid "Line Mode" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:17 +msgid "Line State" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:19 +msgid "Line Uptime" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:123 +msgid "Link Aggregation (Channel Bonding)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:348 +msgid "Link Monitoring" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:23 +msgid "Link On" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:278 +msgid "" +"List of DNS servers to forward " +"requests to" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1482 +msgid "" +"List of R0KHs in the same Mobility Domain.
Format: MAC-address,NAS-" +"Identifier,128-bit key as hex string.
This list is used to map R0KH-ID " +"(NAS Identifier) to a destination MAC address when requesting PMK-R1 key " +"from the R0KH that the STA used during the Initial Mobility Domain " +"Association." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1486 +msgid "" +"List of R1KHs in the same Mobility Domain.
Format: MAC-address,R1KH-ID " +"as 6 octets with colons,128-bit key as hex string.
This list is used " +"to map R1KH-ID to a destination MAC address when sending PMK-R1 key from the " +"R0KH. This is also the list of authorized R1KHs in the MD that can request " +"PMK-R1 keys." +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:82 +msgid "List of SSH key files for auth" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:308 +msgid "List of domains to allow RFC1918 responses for" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:286 +msgid "List of domains to force to an IP address." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:267 +msgid "List of hosts that supply bogus NX domain results" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:401 +msgid "Listen Interfaces" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:78 +msgid "Listen Port" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:17 +msgid "Listen only on the given interface or, if unspecified, on all" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:318 +msgid "Listening port for inbound DNS queries" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:87 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:54 +msgid "Load" +msgstr "Carga" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:61 +msgid "Load Average" +msgstr "Carga mejana" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2938 +msgid "Loading directory contents…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:1948 +#: modules/luci-base/luasrc/view/view.htm:4 +#: modules/luci-mod-status/luasrc/view/admin_status/index.htm:12 +msgid "Loading view…" +msgstr "" + +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:77 +msgid "Local IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:12 +#: modules/luci-compat/luasrc/model/network.lua:30 +msgid "Local IP address is invalid" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:86 +msgid "Local IP address to assign" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:46 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:44 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:39 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:151 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:44 +msgid "Local IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:46 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:54 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:45 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:44 +msgid "Local IPv6 address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:388 +msgid "Local Service Only" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:115 +msgid "Local Startup" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:59 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:117 +msgid "Local Time" +msgstr "Ora locala" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:243 +msgid "Local domain" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:240 +msgid "" +"Local domain specification. Names matching this domain are never forwarded " +"and are resolved from DHCP or hosts files only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:244 +msgid "Local domain suffix appended to DHCP names and hosts file entries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:239 +msgid "Local server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:224 +msgid "" +"Localise hostname depending on the requesting subnet if multiple IPs are " +"available" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:223 +msgid "Localise queries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1938 +msgid "Lock to BSSID" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:164 +msgid "Log output level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:274 +msgid "Log queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:109 +msgid "Logging" +msgstr "Jornalizacion" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:50 +msgid "" +"Logical network from which to select the local endpoint if local IPv6 " +"address is empty and no WAN IPv6 is available (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:55 +msgid "Logical network to which the tunnel will be added (bridged) (optional)." +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:38 +msgid "Login" +msgstr "Connexion" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:81 +msgid "Logout" +msgstr "Desconnexion" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:32 +msgid "Loss of Signal Seconds (LOSS)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:581 +msgid "Lowest leased address as offset from the network address." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:47 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:82 +msgid "MAC" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:251 +msgid "MAC Address For The Actor" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:38 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2069 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:31 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:139 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:155 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:173 +msgid "MAC-Address" +msgstr "Adreça MAC" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1011 +msgid "MAC-Address Filter" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:923 +msgid "MAC-Filter" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1018 +msgid "MAC-List" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:16 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:13 +msgid "MAP / LW4over6" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:62 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:7 +msgid "MAP rule is invalid" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:321 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:322 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:323 +msgid "MBit/s" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:218 +msgid "MD5" +msgstr "MD5" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:199 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:71 +msgid "MHz" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:353 +msgid "MII" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:421 +msgid "MII / ETHTOOL ioctls" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:394 +msgid "MII Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:54 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:53 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:97 +msgid "MTU" +msgstr "MTU" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:302 +msgid "" +"Make sure to clone the root filesystem using something like the commands " +"below:" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:108 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:52 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:96 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:83 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:57 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:70 +msgid "Manual" +msgstr "Manual" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3664 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:642 +msgid "Master" +msgstr "Principal" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:23 +msgid "Max. Attainable Data Rate (ATTNDR)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1107 +msgid "Maximum allowed Listen Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:336 +msgid "Maximum allowed number of active DHCP leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:354 +msgid "Maximum allowed number of concurrent DNS queries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:345 +msgid "Maximum allowed size of EDNS.0 UDP packets" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:112 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:104 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:93 +msgid "Maximum amount of seconds to wait for the modem to become ready" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:586 +msgid "Maximum number of leased addresses." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:886 +msgid "Maximum transmit power" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:188 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:199 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:63 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:71 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:327 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:328 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:329 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:35 +msgid "Medium" +msgstr "Mejan" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:24 +msgid "Memory" +msgstr "Memòria" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:73 +msgid "Memory usage (%)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3667 +msgid "Mesh" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:156 +msgid "Mesh ID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:931 +msgid "Mesh Id" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:404 +msgid "Method not found" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:349 +msgid "Method of link monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:418 +msgid "Method to determine link status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:165 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:183 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:92 +msgid "Metric" +msgstr "Metric" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:235 +msgid "Minimum Number of Links" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:202 +msgid "Mirror monitor port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:201 +msgid "Mirror source port" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:9 +msgid "Mobile Data" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1442 +msgid "Mobility Domain" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:154 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:157 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:180 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:442 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:926 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1664 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:43 +msgid "Mode" +msgstr "Mòde" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:55 +msgid "Model" +msgstr "Modèl" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:43 +msgid "Modem bearer teardown in progress." +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:42 +msgid "" +"Modem connection in progress. Please wait. This process will timeout after 2 " +"minutes." +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:72 +msgid "Modem default" +msgstr "Modem per defaut" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:73 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:82 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:73 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:57 +msgid "Modem device" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:41 +msgid "Modem disconnection in progress. Please wait." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:66 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:24 +msgid "Modem information query failed" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:112 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:104 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:93 +msgid "Modem init timeout" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:44 +msgid "Modem is disabled." +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:52 +msgid "ModemManager" +msgstr "ModemManager" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3668 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1005 +msgid "Monitor" +msgstr "Monitor" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:31 +msgid "More Characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2504 +msgid "More…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:192 +msgid "Mount Point" +msgstr "Punt de montatge" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:144 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:228 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:88 +msgid "Mount Points" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:229 +msgid "Mount Points - Mount Entry" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:340 +msgid "Mount Points - Swap Entry" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:228 +msgid "" +"Mount Points define at which point a memory device will be attached to the " +"filesystem" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:154 +msgid "Mount attached devices" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:162 +msgid "Mount filesystems not specifically configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:331 +msgid "Mount options" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:292 +msgid "Mount point" +msgstr "Punt de montatge" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:158 +msgid "Mount swap not specifically configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:223 +msgid "Mounted file systems" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:152 +msgid "Move down" +msgstr "Desplaçar cap aval" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:151 +msgid "Move up" +msgstr "Desplaçar cap amont" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1437 +msgid "NAS ID" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:87 +msgid "NAT-T Mode" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:41 +msgid "NAT64 Prefix" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:26 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:31 +msgid "NCM" +msgstr "NCM" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:637 +msgid "NDP-Proxy" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:72 +msgid "NT Domain" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:274 +msgid "NTP server candidates" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2542 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3785 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:27 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:710 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:67 +msgid "Name" +msgstr "Nom" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1916 +msgid "Name of the new network" +msgstr "" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:40 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:50 +msgid "Navigation" +msgstr "Navigacion" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:959 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2068 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:381 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:63 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:138 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:162 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:180 +msgid "Network" +msgstr "Ret" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:68 +msgid "Network Utilities" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:380 +msgid "Network boot image" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:7 +msgid "Network device activity (kernel: netdev)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:15 +#: modules/luci-compat/luasrc/model/network.lua:33 +msgid "Network device is not present" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:55 +msgid "Network interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:777 +msgid "New interface for \"%s\" can not be created: %s" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:713 +msgid "New interface name…" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:11 +msgid "Next »" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3643 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:296 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:345 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:108 +msgid "No" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:562 +msgid "No DHCP Server configured for this interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1310 +msgid "No Encryption" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:87 +msgid "No Host Routes" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:89 +msgid "No NAT-T" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:79 +msgid "No RX signal" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:69 +msgid "No client associated" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:406 +msgid "No data received" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2878 +msgid "No entries in this directory" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:82 +msgid "No files found" +msgstr "Pas cap de fichièr trobat" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:79 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:81 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:86 +msgid "No host route" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:674 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:142 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:241 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:59 +msgid "No information available" +msgstr "Pas cap d'informacion disponibla" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:63 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:8 +msgid "No matching prefix delegation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:140 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:143 +msgid "No more slaves available" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:187 +msgid "No more slaves available, can not save interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:251 +msgid "No negative cache" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:54 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:212 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:55 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:79 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:279 +msgid "No password set!" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:130 +msgid "No peers defined yet" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:121 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:268 +msgid "No public keys present yet." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:90 +msgid "No rules in this chain." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:384 +msgid "No validation or filtering" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:152 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:825 +msgid "No zone assigned" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:58 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:84 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:187 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:141 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:174 +msgid "Noise" +msgstr "Bruch" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:27 +msgid "Noise Margin (SNR)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:270 +msgid "Noise:" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:35 +msgid "Non Pre-emptive CRC errors (CRC_P)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:394 +msgid "Non-wildcard" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:159 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:183 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:100 +msgid "None" +msgstr "Cap" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:177 +msgid "Normal" +msgstr "Normala" + +#: modules/luci-base/luasrc/view/error404.htm:8 +msgid "Not Found" +msgstr "Pas trobat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:75 +msgid "Not associated" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:32 +msgid "Not connected" +msgstr "Pas connectat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:120 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:146 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:280 +msgid "Not present" +msgstr "Pas present" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:101 +msgid "Not started on boot" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:409 +msgid "Not supported" +msgstr "Pas pres en carga" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:167 +msgid "Notice" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:127 +msgid "Nslookup" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:332 +msgid "Number of IGMP membership reports" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:362 +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:199 +msgid "Number of parallel threads used for compression" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:309 +msgid "Number of peer notifications after failover event" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:69 +msgid "Obfuscated Group Password" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:61 +msgid "Obfuscated Password" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:105 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:97 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:49 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:80 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:54 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:67 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:93 +msgid "Obtain IPv6-Address" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:18 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:351 +msgid "Off" +msgstr "Desactivat" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:15 +msgid "Off-State Delay" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:18 +msgid "On" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:96 +msgid "On-Link route" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:11 +msgid "On-State Delay" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:484 +msgid "One of hostname or mac address must be specified!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:466 +msgid "One of the following: %s" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/nullsection.htm:17 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:22 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/map.htm:32 +msgid "One or more invalid/required values on tab" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/nullsection.htm:19 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:24 +msgid "One or more required fields have no value!" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:229 +msgid "" +"Only if current active slave fails and the primary slave is up (failure, 2)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:444 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:19 +msgid "Open list..." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_openconnect.lua:9 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:64 +msgid "OpenConnect (CISCO AnyConnect)" +msgstr "" + +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:12 +msgid "OpenFortivpn" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:882 +msgid "Operating frequency" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:1971 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3653 +msgid "Option \"%s\" contains an invalid input value." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:1984 +msgid "Option \"%s\" must not be empty." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4037 +msgid "Option changed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4039 +msgid "Option removed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1609 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:92 +msgid "Optional" +msgstr "Opcional" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:102 +msgid "" +"Optional. 32-bit mark for outgoing encrypted packets. Enter value in hex, " +"starting with 0x." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:218 +msgid "" +"Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or " +"'::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating " +"server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') " +"for the interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:143 +msgid "" +"Optional. Base64-encoded preshared key. Adds in an additional layer of " +"symmetric-key cryptography for post-quantum resistance." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:159 +msgid "Optional. Create routes for Allowed IPs for this peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:134 +msgid "Optional. Description of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:87 +msgid "Optional. Do not create host routes to peers." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:161 +msgid "" +"Optional. Host of peer. Names are resolved prior to bringing up the " +"interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:97 +msgid "Optional. Maximum Transmission Unit of tunnel interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:165 +msgid "Optional. Port of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:169 +msgid "" +"Optional. Seconds between keep alive messages. Default is 0 (disabled). " +"Recommended value if this device is behind a NAT is 25." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:78 +msgid "Optional. UDP port used for outgoing and incoming packets." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:71 +msgid "Options" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:346 +msgid "Other:" +msgstr "Autre :" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:68 +msgid "Out" +msgstr "Sortissant" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:275 +msgid "Outbound:" +msgstr "Sortent :" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:96 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:98 +msgid "Outgoing checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:86 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:88 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:93 +msgid "Outgoing key" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:98 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:100 +msgid "Outgoing serialization" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:50 +msgid "Output Interface" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:59 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:165 +msgid "Output zone" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:57 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:222 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:50 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:76 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:71 +msgid "Override MAC address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:61 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:226 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:67 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:44 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:54 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:120 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:158 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:71 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:145 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:132 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:110 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:119 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:77 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:62 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:57 +msgid "Override MTU" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:72 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:63 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:72 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:67 +msgid "Override TOS" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:72 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:58 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:67 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:62 +msgid "Override TTL" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1079 +msgid "Override default interface name" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:167 +msgid "Override the gateway in DHCP responses" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:603 +msgid "" +"Override the netmask sent to clients. Normally it is calculated from the " +"subnet that is served." +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 +msgid "Override the table used for internal routes" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:3 +msgid "Overview" +msgstr "Apercebut" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2721 +msgid "Overwrite existing file \"%s\" ?" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:70 +msgid "Owner" +msgstr "Proprietari" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:97 +msgid "PAP/CHAP (both)" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:98 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:108 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:45 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:44 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:63 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:82 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:46 +msgid "PAP/CHAP password" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:96 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:103 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:88 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:43 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:74 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:42 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:61 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:77 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:44 +msgid "PAP/CHAP username" +msgstr "Identificant PAP / CHAP" + +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:101 +msgid "PDP Type" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:69 +msgid "PID" +msgstr "PID" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:95 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:94 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:87 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:68 +msgid "PIN" +msgstr "Còdi personal" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:21 +#: modules/luci-compat/luasrc/model/network.lua:39 +msgid "PIN code rejected" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1477 +msgid "PMK R1 Push" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:13 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:43 +msgid "PPP" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:58 +msgid "PPPoA Encapsulation" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:19 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:28 +msgid "PPPoATM" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:17 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:28 +msgid "PPPoE" +msgstr "PPPoE" + +#: modules/luci-compat/luasrc/model/network/proto_pppossh.lua:9 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:28 +msgid "PPPoSSH" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:15 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:28 +msgid "PPtP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:73 +msgid "PSID offset" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:70 +msgid "PSID-bits length" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:918 +msgid "PTM/EFM (Packet Transfer Mode)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:882 +msgid "Packet Steering" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +msgid "Packets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:275 +msgid "Packets To Transmit Before Moving To Next Slave" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:152 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:825 +msgid "Part of zone %q" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:29 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1599 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:51 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:108 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:52 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:58 +msgid "Password" +msgstr "Senhal" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:25 +msgid "Password authentication" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1531 +msgid "Password of Private Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1589 +msgid "Password of inner Private Key" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:31 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:33 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:35 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:37 +msgid "Password strength" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:111 +msgid "Password2" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:239 +msgid "Paste or drag SSH key file…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1510 +msgid "Path to CA-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1525 +msgid "Path to Client-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1528 +msgid "Path to Private Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1568 +msgid "Path to inner CA-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1583 +msgid "Path to inner Client-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1586 +msgid "Path to inner Private Key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2731 +msgid "Paused" +msgstr "En pausa" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:271 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:281 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:332 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:342 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:352 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:237 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:247 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:257 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:266 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:276 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:294 +msgid "Peak:" +msgstr "Punta :" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:89 +msgid "Peer IP address to assign" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:14 +#: modules/luci-compat/luasrc/model/network.lua:32 +msgid "Peer address is missing" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:115 +msgid "Peers" +msgstr "Pars" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:80 +msgid "Perfect Forward Secrecy" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:98 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:100 +msgid "Perform outgoing packets serialization (optional)." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:34 +msgid "Perform reboot" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:378 +msgid "Perform reset" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:407 +msgid "Permission denied" +msgstr "Permission refusada" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:169 +msgid "Persistent Keep Alive" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:288 +msgid "Phy Rate:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:325 +msgid "Physical Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:90 +msgid "Ping" +msgstr "Ping" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:48 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:49 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:83 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:84 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:138 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:63 +msgid "Pkts." +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:19 +msgid "Please enter your username and password." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3768 +msgid "Please select the file to upload." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +msgid "Policy" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:21 +msgid "Port" +msgstr "Pòrt" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:278 +msgid "Port status:" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:492 +msgid "Potential negation of: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:38 +msgid "Power Management Mode" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:36 +msgid "Pre-emptive CRC errors (CRCP_P)" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:73 +msgid "Prefer LTE" +msgstr "Preferir LTE" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:74 +msgid "Prefer UMTS" +msgstr "Preferir UMTS" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:33 +msgid "Prefix Delegated" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:143 +msgid "Preshared Key" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:131 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:102 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:89 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:112 +msgid "" +"Presume peer to be dead after given amount of LCP echo failures, use 0 to " +"ignore failures" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:407 +msgid "Prevent listening on these interfaces." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1075 +msgid "Prevents client-to-client communication" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:211 +msgid "Primary Slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:228 +msgid "" +"Primary becomes active slave when it comes back up if speed and duplex " +"better than current slave (better, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:227 +msgid "Primary becomes active slave whenever it comes back up (always, 0)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:61 +msgid "Private Key" +msgstr "Clau privada" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:64 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:63 +msgid "Processes" +msgstr "Processus" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:21 +msgid "Profile" +msgstr "Perfil" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:66 +msgid "Prot." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:397 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:727 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:382 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:32 +msgid "Protocol" +msgstr "Protocòl" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:265 +msgid "Provide NTP server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:825 +msgid "Provide new network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1004 +msgid "Pseudo Ad-Hoc (ahdemo)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:139 +msgid "Public Key" +msgstr "Clau publica" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:275 +msgid "" +"Public keys allow for the passwordless SSH logins with a higher security " +"compared to the use of plain passwords. In order to upload a new key to the " +"device, paste an OpenSSH compatible public key line or drag a .pub file into the input field." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:214 +msgid "Public prefix routed to this device for distribution to clients." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:9 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:27 +msgid "QMI Cellular" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:41 +msgid "Quality" +msgstr "Qualitat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:264 +msgid "" +"Query all available upstream DNS " +"servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1465 +msgid "R0 Key Lifetime" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1471 +msgid "R1 Key Holder" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:88 +msgid "RFC3947 NAT-T mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:939 +msgid "RSSI threshold for joining" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:903 +msgid "RTS/CTS Threshold" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:48 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:83 +msgid "RX" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:142 +msgid "RX Rate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2072 +msgid "RX Rate / TX Rate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1343 +msgid "Radius-Accounting-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1348 +msgid "Radius-Accounting-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1338 +msgid "Radius-Accounting-Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1328 +msgid "Radius-Authentication-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1333 +msgid "Radius-Authentication-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1323 +msgid "Radius-Authentication-Server" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:102 +msgid "Raw hex-encoded bytes. Leave empty unless your ISP require this" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:178 +msgid "" +"Read /etc/ethers to configure the DHCP-Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:402 +msgid "Really switch protocol?" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:75 +msgid "Realtime Graphs" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1448 +msgid "Reassociation Deadline" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:293 +msgid "Rebind protection" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:20 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:126 +msgid "Reboot" +msgstr "Reaviar" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:153 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:162 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:46 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:51 +msgid "Rebooting…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:21 +msgid "Reboots the operating system of your device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:25 +msgid "Receive" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:83 +msgid "Recommended. IP addresses of the WireGuard interface." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:348 +msgid "Reconnect this interface" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:56 +msgid "References" +msgstr "Referéncias" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2725 +msgid "Refreshing" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:153 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:39 +msgid "Relay" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:157 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:36 +msgid "Relay Bridge" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:154 +msgid "Relay between networks" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:12 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:64 +msgid "Relay bridge" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:50 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:49 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:40 +msgid "Remote IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:42 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:40 +msgid "Remote IPv4 address or FQDN" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:40 +msgid "Remote IPv6 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:42 +msgid "Remote IPv6 address or FQDN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:849 +msgid "Remove" +msgstr "Levar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1914 +msgid "Replace wireless configuration" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:17 +msgid "Request IPv6-address" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:23 +msgid "Request IPv6-prefix of length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:408 +msgid "Request timeout" +msgstr "Temps passat per la requèsta" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:90 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:97 +msgid "Require incoming checksum (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:97 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:94 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:99 +msgid "Require incoming packets serialization (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1610 +msgid "Required" +msgstr "Requesit" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:34 +msgid "Required for certain ISPs, e.g. Charter with DOCSIS 3" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:61 +msgid "Required. Base64-encoded private key for this interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:139 +msgid "Required. Base64-encoded public key of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:148 +msgid "" +"Required. IP addresses and prefixes that this peer is allowed to use inside " +"the tunnel. Usually the peer's tunnel IP addresses and the networks the peer " +"routes through the tunnel." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1239 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1240 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1241 +msgid "Requires hostapd" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1246 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1247 +msgid "Requires hostapd with EAP Suite-B support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1244 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1245 +msgid "Requires hostapd with EAP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1248 +msgid "Requires hostapd with OWE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1242 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1243 +msgid "Requires hostapd with SAE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1237 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1238 +msgid "Requires hostapd with WEP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1607 +msgid "" +"Requires the 'full' version of wpad/hostapd and support from the wifi driver " +"
(as of Jan 2019: ath9k, ath10k, mwlwifi and mt76)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:233 +msgid "" +"Requires upstream supports DNSSEC; verify unsigned domain responses really " +"come from unsigned domains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1253 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1254 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1255 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1267 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1268 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1269 +msgid "Requires wpa-supplicant" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1260 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1261 +msgid "Requires wpa-supplicant with EAP Suite-B support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1258 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1259 +msgid "Requires wpa-supplicant with EAP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1262 +msgid "Requires wpa-supplicant with OWE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1256 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1257 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1272 +msgid "Requires wpa-supplicant with SAE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1251 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1252 +msgid "Requires wpa-supplicant with WEP support" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:224 +msgid "Reselection policy for primary slave" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2203 +#: modules/luci-base/luasrc/view/sysauth.htm:39 +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:17 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:30 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:66 +msgid "Reset" +msgstr "Reinicializar" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:308 +msgid "Reset Counters" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:376 +msgid "Reset to defaults" +msgstr "Reïnicializar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:162 +msgid "Resolv and Hosts Files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:188 +msgid "Resolve file" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:405 +msgid "Resource not found" +msgstr "Ressorsa introbabla" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:350 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:817 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:100 +msgid "Restart" +msgstr "Reaviar" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:313 +msgid "Restart Firewall" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:815 +msgid "Restart radio interface" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:372 +msgid "Restore" +msgstr "Restablir" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:382 +msgid "Restore backup" +msgstr "Restaurar salvagarda" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:371 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:372 +msgid "Reveal/hide password" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4053 +msgid "Revert" +msgstr "Tornar" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4138 +msgid "Revert changes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4320 +msgid "Revert request failed with status %h" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4300 +msgid "Reverting configuration…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:372 +msgid "Root directory for files served via TFTP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:297 +msgid "Root preparation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:202 +msgid "Round-Robin policy (balance-rr, 0)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:159 +msgid "Route Allowed IPs" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:73 +msgid "Route table" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:60 +msgid "Route type" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:625 +msgid "Router Advertisement-Service" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:46 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:26 +msgid "Router Password" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:15 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:194 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:27 +msgid "Routes" +msgstr "Rotas" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:15 +msgid "" +"Routes specify over which interface and gateway a certain host or network " +"can be reached." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:206 +msgid "Rule" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:335 +msgid "Run a filesystem check before mounting the device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:335 +msgid "Run filesystem check" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2364 +msgid "Runtime error" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:219 +msgid "SHA256" +msgstr "SHA256" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:59 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:175 +msgid "SNR" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:10 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:38 +msgid "SSH Access" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:70 +msgid "SSH server address" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:74 +msgid "SSH server port" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:58 +msgid "SSH username" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:274 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:51 +msgid "SSH-Keys" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:156 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:181 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1662 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:42 +msgid "SSID" +msgstr "SSID" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:9 +msgid "SSTP" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:41 +msgid "SSTP Server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:339 +msgid "SWAP" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2866 +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2198 +#: modules/luci-compat/luasrc/view/cbi/error.htm:17 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:26 +#: modules/luci-compat/luasrc/view/cbi/header.htm:20 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:435 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:123 +msgid "Save" +msgstr "Salvagardar" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2180 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4049 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:22 +msgid "Save & Apply" +msgstr "Salvagardar e aplicar" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:602 +msgid "Save error" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:406 +msgid "Save mtdblock" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:396 +msgid "Save mtdblock contents" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:822 +msgid "Scan" +msgstr "Analisar" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:26 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:76 +msgid "Scheduled Tasks" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4033 +msgid "Section added" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4035 +msgid "Section removed" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:331 +msgid "See \"mount\" manpage for details" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:257 +msgid "" +"Select 'Force upgrade' to flash the image even if the image format check " +"fails. Use only if you are sure that the firmware is correct and meant for " +"your device!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2622 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2762 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2927 +msgid "Select file…" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:318 +msgid "Selects the transmit hash policy to use for slave selection" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:144 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:102 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:125 +msgid "" +"Send LCP echo requests at the given interval in seconds, only effective in " +"conjunction with failure threshold" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:24 +msgid "Send the hostname of this device" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:157 +msgid "Server Settings" +msgstr "Paramètres del servidor" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:50 +msgid "Service Name" +msgstr "Nom de servici" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:87 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:71 +msgid "Service Type" +msgstr "Tipe de servici" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:36 +msgid "Services" +msgstr "Servicis" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2668 +msgid "Session expired" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:107 +msgid "Set VPN as Default Route" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:864 +msgid "" +"Set interface properties regardless of the link carrier (If set, carrier " +"sense events do not invoke hotplug handlers)." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:300 +msgid "Set same MAC Address to all slaves" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:642 +msgid "Set this interface as master for the dhcpv6 relay." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:304 +msgid "Set to currently active slave (active, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:305 +msgid "Set to first slave added to the bond (follow, 2)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:55 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:55 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:23 +msgid "Setting PLMN failed" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:68 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:26 +msgid "Setting operation mode failed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:565 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:575 +msgid "Setup DHCP Server" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:31 +msgid "Severely Errored Seconds (SES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:208 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:80 +msgid "Short GI" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1085 +msgid "Short Preamble" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:442 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:18 +msgid "Show current backup file list" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:264 +msgid "Show empty chains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:354 +msgid "Shutdown this interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:57 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:63 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:186 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1661 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:41 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:141 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:173 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:179 +msgid "Signal" +msgstr "Senhal" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2071 +msgid "Signal / Noise" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:26 +msgid "Signal Attenuation (SATN)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:260 +msgid "Signal:" +msgstr "Senhal :" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3786 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:217 +msgid "Size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:361 +msgid "Size of DNS query cache" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:187 +msgid "Size of the ZRam device in megabytes" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/footer.htm:18 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:57 +msgid "Skip" +msgstr "Ignorar" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:36 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:46 +msgid "Skip to content" +msgstr "" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:35 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:45 +msgid "Skip to navigation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:178 +msgid "Slave Interfaces" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2883 +#: modules/luci-compat/luasrc/model/network.lua:1428 +msgid "Software VLAN" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/header.htm:5 +msgid "Some fields are invalid, cannot save values!" +msgstr "" + +#: modules/luci-base/luasrc/view/error404.htm:9 +msgid "Sorry, the object you requested was not found." +msgstr "" + +#: modules/luci-base/luasrc/view/error500.htm:9 +msgid "Sorry, the server encountered an unexpected error." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:414 +msgid "" +"Sorry, there is no sysupgrade support present; a new firmware image must be " +"flashed manually. Please refer to the wiki for device specific install " +"instructions." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:383 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:69 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:182 +msgid "Source" +msgstr "Font" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:84 +msgid "Source Address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:50 +msgid "Source interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:342 +msgid "" +"Specifies that duplicate frames (received on inactive ports) should be " +"dropped or delivered" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:358 +msgid "Specifies the ARP link monitoring frequency in milliseconds" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:366 +msgid "Specifies the IP addresses to use for ARP monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:395 +msgid "Specifies the MII link monitoring frequency in milliseconds" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:259 +msgid "Specifies the aggregation selection logic to use" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:292 +msgid "Specifies the directory the device is attached to" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:252 +msgid "" +"Specifies the mac-address for the actor in protocol packet exchanges " +"(LACPDUs). If empty, masters' mac address defaults to system default" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:175 +msgid "" +"Specifies the maximum amount of failed ARP requests until hosts are presumed " +"to be dead" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:171 +msgid "" +"Specifies the maximum amount of seconds after which hosts are presumed to be " +"dead" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:886 +msgid "" +"Specifies the maximum transmit power the wireless radio may use. Depending " +"on regulatory requirements and wireless usage, the actual transmit power may " +"be reduced by the driver." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:236 +msgid "" +"Specifies the minimum number of links that must be active before asserting " +"carrier" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:200 +msgid "Specifies the mode to be used for this bonding interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:333 +msgid "" +"Specifies the number of IGMP membership reports to be issued after a " +"failover event in 200ms intervals" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:276 +msgid "" +"Specifies the number of packets to transmit through a slave before moving to " +"the next one" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:310 +msgid "" +"Specifies the number of peer notifications (gratuitous ARPs and unsolicited " +"IPv6 Neighbor Advertisements) to be issued after a failover event" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:284 +msgid "" +"Specifies the number of seconds between instances where the bonding driver " +"sends learning packets to each slaves peer switch" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:374 +msgid "Specifies the quantity of ARP IP targets that must be reachable" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:268 +msgid "" +"Specifies the rate in which the link partner will be asked to transmit " +"LACPDU packets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:225 +msgid "" +"Specifies the reselection policy for the primary slave when failure of the " +"active slave or recovery of the primary slave occurs" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:244 +msgid "Specifies the system priority" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:403 +msgid "" +"Specifies the time in milliseconds to wait before disabling a slave after a " +"link failure detection" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:411 +msgid "" +"Specifies the time in milliseconds to wait before enabling a slave after a " +"link recovery detection" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:382 +msgid "" +"Specifies whether ARP probes and replies should be validated or non-ARP " +"traffic should be filtered for link monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:301 +msgid "" +"Specifies whether active-backup mode should set all slaves to the same MAC " +"address at enslavement" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:419 +msgid "" +"Specifies whether or not miimon should use MII or ETHTOOL ioctls vs. " +"netif_carrier_ok()" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:293 +msgid "" +"Specifies whether to shuffle active flows across slaves based on the load" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:179 +msgid "" +"Specifies which slave interfaces should be attached to this bonding interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:212 +msgid "" +"Specifies which slave is the primary device. It will always be the active " +"slave while it is available" +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:63 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:72 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:67 +msgid "Specify a TOS (Type of Service)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:72 +msgid "" +"Specify a TOS (Type of Service). Can be either inherit (the " +"outer header inherits the value of the inner header) or an hexadecimal value " +"starting with 0x (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:72 +msgid "" +"Specify a TTL (Time to Live) for the encapsulating packet other than the " +"default (64) (optional)." +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:58 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:67 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:62 +msgid "" +"Specify a TTL (Time to Live) for the encapsulating packet other than the " +"default (64)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:72 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:77 +msgid "" +"Specify a Traffic Class. Can be either inherit (the outer " +"header inherits the value of the inner header) or an hexadecimal value " +"starting with 0x (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:67 +msgid "" +"Specify an MTU (Maximum Transmission Unit) other than the default (1280 " +"bytes) (optional)." +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:62 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:57 +msgid "" +"Specify an MTU (Maximum Transmission Unit) other than the default (1280 " +"bytes)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "Specify the secret encryption key here." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:581 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:99 +msgid "Start" +msgstr "Debuta" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:76 +msgid "Start priority" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1765 +msgid "Start refresh" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4253 +msgid "Starting configuration apply…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1678 +msgid "Starting wireless scan..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:109 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:64 +msgid "Startup" +msgstr "Aviada" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:19 +msgid "Static IPv4 Routes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:19 +msgid "Static IPv6 Routes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:165 +msgid "Static Leases" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:76 +msgid "Static Routes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1981 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:172 +#: modules/luci-compat/luasrc/model/network.lua:967 +msgid "Static address" +msgstr "Adreça estatica" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:411 +msgid "" +"Static leases are used to assign fixed IP addresses and symbolic hostnames " +"to DHCP clients. They are also required for non-dynamic interface " +"configurations where only hosts with a corresponding lease are served." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1102 +msgid "Station inactivity limit" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:16 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:385 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:871 +#: modules/luci-mod-status/luasrc/view/admin_status/index.htm:9 +msgid "Status" +msgstr "Estatut" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:356 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:101 +msgid "Stop" +msgstr "Arrestar" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1676 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1770 +msgid "Stop refresh" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:259 +msgid "Strict order" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:33 +msgid "Strong" +msgstr "Fòrt" + +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:61 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1956 +msgid "Submit" +msgstr "Sometre" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:203 +msgid "Suppress logging" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:204 +msgid "Suppress logging of the routine operation of these protocols" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:44 +msgid "Swap free" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:139 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:3 +msgid "Switch" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:172 +msgid "Switch %q" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:150 +msgid "" +"Switch %q has an unknown topology - the VLAN settings might not be accurate." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2883 +#: modules/luci-compat/luasrc/model/network.lua:1426 +msgid "Switch VLAN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:403 +msgid "Switch protocol" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:103 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:104 +#: modules/luci-compat/luasrc/view/cbi/ipaddr.htm:26 +msgid "Switch to CIDR list notation" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2657 +msgid "Symbolic link" +msgstr "Ligam simbolic" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:75 +msgid "Sync with NTP-Server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:67 +msgid "Sync with browser" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:26 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:17 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:99 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:3 +msgid "System" +msgstr "Sistèma" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/syslog.js:25 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:39 +msgid "System Log" +msgstr "Jornal sistèma" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:243 +msgid "System Priority" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:104 +msgid "System Properties" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:141 +msgid "System log buffer size" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:336 +msgid "TCP:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:163 +msgid "TFTP Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:371 +msgid "TFTP server root" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:49 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:84 +msgid "TX" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:142 +msgid "TX Rate" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:17 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:166 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:184 +msgid "Table" +msgstr "Tablèu" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:65 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:163 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:181 +msgid "Target" +msgstr "Cibla" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:103 +msgid "Target network" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:50 +msgid "Terminate" +msgstr "Terminar" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:84 +msgid "The block mount command failed with code %d" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:77 +msgid "" +"The HE.net endpoint update configuration changed, you must now use the plain " +"username instead of the user ID!" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:40 +msgid "The IPv4 address or the fully-qualified domain name of the remote end." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:42 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:40 +msgid "" +"The IPv4 address or the fully-qualified domain name of the remote tunnel end." +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:40 +msgid "The IPv6 address or the fully-qualified domain name of the remote end." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:42 +msgid "" +"The IPv6 address or the fully-qualified domain name of the remote tunnel end." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:59 +msgid "" +"The IPv6 prefix assigned to the provider, usually ends with ::" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1916 +msgid "" +"The allowed characters are: A-Z, a-z, 0-9 and _" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/error.htm:6 +msgid "The configuration file could not be loaded due to the following error:" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4129 +msgid "" +"The device could not be reached within %d seconds after applying the pending " +"changes, which caused the configuration to be rolled back for safety " +"reasons. If you believe that the configuration changes are correct " +"nonetheless, perform an unchecked configuration apply. Alternatively, you " +"can dismiss this warning and edit changes before attempting to apply again, " +"or revert all pending changes to keep the currently working configuration " +"state." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:280 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:392 +msgid "" +"The device file of the memory or partition (e.g." +" /dev/sda1)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:736 +msgid "" +"The existing wireless configuration needs to be changed for LuCI to function " +"properly." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:215 +msgid "" +"The flash image was uploaded. Below is the checksum and file size listed, " +"compare them with the original file to ensure data integrity.
Click " +"\"Proceed\" below to start the flash procedure." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:195 +msgid "The following rules are currently active on this system." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:154 +msgid "The gateway address must not be a local IP address" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:147 +msgid "The given SSH public key has already been added." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:153 +msgid "" +"The given SSH public key is invalid. Please supply proper public RSA or " +"ECDSA keys." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:716 +msgid "The interface name is already used" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:722 +msgid "The interface name is too long" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:55 +msgid "" +"The length of the IPv4 prefix in bits, the remainder is used in the IPv6 " +"addresses." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:63 +msgid "The length of the IPv6 prefix in bits" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:163 +msgid "The local IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:46 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:44 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:44 +msgid "The local IPv4 address over which the tunnel is created (optional)." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:169 +msgid "The local IPv4 netmask" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:46 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:44 +msgid "The local IPv6 address over which the tunnel is created (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1922 +msgid "The network name is already used" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:139 +msgid "" +"The network ports on this device can be combined to several VLANs in which computers can " +"communicate directly with each other. VLANs are often used to separate different network " +"segments. Often there is by default one Uplink port for a connection to the " +"next greater network like the internet and other ports for a local network." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:158 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:42 +msgid "The reboot command failed with code %d" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:147 +msgid "The restore command failed with code %d" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1297 +msgid "The selected %s mode is incompatible with %s encryption" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:11 +msgid "The submitted security token is invalid or already expired!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:98 +msgid "" +"The system is erasing the configuration partition now and will reboot itself " +"when finished." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:291 +msgid "" +"The system is flashing now.
DO NOT POWER OFF THE DEVICE!
Wait a " +"few minutes before you try to reconnect. It might be necessary to renew the " +"address of your computer to reach the device again, depending on your " +"settings." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:163 +msgid "" +"The system is rebooting now. If the restored configuration changed the " +"current LAN IP address, you might need to reconnect manually." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:85 +msgid "The system password has been successfully changed." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:317 +msgid "The sysupgrade command failed with code %d" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:120 +msgid "" +"The uploaded backup archive appears to be valid and contains the files " +"listed below. Press \"Continue\" to restore the backup and reboot, or " +"\"Cancel\" to abort the operation." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:115 +msgid "The uploaded backup archive is not readable" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:244 +msgid "The uploaded firmware does not allow keeping current configuration." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:239 +msgid "" +"The uploaded image file does not contain a supported format. Make sure that " +"you choose the generic image format for your platform." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:535 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:567 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:52 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:89 +msgid "There are no active leases" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4268 +msgid "There are no changes to apply" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:55 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:213 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:56 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:80 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:282 +msgid "" +"There is no password set on this router. Please configure a root password to " +"protect the web interface." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:49 +msgid "This IPv4 address of the relay" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1551 +msgid "This authentication type is not applicable to the selected EAP method." +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:57 +msgid "This does not look like a valid PEM file" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:256 +msgid "" +"This file may contain lines like 'server=/domain/1.2.3.4' or " +"'server=1.2.3.4' for domain-specific or full upstream DNS servers." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:426 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:16 +msgid "" +"This is a list of shell glob patterns for matching files and directories to " +"include during sysupgrade. Modified files in /etc/config/ and certain other " +"configurations are automatically preserved." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:81 +msgid "" +"This is either the \"Update Key\" configured for the tunnel or the account " +"password if no update key has been configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:116 +msgid "" +"This is the content of /etc/rc.local. Insert your own commands here (in " +"front of 'exit 0') to execute them at the end of the boot process." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:54 +msgid "" +"This is the local endpoint address assigned by the tunnel broker, it usually " +"ends with ...:2/64" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:173 +msgid "" +"This is the only DHCP in the local network" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:73 +msgid "This is the plain username for logging into the account" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:57 +msgid "" +"This is the prefix routed to you by the tunnel broker for use by clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:28 +msgid "This is the system crontab in which scheduled tasks can be defined." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:50 +msgid "" +"This is usually the address of the nearest PoP operated by the tunnel broker" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:65 +msgid "" +"This list gives an overview over currently running system processes and " +"their status." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1505 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1563 +msgid "" +"This option cannot be used because the ca-bundle package is not installed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2205 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2511 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:172 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:32 +msgid "This section contains no values yet" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:110 +msgid "Time Synchronization" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1093 +msgid "Time interval for rekeying GTK" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:124 +msgid "Timezone" +msgstr "Fus orari" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2678 +msgid "To login…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:372 +msgid "" +"To restore configuration files, you can upload a previously generated backup " +"archive here. To reset the firmware to its initial state, click \"Perform " +"reset\" (only possible with squashfs images)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:907 +msgid "Tone" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:35 +msgid "Total Available" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:113 +msgid "Traceroute" +msgstr "Traceroute" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:64 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:96 +msgid "Traffic" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:72 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:77 +msgid "Traffic Class" +msgstr "Classa del trafic" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:385 +msgid "Transfer" +msgstr "Transferir" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:24 +msgid "Transmit" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:317 +msgid "Transmit Hash Policy" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:74 +msgid "Trigger" +msgstr "Desenclavador" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:19 +msgid "Trigger Mode" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:69 +msgid "Tunnel ID" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2886 +#: modules/luci-compat/luasrc/model/network.lua:1431 +msgid "Tunnel Interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:44 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:55 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:76 +msgid "Tunnel Link" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:185 +msgid "Tx-Power" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:44 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:43 +msgid "Type" +msgstr "Tipe" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:326 +msgid "UDP:" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:90 +msgid "UMTS only" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_3g.lua:10 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:43 +msgid "UMTS/GPRS/EV-DO" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:254 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:360 +msgid "UUID" +msgstr "UUID" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:16 +#: modules/luci-base/htdocs/luci-static/resources/network.js:17 +#: modules/luci-compat/luasrc/model/network.lua:34 +#: modules/luci-compat/luasrc/model/network.lua:35 +msgid "Unable to determine device name" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:18 +#: modules/luci-compat/luasrc/model/network.lua:36 +msgid "Unable to determine external IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:19 +#: modules/luci-compat/luasrc/model/network.lua:37 +msgid "Unable to determine upstream interface" +msgstr "" + +#: modules/luci-base/luasrc/view/error404.htm:11 +msgid "Unable to dispatch" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/dmesg.js:9 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/syslog.js:15 +msgid "Unable to load log data:" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:54 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:54 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:22 +msgid "Unable to obtain client ID" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:221 +msgid "Unable to obtain mount information" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:278 +msgid "Unable to reset ip6tables counters: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:276 +msgid "Unable to reset iptables counters: %s" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:7 +msgid "Unable to resolve AFTR host name" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:20 +#: modules/luci-compat/luasrc/model/network.lua:38 +msgid "Unable to resolve peer host name" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:284 +msgid "Unable to restart firewall: %s" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:20 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:342 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:57 +msgid "Unable to save contents: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:33 +msgid "Unavailable Seconds (UAS)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/fs.js:102 +msgid "Unexpected reply data format" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1983 +#: modules/luci-compat/luasrc/model/network.lua:971 +msgid "Unknown" +msgstr "Desconegut" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:47 +msgid "Unknown and unsupported connection method." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2292 +#: modules/luci-compat/luasrc/model/network.lua:1138 +msgid "Unknown error (%s)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:412 +msgid "Unknown error code" +msgstr "Còde d'error desconegut" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1980 +#: modules/luci-base/htdocs/luci-static/resources/protocol/none.js:6 +#: modules/luci-compat/luasrc/model/network.lua:965 +msgid "Unmanaged" +msgstr "Pas gerit" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:195 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:217 +msgid "Unmount" +msgstr "Desmontar" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:112 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:259 +msgid "Unnamed key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3973 +msgid "Unsaved Changes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:410 +msgid "Unspecified error" +msgstr "Error pas precisada" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:64 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:9 +msgid "Unsupported MAP type" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:69 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:27 +msgid "Unsupported modem" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:267 +msgid "Unsupported protocol type." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:151 +msgid "Up" +msgstr "Amont" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:410 +msgid "Up Delay" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3860 +msgid "Upload" +msgstr "Mandadís" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:413 +msgid "" +"Upload a sysupgrade-compatible image here to replace the running firmware." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:138 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:169 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:384 +msgid "Upload archive..." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2816 +msgid "Upload file" +msgstr "Enviar un fichièr" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2791 +msgid "Upload file…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2738 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3848 +msgid "Upload request failed: %s" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3767 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3821 +msgid "Uploading file…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:737 +msgid "" +"Upon pressing \"Continue\", anonymous \"wifi-iface\" sections will be " +"assigned with a name in the form wifinet# and the network will be " +"restarted to apply the updated configuration." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:81 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:60 +msgid "Uptime" +msgstr "Temps de connexion" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:177 +msgid "Use /etc/ethers" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:269 +msgid "Use DHCP advertised servers" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:167 +msgid "Use DHCP gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:40 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:124 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:39 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:116 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:68 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:59 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:103 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:77 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:100 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:69 +msgid "Use DNS servers advertised by peer" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:565 +msgid "Use ISO/IEC 3166 alpha2 country codes." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:56 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:97 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:77 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:75 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "Use MTU on tunnel interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:93 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:73 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:88 +msgid "Use TTL on tunnel interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:320 +msgid "Use XOR of hardware MAC addresses (layer2)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:321 +msgid "Use XOR of hardware MAC addresses and IP addresses (layer2+3)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:323 +msgid "" +"Use XOR of hardware MAC addresses and IP addresses, rely on skb_flow_dissect " +"(encap2+3)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:294 +msgid "Use as external overlay (/overlay)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:293 +msgid "Use as root filesystem (/)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:34 +msgid "Use broadcast flag" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:860 +msgid "Use builtin IPv6-management" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:43 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:182 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:127 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:42 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:119 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:62 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:67 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:80 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:103 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:72 +msgid "Use custom DNS servers" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:37 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:116 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:33 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:74 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:61 +msgid "Use default gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:48 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:230 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:119 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:51 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:88 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:68 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:52 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:70 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:83 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:111 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:153 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:72 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:67 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:111 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:98 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:72 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:85 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:108 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:64 +msgid "Use gateway metric" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:96 +msgid "Use legacy MAP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:96 +msgid "" +"Use legacy MAP interface identifier format (draft-ietf-softwire-map-00) " +"instead of RFC7597" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 +msgid "Use routing table" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1498 +msgid "Use system certificates" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1556 +msgid "Use system certificates for inner-tunnel" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:412 +msgid "" +"Use the Add Button to add a new lease entry. The MAC-Address identifies the host, the IPv4-Address specifies the fixed " +"address to use, and the Hostname is assigned as a symbolic name to " +"the requesting host. The optional Lease time can be used to set non-" +"standard host-specific lease time, e.g. 12h, 3d or infinite." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:322 +msgid "Use upper layer protocol information (layer3+4)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:324 +msgid "" +"Use upper layer protocol information, rely on skb_flow_dissect (encap3+4)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:36 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:194 +msgid "Used" +msgstr "Utilizat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1394 +msgid "Used Key Slot" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1437 +msgid "" +"Used for two different purposes: RADIUS NAS ID and 802.11r R0KH-ID. Not " +"needed with normal WPA(2)-PSK." +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:105 +msgid "User Group" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:114 +msgid "User certificate (PEM encoded)" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:126 +msgid "User key (PEM encoded)" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:23 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:106 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:50 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:56 +msgid "Username" +msgstr "Nom d'utilizaire" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:975 +msgid "VC-Mux" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:923 +msgid "VDSL" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:173 +msgid "VLANs on %q" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:54 +msgid "VPN" +msgstr "VPN" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:42 +msgid "VPN Local address" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:46 +msgid "VPN Local port" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:96 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:42 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:58 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:39 +msgid "VPN Server" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:99 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:45 +msgid "VPN Server port" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:103 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:60 +msgid "VPN Server's certificate SHA1 hash" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_vpnc.lua:9 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:9 +msgid "VPNC (CISCO 3000 (and others) VPN)" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:10 +msgid "VXLAN (RFC7348)" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:48 +msgid "VXLAN network identifier" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:10 +msgid "VXLANv6 (RFC7348)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1498 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1556 +msgid "" +"Validate server certificate using built-in system CA bundle,
requires " +"the \"ca-bundle\" package" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:387 +msgid "Validation for all slaves" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:385 +msgid "Validation only for active slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:386 +msgid "Validation only for backup slaves" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:154 +msgid "Value must not be empty" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:73 +msgid "Vendor" +msgstr "Vendeire" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:55 +msgid "Vendor Class to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:196 +msgid "Verifying the uploaded image file." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:59 +msgid "Virtual dynamic interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1032 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1033 +msgid "WDS" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1217 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1306 +msgid "WEP Open System" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1218 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1307 +msgid "WEP Shared Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "WEP passphrase" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1070 +msgid "WMM Mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "WPA passphrase" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1208 +msgid "" +"WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " +"and ad-hoc mode) to be installed." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:47 +msgid "Waiting for device..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:168 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:178 +msgid "Warning" +msgstr "Avertiment" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:26 +msgid "Warning: There are unsaved changes that will get lost on reboot!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:37 +msgid "Weak" +msgstr "Feble" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1460 +msgid "" +"When using a PSK, the PMK can be automatically generated. When enabled, the " +"R0/R1 key options below are not applied. Disable this to use the R0 and R1 " +"key options." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:166 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:468 +msgid "Width" +msgstr "Largor" + +#: modules/luci-compat/luasrc/model/network/proto_wireguard.lua:9 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:29 +msgid "WireGuard VPN" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:17 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:87 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:105 +msgid "Wireless" +msgstr "Inalambric" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2874 +#: modules/luci-compat/luasrc/model/network.lua:1419 +msgid "Wireless Adapter" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2853 +#: modules/luci-base/htdocs/luci-static/resources/network.js:4057 +#: modules/luci-compat/luasrc/model/network.lua:1405 +#: modules/luci-compat/luasrc/model/network.lua:1868 +msgid "Wireless Network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:753 +msgid "Wireless Overview" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:922 +msgid "Wireless Security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:735 +msgid "Wireless configuration migration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:153 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:193 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:47 +msgid "Wireless is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:153 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:193 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:47 +msgid "Wireless is not associated" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:877 +msgid "Wireless network is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:877 +msgid "Wireless network is enabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:275 +msgid "Write received DNS requests to syslog" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:160 +msgid "Write system log to file" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:204 +msgid "XOR policy (balance-xor, 2)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3643 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:295 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:344 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:109 +msgid "Yes" +msgstr "Òc" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:303 +msgid "Yes (none, 0)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:176 +msgid "" +"You appear to be currently connected to the device via the \"%h\" interface. " +"Do you really want to shut down the interface?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:112 +msgid "" +"You can enable or disable installed init scripts here. Changes will applied " +"after a device reboot.
Warning: If you disable essential init " +"scripts like \"network\", your device might become inaccessible!" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:65 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:223 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:73 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:294 +msgid "" +"You must enable JavaScript in your browser or LuCI will not work properly." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:115 +msgid "" +"You must select a primary interface which is included in selected slave " +"interfaces!" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:96 +msgid "" +"You must select at least one ARP IP target if ARP monitoring is selected!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:192 +msgid "ZRam Compression Algorithm" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:199 +msgid "ZRam Compression Streams" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:185 +msgid "ZRam Settings" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:187 +msgid "ZRam Size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:331 +msgid "any" +msgstr "Quin que siá" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:908 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:916 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:921 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1157 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:78 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:48 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:51 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:103 +msgid "auto" +msgstr "auto" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:85 +msgid "automatic" +msgstr "automatic" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:82 +msgid "baseT" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:981 +msgid "bridged" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:146 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:401 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:35 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:99 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:31 +msgid "create" +msgstr "crear" + +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:69 +msgid "create:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:55 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:57 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:58 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:62 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:63 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:83 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:84 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:87 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:185 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:186 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:187 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:171 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:173 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:178 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:179 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:261 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:264 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:267 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:271 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:274 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:277 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:303 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:304 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:305 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:309 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:310 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:311 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:313 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:314 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:315 +msgid "dBm" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1014 +msgid "disable" +msgstr "desactivar" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:185 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:626 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:632 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:638 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:91 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:25 +msgid "disabled" +msgstr "desactivat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:519 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:553 +msgid "driver default" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:81 +msgid "e.g: --proxy 10.10.10.10" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:83 +msgid "e.g: dump" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:524 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:545 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:42 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:69 +msgid "expired" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:182 +msgid "" +"file where given DHCP-leases will be stored" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:85 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:195 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:61 +msgid "forward" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:84 +msgid "full-duplex" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:84 +msgid "half-duplex" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:569 +msgid "hexadecimal encoded value" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1738 +msgid "hidden" +msgstr "amagat" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:629 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:635 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:640 +msgid "hybrid mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:36 +msgid "if target is a network" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:63 +msgid "ignore" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:69 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:191 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:46 +msgid "input" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:395 +msgid "key between 8 and 63 characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:407 +msgid "key with either 5 or 13 characters" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:189 +msgid "local DNS file" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1316 +msgid "medium security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1465 +msgid "minutes" +msgstr "minutas" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:422 +msgid "netif_carrier_ok()" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +msgid "no" +msgstr "non" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:76 +msgid "no link" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:59 +msgid "non-empty value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3007 +msgid "none" +msgstr "pas res" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:41 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:55 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:69 +msgid "not present" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:347 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:901 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:905 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:197 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:245 +msgid "off" +msgstr "desactivat" + +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:196 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:242 +msgid "on" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1317 +msgid "open network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:69 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:46 +msgid "output" +msgstr "sortida" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:241 +msgid "positive decimal value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:233 +msgid "positive integer value" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:80 +msgid "random" +msgstr "aleatòri" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:628 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:634 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:639 +msgid "relay mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:982 +msgid "routed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1093 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1102 +msgid "sec" +msgstr "seg" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:627 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:633 +msgid "server mode" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:53 +msgid "sstpc Log-level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:649 +msgid "stateful-only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:647 +msgid "stateless" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:648 +msgid "stateless + stateful" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1315 +msgid "strong security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:352 +msgid "tagged" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1448 +msgid "time units (TUs / 1.024 ms) [1000-65535]" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:559 +msgid "unique value" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:534 +msgid "unknown" +msgstr "desconegut" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:340 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:522 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:543 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:40 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:67 +msgid "unlimited" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3372 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:76 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:138 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:369 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:393 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:428 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:465 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:561 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:53 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:38 +msgid "unspecified" +msgstr "pas precisat" + +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:71 +msgid "unspecified -or- create:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:350 +msgid "untagged" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:246 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:121 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:132 +msgid "valid IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:246 +msgid "valid IP address or prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:281 +msgid "valid IPv4 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:254 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:125 +msgid "valid IPv4 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:254 +msgid "valid IPv4 address or network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:374 +msgid "valid IPv4 address:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:314 +msgid "valid IPv4 network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:276 +msgid "valid IPv4 or IPv6 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:267 +msgid "valid IPv4 prefix value (0-32)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:286 +msgid "valid IPv6 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:262 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:129 +msgid "valid IPv6 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:262 +msgid "valid IPv6 address or prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:304 +msgid "valid IPv6 host id" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:319 +msgid "valid IPv6 network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:272 +msgid "valid IPv6 prefix value (0-128)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:340 +msgid "valid MAC address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:411 +msgid "valid UCI identifier" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:362 +msgid "valid UCI identifier, hostname or IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:383 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:386 +msgid "valid address:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:533 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:537 +msgid "valid date (YYYY-MM-DD)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:237 +msgid "valid decimal value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:405 +msgid "valid hexadecimal WEP key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:393 +msgid "valid hexadecimal WPA key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:368 +msgid "valid host:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:355 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:357 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:73 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:107 +msgid "valid hostname" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:345 +msgid "valid hostname or IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:229 +msgid "valid integer value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:309 +msgid "valid network in address/netmask notation" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:508 +msgid "valid phone digit (0-9, \"*\", \"#\", \"!\" or \".\")" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:332 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:335 +msgid "valid port or port range (port1-port2)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:324 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:136 +msgid "valid port value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:513 +msgid "valid time (HH:MM:SS)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:435 +msgid "value between %d and %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:416 +msgid "value between %f and %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:420 +msgid "value greater or equal to %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:424 +msgid "value smaller or equal to %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:429 +msgid "value with %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:440 +msgid "value with at least %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:445 +msgid "value with at most %d characters" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1317 +msgid "weak security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +msgid "yes" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:20 +msgid "« Back" +msgstr "" diff --git a/luci-base/po/templates/base.pot b/luci-base/po/templates/base.pot new file mode 100755 index 000000000..d23111f55 --- /dev/null +++ b/luci-base/po/templates/base.pot @@ -0,0 +1,7611 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:929 +msgid "%.1f dB" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:114 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:261 +msgid "%d Bit" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3689 +msgid "%d invalid field(s)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:35 +msgid "%s is untagged in multiple VLANs!" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:294 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:403 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:270 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:307 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:325 +msgid "(%d minute window, %d second interval)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:118 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:124 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:258 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:282 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:88 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:91 +msgid "(empty)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:351 +#: modules/luci-compat/luasrc/view/cbi/network_netinfo.htm:23 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:58 +msgid "(no interfaces attached)" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:48 +msgid "-- Additional Field --" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/cbi.js:275 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3372 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3704 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:767 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1005 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1974 +#: modules/luci-compat/luasrc/view/cbi/header.htm:8 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:88 +msgid "-- Please choose --" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/cbi.js:276 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1006 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:1975 +#: modules/luci-compat/luasrc/view/cbi/header.htm:9 +msgid "-- custom --" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:270 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:379 +msgid "-- match by label --" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:256 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:362 +msgid "-- match by uuid --" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:27 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:44 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:23 +msgid "-- please select --" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:54 +msgctxt "sstp log level value" +msgid "0" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:939 +msgid "0 = not using RSSI threshold, 1 = do not change driver default" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:55 +msgctxt "sstp log level value" +msgid "1" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:231 +msgid "1 Minute Load:" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:251 +msgid "15 Minute Load:" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:56 +msgctxt "sstp log level value" +msgid "2" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:57 +msgctxt "sstp log level value" +msgid "3" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:58 +msgctxt "sstp log level value" +msgid "4" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1442 +msgid "4-character hexadecimal ID" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:18 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:11 +msgid "464XLAT (CLAT)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:241 +msgid "5 Minute Load:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1471 +msgid "6-octet identifier as a hex string - no colons" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1431 +msgid "802.11r Fast Transition" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1619 +msgid "802.11w Association SA Query maximum timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1626 +msgid "802.11w Association SA Query retry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1607 +msgid "802.11w Management Frame Protection" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1619 +msgid "802.11w maximum timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1626 +msgid "802.11w retry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:956 +msgid "BSSID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:326 +msgid "DNS query port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:317 +msgid "DNS server port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:260 +msgid "" +"DNS servers will be queried in the " +"order of the resolvfile" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:945 +msgid "ESSID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:475 +msgid "IPv4-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:42 +msgid "IPv4-Gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:603 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:36 +msgid "IPv4-Netmask" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +msgid "" +"IPv6-Address or Network " +"(CIDR)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:42 +msgid "IPv6-Gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:504 +msgid "IPv6-Suffix (hex)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:58 +msgid "LED Configuration" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:69 +msgid "LED Name" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:431 +msgid "MAC-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:498 +msgid "DUID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:335 +msgid "" +"Max. DHCP leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:344 +msgid "" +"Max. EDNS0 packet size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:353 +msgid "Max. concurrent queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:29 +msgid "" +"
Note: you need to manually restart the cron service if the crontab file " +"was empty before editing." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2720 +msgid "A directory with the same name already exists." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2670 +msgid "A new login is required since the authentication session expired." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:909 +msgid "A43C + J43 + A43" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:910 +msgid "A43C + J43 + A43 + V43" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:922 +msgid "ADSL" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:898 +msgid "ANSI T1.413" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:94 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:93 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:86 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:67 +msgid "APN" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:197 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:352 +msgid "ARP" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:365 +msgid "ARP IP Targets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:357 +msgid "ARP Interval" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:381 +msgid "ARP Validation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:373 +msgid "ARP mode to consider a slave as being up" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:77 +msgid "ARP monitoring is not supported for the selected policy!" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:175 +msgid "ARP retry threshold" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:917 +msgid "ATM (Asynchronous Transfer Mode)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:938 +msgid "ATM Bridges" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:970 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:66 +msgid "ATM Virtual Channel Identifier (VCI)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:971 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:70 +msgid "ATM Virtual Path Identifier (VPI)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:938 +msgid "" +"ATM bridges expose encapsulated ethernet in AAL5 connections as virtual " +"Linux network interfaces which can be used in conjunction with DHCP or PPP " +"to dial into the provider network." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:977 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:62 +msgid "ATM device number" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:37 +msgid "ATU-C System Vendor ID" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:265 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:543 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:547 +msgid "Absent Interface" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:47 +msgid "Access Concentrator" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:927 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1032 +msgid "Access Point" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:360 +msgid "Actions" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:200 +msgid "Active IPv4-Routes" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:206 +msgid "Active IPv6-Routes" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:81 +msgid "Active Connections" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:33 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:92 +msgid "Active DHCP Leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:52 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:94 +msgid "Active DHCPv6 Leases" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:203 +msgid "Active-Backup policy (active-backup, 1)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3666 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:929 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:23 +msgid "Ad-Hoc" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:208 +msgid "Adaptive load balancing (balance-alb, 6)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:207 +msgid "Adaptive transmit load balancing (balance-tlb, 5)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2167 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2170 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2184 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2185 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3170 +#: modules/luci-compat/luasrc/view/cbi/nsection.htm:25 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:189 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:197 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:39 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:47 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:54 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:827 +msgid "Add" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:942 +msgid "Add ATM Bridge" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:92 +msgid "Add IPv4 address…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:207 +msgid "Add IPv6 address…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:65 +msgid "Add LED action" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:219 +msgid "Add VLAN" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:15 +msgid "Add instance" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:146 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:152 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:247 +msgid "Add key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:248 +msgid "Add local domain suffix to names served from hosts files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:311 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:757 +msgid "Add new interface..." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:125 +msgid "Add peer" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:200 +msgid "Additional Hosts files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:255 +msgid "Additional servers file" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:34 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:35 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:36 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:37 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:38 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:39 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:40 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:41 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:42 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:43 +msgid "Address" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:151 +msgid "Address to access local relay bridge" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:285 +msgid "Addresses" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:3 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:15 +msgid "Administration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:164 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:324 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:553 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:968 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:25 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:866 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:924 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:241 +msgid "Advanced Settings" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:28 +msgid "Aggregate Transmit Power (ACTATP)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:258 +msgid "Aggregation Selection Logic" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:261 +msgid "Aggregator: All slaves down or has no slaves (stable, 0)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:263 +msgid "" +"Aggregator: Chosen by the largest number of ports + slave added/removed or " +"state changes (count, 2)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:262 +msgid "Aggregator: Slave added/removed or state changes (bandwidth, 1)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:171 +msgid "Alert" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2871 +#: modules/luci-compat/luasrc/model/network.lua:1417 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:61 +msgid "Alias Interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:145 +msgid "Alias of \"%s\"" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:263 +msgid "All Servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:209 +msgid "" +"Allocate IP addresses sequentially, starting from the lowest available " +"address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:208 +msgid "Allocate IP sequentially" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:25 +msgid "Allow SSH password authentication" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1112 +msgid "Allow AP mode to disconnect STAs based on low ACK condition" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1016 +msgid "Allow all except listed" +msgstr "" + +#: modules/luci-compat/root/usr/share/rpcd/acl.d/luci-compat.json:3 +msgid "Allow full UCI access for legacy applications" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:892 +msgid "Allow legacy 802.11b rates" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1015 +msgid "Allow listed only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:300 +msgid "Allow localhost" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:157 +msgid "Allow rebooting the device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:36 +msgid "Allow remote hosts to connect to local SSH forwarded ports" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:31 +msgid "Allow root logins with password" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:3 +msgid "Allow system feature probing" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:31 +msgid "Allow the root user to login with password" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:301 +msgid "" +"Allow upstream responses in the 127.0.0.0/8 range, e.g. for RBL services" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:148 +msgid "Allowed IPs" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:654 +msgid "Always announce default router" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/none.js:5 +msgid "Always off (kernel: none)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:6 +msgid "Always on (kernel: default-on)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:907 +msgid "" +"Always use 40MHz channels even if the secondary channel overlaps. Using this " +"option does not comply with IEEE 802.11n-2009!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:603 +msgid "An error occurred while saving the form:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:890 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:20 +msgid "Annex" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:891 +msgid "Annex A + L + M (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:899 +msgid "Annex A G.992.1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:900 +msgid "Annex A G.992.2" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:901 +msgid "Annex A G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:902 +msgid "Annex A G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:892 +msgid "Annex B (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:895 +msgid "Annex B G.992.1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:896 +msgid "Annex B G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:897 +msgid "Annex B G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:893 +msgid "Annex J (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:903 +msgid "Annex L G.992.3 POTS 1" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:894 +msgid "Annex M (all)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:904 +msgid "Annex M G.992.3" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:905 +msgid "Annex M G.992.5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:654 +msgid "Announce as default router even if no public prefix is available." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:659 +msgid "Announced DNS domains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:658 +msgid "Announced DNS servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1596 +msgid "Anonymous Identity" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:162 +msgid "Anonymous Mount" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:158 +msgid "Anonymous Swap" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:84 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:174 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:195 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:60 +msgid "Any zone" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:119 +msgid "Apply backup?" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4276 +msgid "Apply request failed with status %h" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2181 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4142 +msgid "Apply unchecked" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4215 +msgid "Applying configuration changes… %ds" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:56 +msgid "Architecture" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:184 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:27 +msgid "" +"Assign a part of given length of every public IPv6-prefix to this interface" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:189 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:31 +msgid "" +"Assign prefix parts using this hexadecimal subprefix ID for this interface." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2078 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:245 +msgid "Associated Stations" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:46 +msgid "Associations" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:154 +msgid "Attempt to enable configured mount points for attached devices" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:104 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:64 +msgid "Auth Group" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1535 +msgid "Authentication" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:96 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:70 +msgid "Authentication Type" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:172 +msgid "Authoritative" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:17 +msgid "Authorization Required" +msgstr "" + +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:196 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:197 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:241 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:244 +msgid "Auto Refresh" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:106 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:18 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:24 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:98 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:50 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:94 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:81 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:55 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:68 +msgid "Automatic" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_hnet.lua:7 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:7 +msgid "Automatic Homenet (HNCP)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:174 +msgid "Automatically check filesystem for errors before mounting" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:170 +msgid "Automatically mount filesystems on hotplug" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:166 +msgid "Automatically mount swap on hotplug" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:170 +msgid "Automount Filesystem" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:166 +msgid "Automount Swap" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:193 +msgid "Available" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:268 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:278 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:329 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:339 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:349 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:234 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:244 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:254 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:263 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:273 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:291 +msgid "Average:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:911 +msgid "B43 + B43C" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:912 +msgid "B43 + B43C + V43" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:48 +msgid "BR / DMR / AFTR" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:158 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:182 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1665 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:44 +msgid "BSSID" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/footer.htm:14 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:48 +msgid "Back to Overview" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:48 +msgid "Back to configuration" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:363 +msgid "Backup" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:114 +msgid "Backup / Flash Firmware" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:323 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:12 +msgid "Backup file list" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:158 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:451 +msgid "Band" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:910 +msgid "Beacon Interval" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:324 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:46 +msgid "" +"Below is the determined list of files to backup. It consists of changed " +"configuration files marked by opkg, essential base files and the user " +"defined backup patterns." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:395 +msgid "" +"Bind dynamically to interfaces rather than wildcard address (recommended as " +"linux default)" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:52 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:62 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:48 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:55 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:57 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:52 +msgid "Bind interface" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:52 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:62 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:48 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:55 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:57 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:52 +msgid "Bind the tunnel to this interface (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:188 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:63 +msgid "Bitrate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:266 +msgid "Bogus NX Domain Override" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:199 +msgid "Bonding Policy" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2877 +#: modules/luci-compat/luasrc/model/network.lua:1421 +msgid "Bridge" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:416 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:730 +msgid "Bridge interfaces" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:978 +msgid "Bridge unit number" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:412 +msgid "Bring up on boot" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:205 +msgid "Broadcast policy (broadcast, 3)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2810 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3799 +msgid "Browse…" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:37 +msgid "Buffered" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:138 +msgid "CA certificate; if empty it will be saved after the first connection." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:7 +msgid "CLAT configuration failed" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:72 +msgid "CPU usage (%)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:41 +msgid "Cached" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:53 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:53 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:21 +msgid "Call failed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2903 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3808 +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:14 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:52 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:187 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:763 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1952 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:128 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:272 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:184 +msgid "Cancel" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:17 +msgid "Category" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1519 +msgid "Certificate constraint (Domain)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1516 +msgid "Certificate constraint (SAN)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1513 +msgid "Certificate constraint (Subject)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1522 +msgid "Certificate constraint (Wildcard)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1513 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1571 +msgid "" +"Certificate constraint substring - e.g. /CN=wifi.mycompany.com
See " +"`logread -f` during handshake for actual values" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1519 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1577 +msgid "" +"Certificate constraint(s) against DNS SAN values (if available)
or " +"Subject CN (exact match)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1522 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1580 +msgid "" +"Certificate constraint(s) against DNS SAN values (if available)
or " +"Subject CN (suffix match)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1516 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1574 +msgid "" +"Certificate constraint(s) via Subject Alternate Name values
(supported " +"attributes: EMAIL, DNS, URI) - e.g. DNS:wifi.mycompany.com" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:200 +msgid "Chain" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4028 +msgid "Changes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4311 +msgid "Changes have been reverted." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:46 +msgid "Changes the administrator password for accessing the device" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:162 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:128 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:184 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:460 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1663 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:62 +msgid "Channel" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:174 +msgid "Check filesystems before mount" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1914 +msgid "Check this option to delete the existing networks from this radio." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:110 +msgid "Checking archive…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:193 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:195 +msgid "Checking image…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:399 +msgid "Choose mtdblock" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:491 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1942 +msgid "" +"Choose the firewall zone you want to assign to this interface. Select " +"unspecified to remove the interface from the associated zone or " +"fill out the custom field to define a new zone and attach the " +"interface to it." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:959 +msgid "" +"Choose the network(s) you want to attach to this wireless interface or fill " +"out the custom field to define a new network." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1148 +msgid "Cipher" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:91 +msgid "Cisco UDP encapsulation" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:363 +msgid "" +"Click \"Generate archive\" to download a tar archive of the current " +"configuration files." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:396 +msgid "" +"Click \"Save mtdblock\" to download specified mtdblock file. (NOTE: THIS " +"FEATURE IS FOR PROFESSIONALS! )" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3665 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:928 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1033 +msgid "Client" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:52 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:47 +msgid "Client ID to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:148 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:154 +msgid "Close" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:157 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:141 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:115 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:138 +msgid "" +"Close inactive connection after the given amount of seconds, use 0 to " +"persist connection" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:49 +msgid "Close list..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:42 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:61 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2076 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:389 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:317 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:320 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:204 +msgid "Collecting data..." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:71 +msgid "Command" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:401 +msgid "Command OK" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:33 +msgid "Command failed" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:72 +msgid "Comment" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1634 +msgid "" +"Complicates key reinstallation attacks on the client side by disabling " +"retransmission of EAPOL-Key frames that are used to install keys. This " +"workaround might cause interoperability issues and reduced robustness of key " +"negotiation especially in environments with heavy traffic load." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:96 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:98 +msgid "Compute outgoing checksum (optional)." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4028 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:426 +msgid "Configuration" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4190 +msgid "Configuration changes applied." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4128 +msgid "Configuration changes have been rolled back!" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:63 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:21 +msgid "Configuration failed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:175 +msgid "Confirm disconnect" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:55 +msgid "Confirmation" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:51 +msgid "Connected" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:9 +#: modules/luci-compat/luasrc/model/network.lua:27 +msgid "Connection attempt failed" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:40 +msgid "Connection attempt failed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:411 +msgid "Connection lost" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:117 +msgid "Connections" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:377 +msgid "Consider the slave up when all ARP IP targets are reachable (all, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:376 +msgid "Consider the slave up when any ARP IP target is reachable (any, 0)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:18 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:340 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:55 +msgid "Contents have been saved." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:742 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:132 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:264 +msgid "Continue" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4164 +msgid "" +"Could not regain access to the device after applying the configuration " +"changes. You might need to reconnect if you modified network related " +"settings such as the IP address or wireless security credentials." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:189 +msgid "Country" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:889 +msgid "Country Code" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:491 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1942 +msgid "Create / Assign firewall-zone" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:798 +msgid "Create interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:416 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:730 +msgid "Creates a bridge over specified interface(s)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:170 +msgid "Critical" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:174 +msgid "Cron Log Level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:533 +msgid "Current power" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:568 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:570 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:51 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:53 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:82 +#: modules/luci-compat/luasrc/view/cbi/network_ifacelist.htm:83 +msgid "Custom Interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:36 +msgid "Custom delegated IPv6-prefix" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:382 +msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:6 +msgid "Custom flash interval (kernel: timer)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:59 +msgid "" +"Customizes the behaviour of the device LEDs if possible." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1353 +msgid "DAE-Client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1358 +msgid "DAE-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1363 +msgid "DAE-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:327 +msgid "DHCP Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:155 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:50 +msgid "DHCP and DNS" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1982 +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:16 +#: modules/luci-compat/luasrc/model/network.lua:969 +msgid "DHCP client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:619 +msgid "DHCP-Options" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_dhcpv6.lua:7 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:7 +msgid "DHCPv6 client" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:646 +msgid "DHCPv6-Mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:631 +msgid "DHCPv6-Service" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:45 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:47 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:48 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:49 +msgid "DNS" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:277 +msgid "DNS forwardings" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:37 +msgid "DNS-Label / FQDN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:228 +msgid "DNSSEC" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:232 +msgid "DNSSEC check unsigned" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:99 +msgid "DPD Idle Timeout" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:41 +msgid "DS-Lite AFTR address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:887 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:45 +msgid "DSL" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:14 +msgid "DSL Status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:920 +msgid "DSL line mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1088 +msgid "DTIM Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:57 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:58 +msgid "DUID" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:22 +msgid "Data Rate" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:165 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:176 +msgid "Debug" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1328 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1343 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1358 +msgid "Default %d" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:107 +msgid "Default Route" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:48 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:85 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:65 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:49 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:67 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:80 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:108 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:150 +msgid "Default gateway" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:646 +msgid "Default is stateless + stateful" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:11 +msgid "Default state" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:619 +msgid "" +"Define additional DHCP options, for example " +"\"6,192.168.2.1,192.168.2.2\" which advertises different DNS " +"servers to clients." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2237 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2662 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2666 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3154 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2872 +#: modules/luci-compat/luasrc/view/cbi/nsection.htm:11 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:162 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:16 +msgid "Delete" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:180 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:186 +msgid "Delete key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2769 +msgid "Delete request failed: %s" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:847 +msgid "Delete this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1088 +msgid "Delivery Traffic Indication Message Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:340 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:134 +msgid "Description" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2868 +msgid "Deselect" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:220 +msgid "Design" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:384 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:70 +msgid "Destination" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:48 +msgid "Destination port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:59 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:165 +msgid "Destination zone" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:67 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:191 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:43 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:80 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:55 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:12 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:247 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:280 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:356 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:392 +msgid "Device" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:861 +msgid "Device Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:132 +msgid "Device is not active" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:224 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:599 +msgid "Device is restarting…" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:45 +msgid "Device not managed by ModemManager." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4163 +msgid "Device unreachable!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:53 +msgid "Device unreachable! Still waiting for device..." +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:88 +msgid "Diagnostics" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:101 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:93 +msgid "Dial number" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2665 +msgid "Directory" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:839 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:879 +msgid "Disable" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:579 +msgid "" +"Disable DHCP for " +"this interface." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:373 +msgid "Disable DNS lookups" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:93 +msgid "Disable Encryption" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1098 +msgid "Disable Inactivity Polling" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:837 +msgid "Disable this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1608 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:66 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:107 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:99 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:51 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:95 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:82 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:69 +msgid "Disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1112 +msgid "Disassociate On Low Acknowledgement" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:294 +msgid "Discard upstream RFC1918 responses" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:197 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:665 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:231 +msgid "Disconnect" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:64 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:22 +msgid "Disconnection attempt failed" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:48 +msgid "Disconnection attempt failed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:606 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2861 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3309 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4045 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4134 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1688 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:330 +msgid "Dismiss" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:895 +msgid "Distance Optimization" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:895 +msgid "Distance to farthest network member in meters." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:155 +msgid "" +"Dnsmasq is a combined DHCP-Server and DNS-" +"Forwarder for NAT " +"firewalls" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:252 +msgid "Do not cache negative replies, e.g. for not existing domains" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:79 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:81 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:86 +msgid "Do not create host route to peer (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:219 +msgid "Do not forward requests that cannot be answered by public name servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:214 +msgid "Do not forward reverse lookups for local networks" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:25 +msgid "Do not send a hostname" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2755 +msgid "Do you really want to delete \"%s\" ?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:181 +msgid "Do you really want to delete the following SSH key?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:94 +msgid "Do you really want to erase all settings?" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2753 +msgid "Do you really want to recursively delete the directory \"%s\" ?" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:168 +msgid "Domain required" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:307 +msgid "Domain whitelist" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:81 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:67 +msgid "Don't Fragment" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:169 +msgid "" +"Don't forward DNS-Requests without " +"DNS-Name" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:152 +msgid "Down" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:402 +msgid "Down Delay" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:366 +msgid "Download backup" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:404 +msgid "Download mtdblock" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:925 +msgid "Downstream SNR offset" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2620 +msgid "Drag to reorder" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:341 +msgid "Drop Duplicate Frames" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:12 +msgid "Dropbear Instance" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:10 +msgid "" +"Dropbear offers SSH network shell access " +"and an integrated SCP server" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:14 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:11 +msgid "Dual-Stack Lite (RFC6333)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:595 +msgid "Dynamic DHCP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:60 +msgid "Dynamic tunnel" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:595 +msgid "" +"Dynamically allocate DHCP addresses for clients. If disabled, only clients " +"having static leases will be served." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:67 +msgid "EA-bits length" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1491 +msgid "EAP-Method" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2640 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2643 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3017 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:154 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:160 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:339 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:844 +msgid "Edit" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/error.htm:13 +msgid "" +"Edit the raw configuration data above to fix any error and hit \"Save\" to " +"reload the page." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:842 +msgid "Edit this network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:793 +msgid "Edit wireless network" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:172 +msgid "Emergency" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:839 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:879 +msgid "Enable" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:462 +msgid "" +"Enable IGMP " +"snooping" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:460 +msgid "Enable STP" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:367 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:373 +msgid "Enable DNS lookups" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:292 +msgid "Enable Dynamic Shuffling Of Flows" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:60 +msgid "Enable HE.net dynamic endpoint update" +msgstr "" + +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:89 +msgid "Enable IPv6 negotiation" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:49 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:80 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:54 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:67 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:93 +msgid "Enable IPv6 negotiation on the PPP link" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:192 +msgid "Enable Jumbo Frame passthrough" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:240 +msgid "Enable NTP client" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:96 +msgid "Enable Single DES" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:368 +msgid "Enable TFTP server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:184 +msgid "Enable VLAN functionality" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1638 +msgid "Enable WPS pushbutton, requires WPA(2)-PSK/WPA3-SAE" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1634 +msgid "Enable key reinstallation (KRACK) countermeasures" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:187 +msgid "Enable learning and aging" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:198 +msgid "Enable mirroring of incoming packets" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:199 +msgid "Enable mirroring of outgoing packets" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:882 +msgid "" +"Enable packet steering across all CPUs. May help or hinder network speed." +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:80 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:75 +msgid "Enable rx checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:81 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:67 +msgid "Enable the DF (Don't Fragment) flag of the encapsulating packets." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:837 +msgid "Enable this network" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:84 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:79 +msgid "Enable tx checksum" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:243 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:352 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:66 +msgid "Enabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:462 +msgid "Enables IGMP snooping on this bridge" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1431 +msgid "" +"Enables fast roaming among access points that belong to the same Mobility " +"Domain" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:460 +msgid "Enables the Spanning Tree Protocol on this bridge" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:59 +msgid "Encapsulation limit" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:915 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:973 +msgid "Encapsulation mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:159 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:183 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1117 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1666 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:45 +msgid "Encryption" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:161 +msgid "Endpoint Host" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:165 +msgid "Endpoint Port" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/dropdown.htm:16 +msgid "Enter custom value" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/dropdown.htm:16 +msgid "Enter custom values" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:97 +msgid "Erasing..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:104 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:105 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:106 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:169 +msgid "Error" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:30 +msgid "Errored seconds (ES)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2889 +#: modules/luci-compat/luasrc/model/network.lua:1433 +msgid "Ethernet Adapter" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2880 +#: modules/luci-compat/luasrc/model/network.lua:1423 +msgid "Ethernet Switch" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:270 +msgid "Every 30 seconds (slow, 0)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:271 +msgid "Every second (fast, 1)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:406 +msgid "Exclude interfaces" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:247 +msgid "Expand hosts" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:198 +msgid "Expecting a hexadecimal assignment hint" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:64 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:73 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:107 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:121 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:125 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:132 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:136 +msgid "Expecting: %s" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:48 +msgid "Expecting: non-empty value" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:50 +msgid "Expires" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:591 +msgid "" +"Expiry time of leased addresses, minimum is 2 minutes (2m)." +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:19 +msgid "External" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1482 +msgid "External R0 Key Holder List" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1486 +msgid "External R1 Key Holder List" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:146 +msgid "External system log server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:151 +msgid "External system log server port" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:156 +msgid "External system log server protocol" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:79 +msgid "Extra SSH command options" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:83 +msgid "Extra pppd options" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:81 +msgid "Extra sstpc options" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1456 +msgid "FT over DS" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1457 +msgid "FT over the Air" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1454 +msgid "FT protocol" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:87 +msgid "Failed to change the system password." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4122 +msgid "Failed to confirm apply within %ds, waiting for rollback…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:37 +msgid "Failed to execute \"/etc/init.d/%s %s\" action: %s" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2673 +msgid "File" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2620 +msgid "File not accessible" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2811 +msgid "Filename" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:381 +msgid "Filename of the boot image advertised to clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:191 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:314 +msgid "Filesystem" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:213 +msgid "Filter private" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:218 +msgid "Filter useless" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:388 +msgid "Filtering for all slaves, no validation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:389 +msgid "Filtering for all slaves, validation only for active slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:390 +msgid "Filtering for all slaves, validation only for backup slaves" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:65 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:23 +msgid "Finalizing failed" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:150 +msgid "" +"Find all currently attached filesystems and swap and replace configuration " +"with defaults based on what was detected" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:820 +msgid "Find and join network" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:9 +msgid "Finish" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:15 +msgid "Firewall" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:102 +msgid "Firewall Mark" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:326 +msgid "Firewall Settings" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:297 +msgid "Firewall Status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:932 +msgid "Firmware File" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:57 +msgid "Firmware Version" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:327 +msgid "Fixed source port for outbound DNS queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:283 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:421 +msgid "Flash image..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:279 +msgid "Flash image?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:411 +msgid "Flash new firmware image" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:356 +msgid "Flash operations" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:288 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:290 +msgid "Flashing…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:598 +msgid "Force" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:907 +msgid "Force 40MHz mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1158 +msgid "Force CCMP (AES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:598 +msgid "Force DHCP on this network even if another server is detected." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1159 +msgid "Force TKIP" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1160 +msgid "Force TKIP and CCMP (AES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:864 +msgid "Force link" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:255 +msgid "Force upgrade" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:90 +msgid "Force use of NAT-T" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:8 +msgid "Form token mismatch" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:164 +msgid "Forward DHCP traffic" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:29 +msgid "Forward Error Correction Seconds (FECS)" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:161 +msgid "Forward broadcast traffic" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:934 +msgid "Forward mesh peer traffic" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:980 +msgid "Forwarding mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:899 +msgid "Fragmentation Threshold" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:115 +msgid "" +"Further information about WireGuard interfaces and peers at wireguard.com." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:128 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:184 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:62 +msgid "GHz" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:91 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:77 +msgid "GPRS only" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:10 +msgid "GRE tunnel over IPv4" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:10 +msgid "GRE tunnel over IPv6" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:10 +msgid "GRETAP tunnel over IPv4" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:10 +msgid "GRETAP tunnel over IPv6" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:44 +msgid "Gateway" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:36 +msgid "Gateway Ports" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:11 +#: modules/luci-compat/luasrc/model/network.lua:29 +msgid "Gateway address is invalid" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:124 +msgid "Gateway metric" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:161 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:323 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:24 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:240 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:108 +msgid "General Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:552 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:967 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:865 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:921 +msgid "General Setup" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:150 +msgid "Generate Config" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:66 +msgid "Generate Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1460 +msgid "Generate PMK locally" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:368 +msgid "Generate archive" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:79 +msgid "Given password confirmation did not match, password not changed!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:146 +msgid "Global Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:875 +msgid "Global network options" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:57 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:215 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:58 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:82 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:284 +msgid "Go to password configuration..." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2562 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3336 +#: modules/luci-compat/luasrc/view/cbi/full_valueheader.htm:4 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:58 +msgid "Go to relevant configuration page" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:33 +msgid "Grant access to DHCP configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:102 +msgid "Grant access to DHCP status display" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:111 +msgid "Grant access to DSL status display" +msgstr "" + +#: protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json:3 +msgid "Grant access to LuCI OpenConnect procedures" +msgstr "" + +#: protocols/luci-proto-wireguard/root/usr/share/rpcd/acl.d/luci-wireguard.json:3 +msgid "Grant access to LuCI Wireguard procedures" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:19 +msgid "Grant access to SSH configuration" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:12 +msgid "Grant access to basic LuCI procedures" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:64 +msgid "Grant access to crontab configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:60 +msgid "Grant access to firewall status" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:116 +msgid "Grant access to flash operations" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:86 +msgid "Grant access to main status display" +msgstr "" + +#: protocols/luci-proto-modemmanager/root/usr/share/rpcd/acl.d/luci-proto-modemmanager.json:3 +msgid "Grant access to mmcli" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:84 +msgid "Grant access to mount configuration" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:3 +msgid "Grant access to network configuration" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json:46 +msgid "Grant access to network diagnostic tools" +msgstr "" + +#: modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json:36 +msgid "Grant access to network status information" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:13 +msgid "Grant access to process status" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:3 +msgid "Grant access to realtime statistics" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:42 +msgid "Grant access to startup configuration" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/rpcd/acl.d/luci-mod-system.json:3 +msgid "Grant access to system configuration" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:30 +msgid "Grant access to system logs" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:47 +msgid "Grant access to the system route status" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json:120 +msgid "Grant access to wireless status display" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:66 +msgid "Group Password" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:22 +msgid "Guest" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:81 +msgid "HE.net password" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:73 +msgid "HE.net username" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:46 +msgid "Hang Up" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:34 +msgid "Header Error Code Errors (HEC)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/heartbeat.js:5 +msgid "Heartbeat interval (kernel: heartbeat)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:100 +msgid "" +"Here you can configure the basic aspects of your device like its hostname or " +"the timezone." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1066 +msgid "Hide ESSID" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:264 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:303 +msgid "Hide empty chains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:55 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2070 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:140 +msgid "Host" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:22 +msgid "Host entries" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:171 +msgid "Host expiry timeout" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +msgid "Host-IP or Network" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:102 +msgid "Host-Uniq tag content" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:36 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:419 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:27 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:54 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:29 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:121 +msgid "Hostname" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:22 +msgid "Hostname to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:20 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:63 +msgid "Hostnames" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:24 +msgid "Hybrid" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:48 +msgid "ID used to uniquely identify the VXLAN" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:206 +msgid "IEEE 802.3ad Dynamic link aggregation (802.3ad, 4)" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:75 +msgid "IKE DH Group" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:83 +msgid "IP Addresses" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:80 +msgid "IP Protocol" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:114 +msgid "IP Type" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/hosts.js:31 +msgid "IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:10 +#: modules/luci-compat/luasrc/model/network.lua:28 +msgid "IP address is invalid" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:13 +#: modules/luci-compat/luasrc/model/network.lua:31 +msgid "IP address is missing" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:85 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:86 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:87 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:88 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:89 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:82 +msgid "IPv4" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:316 +msgid "IPv4 Firewall" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:29 +msgid "IPv4 Upstream" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:178 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:162 +msgid "IPv4 address" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:33 +msgid "IPv4 assignment length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:181 +msgid "IPv4 broadcast" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:180 +msgid "IPv4 gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:179 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:168 +msgid "IPv4 netmask" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:291 +msgid "IPv4 network in address/netmask notation" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:116 +msgid "IPv4 only" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:52 +msgid "IPv4 prefix" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:55 +msgid "IPv4 prefix length" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:83 +msgid "IPv4+IPv6" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:37 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:30 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:154 +msgid "IPv4-Address" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:164 +msgid "IPv4-Gateway" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ipip.lua:9 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:10 +msgid "IPv4-in-IPv4 (RFC2003)" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:115 +msgid "IPv4/IPv6 (both - defaults to IPv4)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:90 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:91 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:92 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:93 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:94 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:95 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:96 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:97 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:98 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:99 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:84 +msgid "IPv6" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:319 +msgid "IPv6 Firewall" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:203 +msgid "IPv6 Neighbours" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:554 +msgid "IPv6 Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:879 +msgid "IPv6 ULA-Prefix" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:29 +msgid "IPv6 Upstream" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:205 +msgid "IPv6 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:189 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:31 +msgid "IPv6 assignment hint" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:184 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:27 +msgid "IPv6 assignment length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:210 +msgid "IPv6 gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:296 +msgid "IPv6 network in address/netmask notation" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:117 +msgid "IPv6 only" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:59 +msgid "IPv6 prefix" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:63 +msgid "IPv6 prefix length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:214 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:57 +msgid "IPv6 routed prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:218 +msgid "IPv6 suffix" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:51 +msgid "IPv6 support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:57 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:172 +msgid "IPv6-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:100 +msgid "IPv6-PD" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:13 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:10 +msgid "IPv6-in-IPv4 (RFC4213)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:17 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:9 +msgid "IPv6-over-IPv4 (6rd)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_6x4.lua:15 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:9 +msgid "IPv6-over-IPv4 (6to4)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1593 +msgid "Identity" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:96 +msgid "If checked, 1DES is enabled" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:51 +msgid "If checked, adds \"+ipv6\" to the pppd options" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:93 +msgid "If checked, encryption is disabled" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:254 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:360 +msgid "" +"If specified, mount the device by its UUID instead of a fixed device node" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:267 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:376 +msgid "" +"If specified, mount the device by the partition label instead of a fixed " +"device node" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:37 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:116 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:48 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:85 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:65 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:49 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:33 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:67 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:80 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:108 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:150 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:74 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:61 +msgid "If unchecked, no default route is configured" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:40 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:124 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:39 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:116 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:68 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:59 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:103 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:77 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:100 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:69 +msgid "If unchecked, the advertised DNS server addresses are ignored" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:339 +msgid "" +"If your physical memory is insufficient unused data can be temporarily " +"swapped to a swap-device resulting in a higher amount of usable RAM. Be aware that swapping data is a very " +"slow process as the swap-device cannot be accessed with the high datarates " +"of the RAM." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:197 +msgid "Ignore /etc/hosts" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:579 +msgid "Ignore interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:185 +msgid "Ignore resolve file" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:419 +msgid "Image" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:67 +msgid "In" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:13 +msgid "" +"In order to prevent unauthorized access to the system, your request has been " +"blocked. Click \"Continue »\" below to return to the previous page." +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:157 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:141 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:115 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:138 +msgid "Inactivity timeout" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:265 +msgid "Inbound:" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:90 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:97 +msgid "Incoming checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:82 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:87 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:89 +msgid "Incoming key" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:97 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:94 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:99 +msgid "Incoming serialization" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:166 +msgid "Info" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:101 +msgid "Information" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:67 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:25 +msgid "Initialization failure" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:77 +msgid "Initscript" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:111 +msgid "Initscripts" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1577 +msgid "Inner certificate constraint (Domain)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1574 +msgid "Inner certificate constraint (SAN)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1571 +msgid "Inner certificate constraint (Subject)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1580 +msgid "Inner certificate constraint (Wildcard)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:268 +msgid "Install protocol extensions..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1938 +msgid "" +"Instead of joining any network with a matching SSID, only connect to the " +"BSSID %h." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/map.htm:43 +msgid "Insufficient permissions to read UCI configuration." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:464 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:471 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:735 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:739 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:27 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:156 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:174 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:17 +msgid "Interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:62 +msgid "Interface %q device auto-migrated from %q to %q." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:917 +msgid "Interface Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:110 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:151 +msgid "Interface has %d pending changes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:92 +msgid "Interface is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:64 +msgid "Interface is marked for deletion" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:209 +msgid "Interface is reconnecting..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:193 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:203 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:209 +msgid "Interface is shutting down..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:253 +msgid "Interface is starting..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:256 +msgid "Interface is stopping..." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1079 +msgid "Interface name" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:122 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:272 +msgid "Interface not present or not connected yet." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:308 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:335 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:38 +msgid "Interfaces" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:20 +msgid "Internal" +msgstr "" + +#: modules/luci-base/luasrc/view/error500.htm:8 +msgid "Internal Server Error" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:283 +msgid "Interval For Sending Learning Packets" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:192 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:42 +msgid "Invalid" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:19 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:22 +msgid "Invalid Base64 key string" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:285 +msgid "Invalid VLAN ID given! Only IDs between %d and %d are allowed." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:294 +msgid "Invalid VLAN ID given! Only unique IDs are allowed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:403 +msgid "Invalid argument" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:46 +msgid "" +"Invalid bearer list. Possibly too many bearers created. This protocol " +"supports one and only one bearer." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:402 +msgid "Invalid command" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:106 +msgid "Invalid hexadecimal value" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:12 +msgid "Invalid username and/or password! Please try again." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:71 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:76 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:81 +msgid "Invalid value" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1075 +msgid "Isolate Clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:231 +msgid "" +"It appears that you are trying to flash an image that does not fit into the " +"flash memory, please verify the image file!" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:64 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:222 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:72 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:291 +msgid "JavaScript required!" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1746 +msgid "Join Network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1680 +msgid "Join Network: Wireless Scan" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1946 +msgid "Joining Network: %q" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:223 +msgid "Keep settings and retain the current configuration" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/dmesg.js:20 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:51 +msgid "Kernel Log" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:58 +msgid "Kernel Version" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1369 +msgid "Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1397 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1398 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1399 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1400 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1412 +msgid "Key #%d" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:82 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:87 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:89 +msgid "Key for incoming packets (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:86 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:88 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:93 +msgid "Key for outgoing packets (optinal)." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:54 +msgid "Kill" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:21 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:10 +msgid "L2TP" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:40 +msgid "L2TP Server" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:267 +msgid "LACPDU Packets" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:131 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:102 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:89 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:112 +msgid "LCP echo failure threshold" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:144 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:102 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:125 +msgid "LCP echo interval" +msgstr "" + +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:101 +msgid "LED Configuration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:974 +msgid "LLC" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:267 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:376 +msgid "Label" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:209 +msgid "Language" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:111 +msgid "Language and Style" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:24 +msgid "Latency" +msgstr "" + +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:21 +msgid "Leaf" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:495 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:591 +msgid "Lease time" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:39 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:58 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:32 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:59 +msgid "Lease time remaining" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:181 +msgid "Leasefile" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:41 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:47 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:50 +msgid "Leave empty to autodetect" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:45 +msgid "Leave empty to use the current WAN address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4030 +msgid "Legend:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:586 +msgid "Limit" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:389 +msgid "Limit DNS service to subnets interfaces on which we are serving DNS." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:402 +msgid "Limit listening to these interfaces, and loopback." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:25 +msgid "Line Attenuation (LATN)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:18 +msgid "Line Mode" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:17 +msgid "Line State" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:19 +msgid "Line Uptime" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:123 +msgid "Link Aggregation (Channel Bonding)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:348 +msgid "Link Monitoring" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:23 +msgid "Link On" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:278 +msgid "" +"List of DNS servers to forward " +"requests to" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1482 +msgid "" +"List of R0KHs in the same Mobility Domain.
Format: MAC-address,NAS-" +"Identifier,128-bit key as hex string.
This list is used to map R0KH-ID " +"(NAS Identifier) to a destination MAC address when requesting PMK-R1 key " +"from the R0KH that the STA used during the Initial Mobility Domain " +"Association." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1486 +msgid "" +"List of R1KHs in the same Mobility Domain.
Format: MAC-address,R1KH-ID " +"as 6 octets with colons,128-bit key as hex string.
This list is used " +"to map R1KH-ID to a destination MAC address when sending PMK-R1 key from the " +"R0KH. This is also the list of authorized R1KHs in the MD that can request " +"PMK-R1 keys." +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:82 +msgid "List of SSH key files for auth" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:308 +msgid "List of domains to allow RFC1918 responses for" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:286 +msgid "List of domains to force to an IP address." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:267 +msgid "List of hosts that supply bogus NX domain results" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:401 +msgid "Listen Interfaces" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:78 +msgid "Listen Port" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:17 +msgid "Listen only on the given interface or, if unspecified, on all" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:318 +msgid "Listening port for inbound DNS queries" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:87 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:54 +msgid "Load" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:61 +msgid "Load Average" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2938 +msgid "Loading directory contents…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:1948 +#: modules/luci-base/luasrc/view/view.htm:4 +#: modules/luci-mod-status/luasrc/view/admin_status/index.htm:12 +msgid "Loading view…" +msgstr "" + +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:77 +msgid "Local IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:12 +#: modules/luci-compat/luasrc/model/network.lua:30 +msgid "Local IP address is invalid" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:86 +msgid "Local IP address to assign" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:46 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:44 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:39 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:39 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:151 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:44 +msgid "Local IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:46 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:54 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:45 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:44 +msgid "Local IPv6 address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:388 +msgid "Local Service Only" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:115 +msgid "Local Startup" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:59 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:117 +msgid "Local Time" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:243 +msgid "Local domain" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:240 +msgid "" +"Local domain specification. Names matching this domain are never forwarded " +"and are resolved from DHCP or hosts files only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:244 +msgid "Local domain suffix appended to DHCP names and hosts file entries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:239 +msgid "Local server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:224 +msgid "" +"Localise hostname depending on the requesting subnet if multiple IPs are " +"available" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:223 +msgid "Localise queries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1938 +msgid "Lock to BSSID" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:164 +msgid "Log output level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:274 +msgid "Log queries" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:109 +msgid "Logging" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:50 +msgid "" +"Logical network from which to select the local endpoint if local IPv6 " +"address is empty and no WAN IPv6 is available (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:55 +msgid "Logical network to which the tunnel will be added (bridged) (optional)." +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:38 +msgid "Login" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:81 +msgid "Logout" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:32 +msgid "Loss of Signal Seconds (LOSS)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:581 +msgid "Lowest leased address as offset from the network address." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:47 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:82 +msgid "MAC" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:251 +msgid "MAC Address For The Actor" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:38 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2069 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:56 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:31 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:139 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:155 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:173 +msgid "MAC-Address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1011 +msgid "MAC-Address Filter" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:923 +msgid "MAC-Filter" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1018 +msgid "MAC-List" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:16 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:13 +msgid "MAP / LW4over6" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:62 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:7 +msgid "MAP rule is invalid" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:321 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:322 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:323 +msgid "MBit/s" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:218 +msgid "MD5" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:199 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:71 +msgid "MHz" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:353 +msgid "MII" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:421 +msgid "MII / ETHTOOL ioctls" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:394 +msgid "MII Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:54 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:53 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:97 +msgid "MTU" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:302 +msgid "" +"Make sure to clone the root filesystem using something like the commands " +"below:" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:108 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:52 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:96 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:83 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:57 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:70 +msgid "Manual" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3664 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:642 +msgid "Master" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:23 +msgid "Max. Attainable Data Rate (ATTNDR)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1107 +msgid "Maximum allowed Listen Interval" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:336 +msgid "Maximum allowed number of active DHCP leases" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:354 +msgid "Maximum allowed number of concurrent DNS queries" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:345 +msgid "Maximum allowed size of EDNS.0 UDP packets" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:112 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:104 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:93 +msgid "Maximum amount of seconds to wait for the modem to become ready" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:586 +msgid "Maximum number of leased addresses." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:886 +msgid "Maximum transmit power" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:129 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:188 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:199 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:63 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:71 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:327 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:328 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:329 +msgid "Mbit/s" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:35 +msgid "Medium" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:24 +msgid "Memory" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:73 +msgid "Memory usage (%)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3667 +msgid "Mesh" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:156 +msgid "Mesh ID" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:931 +msgid "Mesh Id" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:404 +msgid "Method not found" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:349 +msgid "Method of link monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:418 +msgid "Method to determine link status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:46 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:165 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:183 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:92 +msgid "Metric" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:235 +msgid "Minimum Number of Links" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:202 +msgid "Mirror monitor port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:201 +msgid "Mirror source port" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:9 +msgid "Mobile Data" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1442 +msgid "Mobility Domain" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:154 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:157 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:180 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:442 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:926 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1664 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:43 +msgid "Mode" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:55 +msgid "Model" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:43 +msgid "Modem bearer teardown in progress." +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:42 +msgid "" +"Modem connection in progress. Please wait. This process will timeout after 2 " +"minutes." +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:72 +msgid "Modem default" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:73 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:82 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:73 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:57 +msgid "Modem device" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:41 +msgid "Modem disconnection in progress. Please wait." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:66 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:24 +msgid "Modem information query failed" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:112 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:104 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:93 +msgid "Modem init timeout" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:44 +msgid "Modem is disabled." +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:52 +msgid "ModemManager" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:3668 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1005 +msgid "Monitor" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:31 +msgid "More Characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2504 +msgid "More…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:192 +msgid "Mount Point" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:144 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:228 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:88 +msgid "Mount Points" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:229 +msgid "Mount Points - Mount Entry" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:340 +msgid "Mount Points - Swap Entry" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:228 +msgid "" +"Mount Points define at which point a memory device will be attached to the " +"filesystem" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:154 +msgid "Mount attached devices" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:162 +msgid "Mount filesystems not specifically configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:331 +msgid "Mount options" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:292 +msgid "Mount point" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:158 +msgid "Mount swap not specifically configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:223 +msgid "Mounted file systems" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:152 +msgid "Move down" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:151 +msgid "Move up" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1437 +msgid "NAS ID" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:87 +msgid "NAT-T Mode" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:41 +msgid "NAT64 Prefix" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:26 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:31 +msgid "NCM" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:637 +msgid "NDP-Proxy" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:72 +msgid "NT Domain" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:274 +msgid "NTP server candidates" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2542 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3785 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:27 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:710 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:67 +msgid "Name" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1916 +msgid "Name of the new network" +msgstr "" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:40 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:50 +msgid "Navigation" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:959 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2068 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:381 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:63 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:138 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:162 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:180 +msgid "Network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:68 +msgid "Network Utilities" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:380 +msgid "Network boot image" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:7 +msgid "Network device activity (kernel: netdev)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:15 +#: modules/luci-compat/luasrc/model/network.lua:33 +msgid "Network device is not present" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:55 +msgid "Network interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:777 +msgid "New interface for \"%s\" can not be created: %s" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:713 +msgid "New interface name…" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:11 +msgid "Next »" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3643 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:296 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:345 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:108 +msgid "No" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:562 +msgid "No DHCP Server configured for this interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1310 +msgid "No Encryption" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:87 +msgid "No Host Routes" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:89 +msgid "No NAT-T" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:79 +msgid "No RX signal" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:69 +msgid "No client associated" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:406 +msgid "No data received" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2878 +msgid "No entries in this directory" +msgstr "" + +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:82 +msgid "No files found" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:79 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:84 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:81 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:86 +msgid "No host route" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:674 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:142 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:241 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:59 +msgid "No information available" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:63 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:8 +msgid "No matching prefix delegation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:140 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:143 +msgid "No more slaves available" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:187 +msgid "No more slaves available, can not save interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:251 +msgid "No negative cache" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:54 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:212 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:55 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:79 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:279 +msgid "No password set!" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:130 +msgid "No peers defined yet" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:121 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:268 +msgid "No public keys present yet." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:90 +msgid "No rules in this chain." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:384 +msgid "No validation or filtering" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:152 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:825 +msgid "No zone assigned" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:58 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:84 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:187 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:141 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:174 +msgid "Noise" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:27 +msgid "Noise Margin (SNR)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:270 +msgid "Noise:" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:35 +msgid "Non Pre-emptive CRC errors (CRC_P)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:394 +msgid "Non-wildcard" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:159 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:183 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:100 +msgid "None" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:177 +msgid "Normal" +msgstr "" + +#: modules/luci-base/luasrc/view/error404.htm:8 +msgid "Not Found" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:75 +msgid "Not associated" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:32 +msgid "Not connected" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:45 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:120 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:146 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:280 +msgid "Not present" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:101 +msgid "Not started on boot" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:409 +msgid "Not supported" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:167 +msgid "Notice" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:127 +msgid "Nslookup" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:332 +msgid "Number of IGMP membership reports" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:362 +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:199 +msgid "Number of parallel threads used for compression" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:309 +msgid "Number of peer notifications after failover event" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:69 +msgid "Obfuscated Group Password" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:61 +msgid "Obfuscated Password" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:105 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:97 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:49 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:80 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:54 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:67 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:93 +msgid "Obtain IPv6-Address" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:18 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:351 +msgid "Off" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:15 +msgid "Off-State Delay" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/default-on.js:18 +msgid "On" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:96 +msgid "On-Link route" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/timer.js:11 +msgid "On-State Delay" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:484 +msgid "One of hostname or mac address must be specified!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:466 +msgid "One of the following: %s" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/nullsection.htm:17 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:22 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/map.htm:32 +msgid "One or more invalid/required values on tab" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/nullsection.htm:19 +#: modules/luci-compat/luasrc/view/cbi/ucisection.htm:24 +msgid "One or more required fields have no value!" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:229 +msgid "" +"Only if current active slave fails and the primary slave is up (failure, 2)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:444 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:19 +msgid "Open list..." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_openconnect.lua:9 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:64 +msgid "OpenConnect (CISCO AnyConnect)" +msgstr "" + +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:12 +msgid "OpenFortivpn" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:882 +msgid "Operating frequency" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:1971 +#: modules/luci-base/htdocs/luci-static/resources/form.js:3653 +msgid "Option \"%s\" contains an invalid input value." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:1984 +msgid "Option \"%s\" must not be empty." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4037 +msgid "Option changed" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4039 +msgid "Option removed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1609 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:92 +msgid "Optional" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:102 +msgid "" +"Optional. 32-bit mark for outgoing encrypted packets. Enter value in hex, " +"starting with 0x." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:218 +msgid "" +"Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or " +"'::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating " +"server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') " +"for the interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:143 +msgid "" +"Optional. Base64-encoded preshared key. Adds in an additional layer of " +"symmetric-key cryptography for post-quantum resistance." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:159 +msgid "Optional. Create routes for Allowed IPs for this peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:134 +msgid "Optional. Description of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:87 +msgid "Optional. Do not create host routes to peers." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:161 +msgid "" +"Optional. Host of peer. Names are resolved prior to bringing up the " +"interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:97 +msgid "Optional. Maximum Transmission Unit of tunnel interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:165 +msgid "Optional. Port of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:169 +msgid "" +"Optional. Seconds between keep alive messages. Default is 0 (disabled). " +"Recommended value if this device is behind a NAT is 25." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:78 +msgid "Optional. UDP port used for outgoing and incoming packets." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:71 +msgid "Options" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:346 +msgid "Other:" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:68 +msgid "Out" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:275 +msgid "Outbound:" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:96 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:98 +msgid "Outgoing checksum" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:86 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:91 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:88 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:93 +msgid "Outgoing key" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:98 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:100 +msgid "Outgoing serialization" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:50 +msgid "Output Interface" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:59 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:165 +msgid "Output zone" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:57 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:222 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:40 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:50 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:76 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:71 +msgid "Override MAC address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:61 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:226 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:67 +#: protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js:44 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:54 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:120 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:158 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:71 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:145 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:132 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:110 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:119 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:77 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:62 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:57 +msgid "Override MTU" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:72 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:63 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:72 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:67 +msgid "Override TOS" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:72 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:58 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:67 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:62 +msgid "Override TTL" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1079 +msgid "Override default interface name" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:167 +msgid "Override the gateway in DHCP responses" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:603 +msgid "" +"Override the netmask sent to clients. Normally it is calculated from the " +"subnet that is served." +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 +msgid "Override the table used for internal routes" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:3 +msgid "Overview" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2721 +msgid "Overwrite existing file \"%s\" ?" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:70 +msgid "Owner" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:97 +msgid "PAP/CHAP (both)" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:98 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:108 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:45 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:44 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:63 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:82 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:46 +msgid "PAP/CHAP password" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:96 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:103 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:88 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:43 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:74 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:42 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:61 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:77 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:44 +msgid "PAP/CHAP username" +msgstr "" + +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:101 +msgid "PDP Type" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:69 +msgid "PID" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:95 +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:94 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:87 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:68 +msgid "PIN" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:21 +#: modules/luci-compat/luasrc/model/network.lua:39 +msgid "PIN code rejected" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1477 +msgid "PMK R1 Push" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:13 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:43 +msgid "PPP" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:58 +msgid "PPPoA Encapsulation" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:19 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:28 +msgid "PPPoATM" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:17 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:28 +msgid "PPPoE" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_pppossh.lua:9 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:28 +msgid "PPPoSSH" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ppp.lua:15 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:28 +msgid "PPtP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:73 +msgid "PSID offset" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:70 +msgid "PSID-bits length" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:918 +msgid "PTM/EFM (Packet Transfer Mode)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:882 +msgid "Packet Steering" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +msgid "Packets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:275 +msgid "Packets To Transmit Before Moving To Next Slave" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:152 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:825 +msgid "Part of zone %q" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:29 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1599 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:51 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:108 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:52 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:58 +msgid "Password" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:25 +msgid "Password authentication" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1531 +msgid "Password of Private Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1589 +msgid "Password of inner Private Key" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:31 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:33 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:35 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:37 +msgid "Password strength" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:111 +msgid "Password2" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:239 +msgid "Paste or drag SSH key file…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1510 +msgid "Path to CA-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1525 +msgid "Path to Client-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1528 +msgid "Path to Private Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1568 +msgid "Path to inner CA-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1583 +msgid "Path to inner Client-Certificate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1586 +msgid "Path to inner Private Key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2731 +msgid "Paused" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:271 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/bandwidth.js:281 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:332 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:342 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:352 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:237 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:247 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/load.js:257 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:266 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:276 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:294 +msgid "Peak:" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:89 +msgid "Peer IP address to assign" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:14 +#: modules/luci-compat/luasrc/model/network.lua:32 +msgid "Peer address is missing" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:115 +msgid "Peers" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:80 +msgid "Perfect Forward Secrecy" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:93 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:98 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:100 +msgid "Perform outgoing packets serialization (optional)." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:34 +msgid "Perform reboot" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:378 +msgid "Perform reset" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:407 +msgid "Permission denied" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:169 +msgid "Persistent Keep Alive" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:288 +msgid "Phy Rate:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:325 +msgid "Physical Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:80 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:90 +msgid "Ping" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:48 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:49 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:83 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:84 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:138 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:63 +msgid "Pkts." +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:19 +msgid "Please enter your username and password." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3768 +msgid "Please select the file to upload." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +msgid "Policy" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:21 +msgid "Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:278 +msgid "Port status:" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:492 +msgid "Potential negation of: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:38 +msgid "Power Management Mode" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:36 +msgid "Pre-emptive CRC errors (CRCP_P)" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:73 +msgid "Prefer LTE" +msgstr "" + +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:74 +msgid "Prefer UMTS" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:33 +msgid "Prefix Delegated" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:143 +msgid "Preshared Key" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:131 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:102 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:76 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:89 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:112 +msgid "" +"Presume peer to be dead after given amount of LCP echo failures, use 0 to " +"ignore failures" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:407 +msgid "Prevent listening on these interfaces." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1075 +msgid "Prevents client-to-client communication" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:211 +msgid "Primary Slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:228 +msgid "" +"Primary becomes active slave when it comes back up if speed and duplex " +"better than current slave (better, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:227 +msgid "Primary becomes active slave whenever it comes back up (always, 0)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:61 +msgid "Private Key" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:64 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:63 +msgid "Processes" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:21 +msgid "Profile" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:66 +msgid "Prot." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:397 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:727 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:382 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:32 +msgid "Protocol" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:265 +msgid "Provide NTP server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:825 +msgid "Provide new network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1004 +msgid "Pseudo Ad-Hoc (ahdemo)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:139 +msgid "Public Key" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:275 +msgid "" +"Public keys allow for the passwordless SSH logins with a higher security " +"compared to the use of plain passwords. In order to upload a new key to the " +"device, paste an OpenSSH compatible public key line or drag a .pub file into the input field." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:214 +msgid "Public prefix routed to this device for distribution to clients." +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:9 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:27 +msgid "QMI Cellular" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:41 +msgid "Quality" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:264 +msgid "" +"Query all available upstream DNS " +"servers" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1465 +msgid "R0 Key Lifetime" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1471 +msgid "R1 Key Holder" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:88 +msgid "RFC3947 NAT-T mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:939 +msgid "RSSI threshold for joining" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:903 +msgid "RTS/CTS Threshold" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:48 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:83 +msgid "RX" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:142 +msgid "RX Rate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2072 +msgid "RX Rate / TX Rate" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1343 +msgid "Radius-Accounting-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1348 +msgid "Radius-Accounting-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1338 +msgid "Radius-Accounting-Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1328 +msgid "Radius-Authentication-Port" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1333 +msgid "Radius-Authentication-Secret" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1323 +msgid "Radius-Authentication-Server" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:102 +msgid "Raw hex-encoded bytes. Leave empty unless your ISP require this" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:178 +msgid "" +"Read /etc/ethers to configure the DHCP-Server" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:402 +msgid "Really switch protocol?" +msgstr "" + +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:75 +msgid "Realtime Graphs" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1448 +msgid "Reassociation Deadline" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:293 +msgid "Rebind protection" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:20 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:126 +msgid "Reboot" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:153 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:162 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:46 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:51 +msgid "Rebooting…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:21 +msgid "Reboots the operating system of your device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:25 +msgid "Receive" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:83 +msgid "Recommended. IP addresses of the WireGuard interface." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:348 +msgid "Reconnect this interface" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:56 +msgid "References" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2725 +msgid "Refreshing" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:153 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:39 +msgid "Relay" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:157 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:36 +msgid "Relay Bridge" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:154 +msgid "Relay between networks" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_relay.lua:12 +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:64 +msgid "Relay bridge" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:50 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:49 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:40 +msgid "Remote IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:42 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:40 +msgid "Remote IPv4 address or FQDN" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:40 +msgid "Remote IPv6 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:42 +msgid "Remote IPv6 address or FQDN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:849 +msgid "Remove" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1914 +msgid "Replace wireless configuration" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:17 +msgid "Request IPv6-address" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:23 +msgid "Request IPv6-prefix of length" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:408 +msgid "Request timeout" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:90 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:95 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:97 +msgid "Require incoming checksum (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:92 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:97 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:94 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:99 +msgid "Require incoming packets serialization (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1610 +msgid "Required" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:34 +msgid "Required for certain ISPs, e.g. Charter with DOCSIS 3" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:61 +msgid "Required. Base64-encoded private key for this interface." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:139 +msgid "Required. Base64-encoded public key of peer." +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:148 +msgid "" +"Required. IP addresses and prefixes that this peer is allowed to use inside " +"the tunnel. Usually the peer's tunnel IP addresses and the networks the peer " +"routes through the tunnel." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1239 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1240 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1241 +msgid "Requires hostapd" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1246 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1247 +msgid "Requires hostapd with EAP Suite-B support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1244 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1245 +msgid "Requires hostapd with EAP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1248 +msgid "Requires hostapd with OWE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1242 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1243 +msgid "Requires hostapd with SAE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1237 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1238 +msgid "Requires hostapd with WEP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1607 +msgid "" +"Requires the 'full' version of wpad/hostapd and support from the wifi driver " +"
(as of Jan 2019: ath9k, ath10k, mwlwifi and mt76)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:233 +msgid "" +"Requires upstream supports DNSSEC; verify unsigned domain responses really " +"come from unsigned domains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1253 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1254 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1255 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1267 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1268 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1269 +msgid "Requires wpa-supplicant" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1260 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1261 +msgid "Requires wpa-supplicant with EAP Suite-B support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1258 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1259 +msgid "Requires wpa-supplicant with EAP support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1262 +msgid "Requires wpa-supplicant with OWE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1256 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1257 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1272 +msgid "Requires wpa-supplicant with SAE support" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1251 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1252 +msgid "Requires wpa-supplicant with WEP support" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:224 +msgid "Reselection policy for primary slave" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2203 +#: modules/luci-base/luasrc/view/sysauth.htm:39 +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:17 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:30 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:66 +msgid "Reset" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:308 +msgid "Reset Counters" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:376 +msgid "Reset to defaults" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:162 +msgid "Resolv and Hosts Files" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:188 +msgid "Resolve file" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:405 +msgid "Resource not found" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:350 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:817 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:100 +msgid "Restart" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:313 +msgid "Restart Firewall" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:815 +msgid "Restart radio interface" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:372 +msgid "Restore" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:382 +msgid "Restore backup" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:371 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:372 +msgid "Reveal/hide password" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4053 +msgid "Revert" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4138 +msgid "Revert changes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4320 +msgid "Revert request failed with status %h" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4300 +msgid "Reverting configuration…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:372 +msgid "Root directory for files served via TFTP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:297 +msgid "Root preparation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:202 +msgid "Round-Robin policy (balance-rr, 0)" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:159 +msgid "Route Allowed IPs" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:73 +msgid "Route table" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:60 +msgid "Route type" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:625 +msgid "Router Advertisement-Service" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:46 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:26 +msgid "Router Password" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:15 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:194 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:27 +msgid "Routes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:15 +msgid "" +"Routes specify over which interface and gateway a certain host or network " +"can be reached." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:206 +msgid "Rule" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:335 +msgid "Run a filesystem check before mounting the device" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:335 +msgid "Run filesystem check" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2364 +msgid "Runtime error" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:219 +msgid "SHA256" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:59 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:175 +msgid "SNR" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/dropbear.js:10 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:38 +msgid "SSH Access" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:70 +msgid "SSH server address" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:74 +msgid "SSH server port" +msgstr "" + +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:58 +msgid "SSH username" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:274 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:51 +msgid "SSH-Keys" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:156 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:181 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1662 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:42 +msgid "SSID" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:9 +msgid "SSTP" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:41 +msgid "SSTP Server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:339 +msgid "SWAP" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2866 +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2198 +#: modules/luci-compat/luasrc/view/cbi/error.htm:17 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:26 +#: modules/luci-compat/luasrc/view/cbi/header.htm:20 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:435 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:123 +msgid "Save" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2180 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4049 +#: modules/luci-compat/luasrc/view/cbi/footer.htm:22 +msgid "Save & Apply" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:602 +msgid "Save error" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:406 +msgid "Save mtdblock" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:396 +msgid "Save mtdblock contents" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:822 +msgid "Scan" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:26 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:76 +msgid "Scheduled Tasks" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4033 +msgid "Section added" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4035 +msgid "Section removed" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:331 +msgid "See \"mount\" manpage for details" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:257 +msgid "" +"Select 'Force upgrade' to flash the image even if the image format check " +"fails. Use only if you are sure that the firmware is correct and meant for " +"your device!" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2622 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2762 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2927 +msgid "Select file…" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:318 +msgid "Selects the transmit hash policy to use for slave selection" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:144 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:128 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:115 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:89 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:102 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:125 +msgid "" +"Send LCP echo requests at the given interval in seconds, only effective in " +"conjunction with failure threshold" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:24 +msgid "Send the hostname of this device" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:157 +msgid "Server Settings" +msgstr "" + +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:50 +msgid "Service Name" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:87 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:71 +msgid "Service Type" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:36 +msgid "Services" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2668 +msgid "Session expired" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:107 +msgid "Set VPN as Default Route" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:864 +msgid "" +"Set interface properties regardless of the link carrier (If set, carrier " +"sense events do not invoke hotplug handlers)." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:300 +msgid "Set same MAC Address to all slaves" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:642 +msgid "Set this interface as master for the dhcpv6 relay." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:304 +msgid "Set to currently active slave (active, 1)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:305 +msgid "Set to first slave added to the bond (follow, 2)" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:55 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:55 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:23 +msgid "Setting PLMN failed" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:68 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:26 +msgid "Setting operation mode failed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:565 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:575 +msgid "Setup DHCP Server" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:31 +msgid "Severely Errored Seconds (SES)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:208 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:80 +msgid "Short GI" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1085 +msgid "Short Preamble" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:442 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:18 +msgid "Show current backup file list" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:264 +msgid "Show empty chains" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:354 +msgid "Shutdown this interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:57 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:63 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:186 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1661 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:41 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:141 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:173 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:179 +msgid "Signal" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:2071 +msgid "Signal / Noise" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:26 +msgid "Signal Attenuation (SATN)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:260 +msgid "Signal:" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3786 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:217 +msgid "Size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:361 +msgid "Size of DNS query cache" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:187 +msgid "Size of the ZRam device in megabytes" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/footer.htm:18 +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:57 +msgid "Skip" +msgstr "" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:36 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:46 +msgid "Skip to content" +msgstr "" + +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:35 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:45 +msgid "Skip to navigation" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:178 +msgid "Slave Interfaces" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2883 +#: modules/luci-compat/luasrc/model/network.lua:1428 +msgid "Software VLAN" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/header.htm:5 +msgid "Some fields are invalid, cannot save values!" +msgstr "" + +#: modules/luci-base/luasrc/view/error404.htm:9 +msgid "Sorry, the object you requested was not found." +msgstr "" + +#: modules/luci-base/luasrc/view/error500.htm:9 +msgid "Sorry, the server encountered an unexpected error." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:414 +msgid "" +"Sorry, there is no sysupgrade support present; a new firmware image must be " +"flashed manually. Please refer to the wiki for device specific install " +"instructions." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:383 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:69 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:182 +msgid "Source" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:84 +msgid "Source Address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:50 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:50 +msgid "Source interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:342 +msgid "" +"Specifies that duplicate frames (received on inactive ports) should be " +"dropped or delivered" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:358 +msgid "Specifies the ARP link monitoring frequency in milliseconds" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:366 +msgid "Specifies the IP addresses to use for ARP monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:395 +msgid "Specifies the MII link monitoring frequency in milliseconds" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:259 +msgid "Specifies the aggregation selection logic to use" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:292 +msgid "Specifies the directory the device is attached to" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:252 +msgid "" +"Specifies the mac-address for the actor in protocol packet exchanges " +"(LACPDUs). If empty, masters' mac address defaults to system default" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:175 +msgid "" +"Specifies the maximum amount of failed ARP requests until hosts are presumed " +"to be dead" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:171 +msgid "" +"Specifies the maximum amount of seconds after which hosts are presumed to be " +"dead" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:886 +msgid "" +"Specifies the maximum transmit power the wireless radio may use. Depending " +"on regulatory requirements and wireless usage, the actual transmit power may " +"be reduced by the driver." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:236 +msgid "" +"Specifies the minimum number of links that must be active before asserting " +"carrier" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:200 +msgid "Specifies the mode to be used for this bonding interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:333 +msgid "" +"Specifies the number of IGMP membership reports to be issued after a " +"failover event in 200ms intervals" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:276 +msgid "" +"Specifies the number of packets to transmit through a slave before moving to " +"the next one" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:310 +msgid "" +"Specifies the number of peer notifications (gratuitous ARPs and unsolicited " +"IPv6 Neighbor Advertisements) to be issued after a failover event" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:284 +msgid "" +"Specifies the number of seconds between instances where the bonding driver " +"sends learning packets to each slaves peer switch" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:374 +msgid "Specifies the quantity of ARP IP targets that must be reachable" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:268 +msgid "" +"Specifies the rate in which the link partner will be asked to transmit " +"LACPDU packets" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:225 +msgid "" +"Specifies the reselection policy for the primary slave when failure of the " +"active slave or recovery of the primary slave occurs" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:244 +msgid "Specifies the system priority" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:403 +msgid "" +"Specifies the time in milliseconds to wait before disabling a slave after a " +"link failure detection" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:411 +msgid "" +"Specifies the time in milliseconds to wait before enabling a slave after a " +"link recovery detection" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:382 +msgid "" +"Specifies whether ARP probes and replies should be validated or non-ARP " +"traffic should be filtered for link monitoring" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:301 +msgid "" +"Specifies whether active-backup mode should set all slaves to the same MAC " +"address at enslavement" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:419 +msgid "" +"Specifies whether or not miimon should use MII or ETHTOOL ioctls vs. " +"netif_carrier_ok()" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:293 +msgid "" +"Specifies whether to shuffle active flows across slaves based on the load" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:179 +msgid "" +"Specifies which slave interfaces should be attached to this bonding interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:212 +msgid "" +"Specifies which slave is the primary device. It will always be the active " +"slave while it is available" +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:63 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:72 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:67 +msgid "Specify a TOS (Type of Service)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:72 +msgid "" +"Specify a TOS (Type of Service). Can be either inherit (the " +"outer header inherits the value of the inner header) or an hexadecimal value " +"starting with 0x (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:67 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:72 +msgid "" +"Specify a TTL (Time to Live) for the encapsulating packet other than the " +"default (64) (optional)." +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:58 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:67 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:62 +msgid "" +"Specify a TTL (Time to Live) for the encapsulating packet other than the " +"default (64)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:72 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:77 +msgid "" +"Specify a Traffic Class. Can be either inherit (the outer " +"header inherits the value of the inner header) or an hexadecimal value " +"starting with 0x (optional)." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:57 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:62 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:67 +msgid "" +"Specify an MTU (Maximum Transmission Unit) other than the default (1280 " +"bytes) (optional)." +msgstr "" + +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:62 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:57 +msgid "" +"Specify an MTU (Maximum Transmission Unit) other than the default (1280 " +"bytes)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "Specify the secret encryption key here." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:581 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:99 +msgid "Start" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:76 +msgid "Start priority" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1765 +msgid "Start refresh" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4253 +msgid "Starting configuration apply…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1678 +msgid "Starting wireless scan..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:109 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:64 +msgid "Startup" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:19 +msgid "Static IPv4 Routes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:19 +msgid "Static IPv6 Routes" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:165 +msgid "Static Leases" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:76 +msgid "Static Routes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1981 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:172 +#: modules/luci-compat/luasrc/model/network.lua:967 +msgid "Static address" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:411 +msgid "" +"Static leases are used to assign fixed IP addresses and symbolic hostnames " +"to DHCP clients. They are also required for non-dynamic interface " +"configurations where only hosts with a corresponding lease are served." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1102 +msgid "Station inactivity limit" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:16 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:385 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:871 +#: modules/luci-mod-status/luasrc/view/admin_status/index.htm:9 +msgid "Status" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:356 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:101 +msgid "Stop" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1676 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1770 +msgid "Stop refresh" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:259 +msgid "Strict order" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:33 +msgid "Strong" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/simpleform.htm:61 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1956 +msgid "Submit" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:203 +msgid "Suppress logging" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:204 +msgid "Suppress logging of the routine operation of these protocols" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:44 +msgid "Swap free" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:139 +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:3 +msgid "Switch" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:172 +msgid "Switch %q" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:150 +msgid "" +"Switch %q has an unknown topology - the VLAN settings might not be accurate." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2883 +#: modules/luci-compat/luasrc/model/network.lua:1426 +msgid "Switch VLAN" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:403 +msgid "Switch protocol" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:103 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:104 +#: modules/luci-compat/luasrc/view/cbi/ipaddr.htm:26 +msgid "Switch to CIDR list notation" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2657 +msgid "Symbolic link" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:75 +msgid "Sync with NTP-Server" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:67 +msgid "Sync with browser" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:26 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:17 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:99 +#: modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json:3 +msgid "System" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/syslog.js:25 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:39 +msgid "System Log" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:243 +msgid "System Priority" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:104 +msgid "System Properties" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:141 +msgid "System log buffer size" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:336 +msgid "TCP:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:163 +msgid "TFTP Settings" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:371 +msgid "TFTP server root" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:49 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:84 +msgid "TX" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:142 +msgid "TX Rate" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:17 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:166 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:184 +msgid "Table" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:31 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:65 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:163 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:181 +msgid "Target" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:103 +msgid "Target network" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:50 +msgid "Terminate" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:84 +msgid "The block mount command failed with code %d" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:77 +msgid "" +"The HE.net endpoint update configuration changed, you must now use the plain " +"username instead of the user ID!" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:40 +msgid "The IPv4 address or the fully-qualified domain name of the remote end." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:42 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:40 +msgid "" +"The IPv4 address or the fully-qualified domain name of the remote tunnel end." +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:40 +msgid "The IPv6 address or the fully-qualified domain name of the remote end." +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:42 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:42 +msgid "" +"The IPv6 address or the fully-qualified domain name of the remote tunnel end." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:53 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:59 +msgid "" +"The IPv6 prefix assigned to the provider, usually ends with ::" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1916 +msgid "" +"The allowed characters are: A-Z, a-z, 0-9 and _" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/error.htm:6 +msgid "The configuration file could not be loaded due to the following error:" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4129 +msgid "" +"The device could not be reached within %d seconds after applying the pending " +"changes, which caused the configuration to be rolled back for safety " +"reasons. If you believe that the configuration changes are correct " +"nonetheless, perform an unchecked configuration apply. Alternatively, you " +"can dismiss this warning and edit changes before attempting to apply again, " +"or revert all pending changes to keep the currently working configuration " +"state." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:280 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:392 +msgid "" +"The device file of the memory or partition (e.g." +" /dev/sda1)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:736 +msgid "" +"The existing wireless configuration needs to be changed for LuCI to function " +"properly." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:215 +msgid "" +"The flash image was uploaded. Below is the checksum and file size listed, " +"compare them with the original file to ensure data integrity.
Click " +"\"Proceed\" below to start the flash procedure." +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js:195 +msgid "The following rules are currently active on this system." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:154 +msgid "The gateway address must not be a local IP address" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:147 +msgid "The given SSH public key has already been added." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:153 +msgid "" +"The given SSH public key is invalid. Please supply proper public RSA or " +"ECDSA keys." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:716 +msgid "The interface name is already used" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:722 +msgid "The interface name is too long" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:55 +msgid "" +"The length of the IPv4 prefix in bits, the remainder is used in the IPv6 " +"addresses." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:63 +msgid "The length of the IPv6 prefix in bits" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:163 +msgid "The local IPv4 address" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js:46 +#: protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js:44 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:44 +msgid "The local IPv4 address over which the tunnel is created (optional)." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:169 +msgid "The local IPv4 netmask" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:46 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:46 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:44 +msgid "The local IPv6 address over which the tunnel is created (optional)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1922 +msgid "The network name is already used" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:139 +msgid "" +"The network ports on this device can be combined to several VLANs in which computers can " +"communicate directly with each other. VLANs are often used to separate different network " +"segments. Often there is by default one Uplink port for a connection to the " +"next greater network like the internet and other ports for a local network." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:158 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:42 +msgid "The reboot command failed with code %d" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:147 +msgid "The restore command failed with code %d" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1297 +msgid "The selected %s mode is incompatible with %s encryption" +msgstr "" + +#: modules/luci-base/luasrc/view/csrftoken.htm:11 +msgid "The submitted security token is invalid or already expired!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:98 +msgid "" +"The system is erasing the configuration partition now and will reboot itself " +"when finished." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:291 +msgid "" +"The system is flashing now.
DO NOT POWER OFF THE DEVICE!
Wait a " +"few minutes before you try to reconnect. It might be necessary to renew the " +"address of your computer to reach the device again, depending on your " +"settings." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:163 +msgid "" +"The system is rebooting now. If the restored configuration changed the " +"current LAN IP address, you might need to reconnect manually." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:85 +msgid "The system password has been successfully changed." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:317 +msgid "The sysupgrade command failed with code %d" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:120 +msgid "" +"The uploaded backup archive appears to be valid and contains the files " +"listed below. Press \"Continue\" to restore the backup and reboot, or " +"\"Cancel\" to abort the operation." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:115 +msgid "The uploaded backup archive is not readable" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:244 +msgid "The uploaded firmware does not allow keeping current configuration." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:239 +msgid "" +"The uploaded image file does not contain a supported format. Make sure that " +"you choose the generic image format for your platform." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:535 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:567 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:52 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:89 +msgid "There are no active leases" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:4268 +msgid "There are no changes to apply" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:55 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:213 +#: themes/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm:56 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:80 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:282 +msgid "" +"There is no password set on this router. Please configure a root password to " +"protect the web interface." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:49 +msgid "This IPv4 address of the relay" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1551 +msgid "This authentication type is not applicable to the selected EAP method." +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:57 +msgid "This does not look like a valid PEM file" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:256 +msgid "" +"This file may contain lines like 'server=/domain/1.2.3.4' or " +"'server=1.2.3.4' for domain-specific or full upstream DNS servers." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:426 +#: modules/luci-mod-system/luasrc/model/cbi/admin_system/backupfiles.lua:16 +msgid "" +"This is a list of shell glob patterns for matching files and directories to " +"include during sysupgrade. Modified files in /etc/config/ and certain other " +"configurations are automatically preserved." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:81 +msgid "" +"This is either the \"Update Key\" configured for the tunnel or the account " +"password if no update key has been configured" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:116 +msgid "" +"This is the content of /etc/rc.local. Insert your own commands here (in " +"front of 'exit 0') to execute them at the end of the boot process." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:54 +msgid "" +"This is the local endpoint address assigned by the tunnel broker, it usually " +"ends with ...:2/64" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:173 +msgid "" +"This is the only DHCP in the local network" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:73 +msgid "This is the plain username for logging into the account" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:57 +msgid "" +"This is the prefix routed to you by the tunnel broker for use by clients" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:28 +msgid "This is the system crontab in which scheduled tasks can be defined." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:50 +msgid "" +"This is usually the address of the nearest PoP operated by the tunnel broker" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/processes.js:65 +msgid "" +"This list gives an overview over currently running system processes and " +"their status." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1505 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1563 +msgid "" +"This option cannot be used because the ca-bundle package is not installed." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:2205 +#: modules/luci-base/htdocs/luci-static/resources/form.js:2511 +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:172 +#: modules/luci-compat/luasrc/view/cbi/tsection.htm:32 +msgid "This section contains no values yet" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:110 +msgid "Time Synchronization" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1093 +msgid "Time interval for rekeying GTK" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:124 +msgid "Timezone" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/luci.js:2678 +msgid "To login…" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:372 +msgid "" +"To restore configuration files, you can upload a previously generated backup " +"archive here. To reset the firmware to its initial state, click \"Perform " +"reset\" (only possible with squashfs images)." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:907 +msgid "Tone" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:35 +msgid "Total Available" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:102 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:103 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js:113 +msgid "Traceroute" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:53 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:64 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:96 +msgid "Traffic" +msgstr "" + +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js:72 +#: protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js:77 +msgid "Traffic Class" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:385 +msgid "Transfer" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:24 +msgid "Transmit" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:317 +msgid "Transmit Hash Policy" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/leds.js:74 +msgid "Trigger" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/led-trigger/netdev.js:19 +msgid "Trigger Mode" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:69 +msgid "Tunnel ID" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2886 +#: modules/luci-compat/luasrc/model/network.lua:1431 +msgid "Tunnel Interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:44 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:55 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:76 +msgid "Tunnel Link" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:185 +msgid "Tx-Power" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:44 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:43 +msgid "Type" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js:326 +msgid "UDP:" +msgstr "" + +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:90 +msgid "UMTS only" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_3g.lua:10 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:43 +msgid "UMTS/GPRS/EV-DO" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:254 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:360 +msgid "UUID" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:16 +#: modules/luci-base/htdocs/luci-static/resources/network.js:17 +#: modules/luci-compat/luasrc/model/network.lua:34 +#: modules/luci-compat/luasrc/model/network.lua:35 +msgid "Unable to determine device name" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:18 +#: modules/luci-compat/luasrc/model/network.lua:36 +msgid "Unable to determine external IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:19 +#: modules/luci-compat/luasrc/model/network.lua:37 +msgid "Unable to determine upstream interface" +msgstr "" + +#: modules/luci-base/luasrc/view/error404.htm:11 +msgid "Unable to dispatch" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/dmesg.js:9 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/syslog.js:15 +msgid "Unable to load log data:" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_modemmanager.lua:54 +#: modules/luci-compat/luasrc/model/network/proto_qmi.lua:54 +#: protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js:22 +msgid "Unable to obtain client ID" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:221 +msgid "Unable to obtain mount information" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:278 +msgid "Unable to reset ip6tables counters: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:276 +msgid "Unable to reset iptables counters: %s" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:7 +msgid "Unable to resolve AFTR host name" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:20 +#: modules/luci-compat/luasrc/model/network.lua:38 +msgid "Unable to resolve peer host name" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js:284 +msgid "Unable to restart firewall: %s" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js:20 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:342 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:57 +msgid "Unable to save contents: %s" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/50_dsl.js:33 +msgid "Unavailable Seconds (UAS)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/fs.js:102 +msgid "Unexpected reply data format" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1983 +#: modules/luci-compat/luasrc/model/network.lua:971 +msgid "Unknown" +msgstr "" + +#: protocols/luci-proto-modemmanager/htdocs/luci-static/resources/protocol/modemmanager.js:47 +msgid "Unknown and unsupported connection method." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2292 +#: modules/luci-compat/luasrc/model/network.lua:1138 +msgid "Unknown error (%s)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:412 +msgid "Unknown error code" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:1980 +#: modules/luci-base/htdocs/luci-static/resources/protocol/none.js:6 +#: modules/luci-compat/luasrc/model/network.lua:965 +msgid "Unmanaged" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:195 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:217 +msgid "Unmount" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:112 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js:259 +msgid "Unnamed key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3973 +msgid "Unsaved Changes" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/rpc.js:410 +msgid "Unspecified error" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_4x6.lua:64 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:9 +msgid "Unsupported MAP type" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_ncm.lua:69 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:27 +msgid "Unsupported modem" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:267 +msgid "Unsupported protocol type." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/tblsection.htm:151 +msgid "Up" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:410 +msgid "Up Delay" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3860 +msgid "Upload" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:413 +msgid "" +"Upload a sysupgrade-compatible image here to replace the running firmware." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:138 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:169 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:384 +msgid "Upload archive..." +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2816 +msgid "Upload file" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2791 +msgid "Upload file…" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:2738 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3848 +msgid "Upload request failed: %s" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3767 +#: modules/luci-base/htdocs/luci-static/resources/ui.js:3821 +msgid "Uploading file…" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:737 +msgid "" +"Upon pressing \"Continue\", anonymous \"wifi-iface\" sections will be " +"assigned with a name in the form wifinet# and the network will be " +"restarted to apply the updated configuration." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:81 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/10_system.js:60 +msgid "Uptime" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:177 +msgid "Use /etc/ethers" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:269 +msgid "Use DHCP advertised servers" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:167 +msgid "Use DHCP gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:40 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:124 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:39 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:116 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:68 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:59 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:103 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:90 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:77 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:100 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:69 +msgid "Use DNS servers advertised by peer" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:565 +msgid "Use ISO/IEC 3166 alpha2 country codes." +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:56 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:97 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:77 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:61 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:75 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "Use MTU on tunnel interface" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:93 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:73 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:57 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:88 +msgid "Use TTL on tunnel interface" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:320 +msgid "Use XOR of hardware MAC addresses (layer2)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:321 +msgid "Use XOR of hardware MAC addresses and IP addresses (layer2+3)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:323 +msgid "" +"Use XOR of hardware MAC addresses and IP addresses, rely on skb_flow_dissect " +"(encap2+3)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:294 +msgid "Use as external overlay (/overlay)" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:293 +msgid "Use as root filesystem (/)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:34 +msgid "Use broadcast flag" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:860 +msgid "Use builtin IPv6-management" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:43 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:182 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:127 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:42 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:119 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:62 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:106 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:93 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:67 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:80 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:103 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:72 +msgid "Use custom DNS servers" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:37 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:116 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:33 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:64 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:56 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:100 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:87 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:61 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:74 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:97 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:61 +msgid "Use default gateway" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:48 +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:230 +#: protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js:119 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js:51 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js:88 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js:68 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js:52 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:70 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:83 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:111 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:153 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:72 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js:67 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js:111 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js:98 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:72 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:85 +#: protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js:108 +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:64 +msgid "Use gateway metric" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:96 +msgid "Use legacy MAP" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:96 +msgid "" +"Use legacy MAP interface identifier format (draft-ietf-softwire-map-00) " +"instead of RFC7597" +msgstr "" + +#: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 +msgid "Use routing table" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1498 +msgid "Use system certificates" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1556 +msgid "Use system certificates for inner-tunnel" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:412 +msgid "" +"Use the Add Button to add a new lease entry. The MAC-Address identifies the host, the IPv4-Address specifies the fixed " +"address to use, and the Hostname is assigned as a symbolic name to " +"the requesting host. The optional Lease time can be used to set non-" +"standard host-specific lease time, e.g. 12h, 3d or infinite." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:322 +msgid "Use upper layer protocol information (layer3+4)" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:324 +msgid "" +"Use upper layer protocol information, rely on skb_flow_dissect (encap3+4)" +msgstr "" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/20_memory.js:36 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:194 +msgid "Used" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1394 +msgid "Used Key Slot" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1437 +msgid "" +"Used for two different purposes: RADIUS NAS ID and 802.11r R0KH-ID. Not " +"needed with normal WPA(2)-PSK." +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:105 +msgid "User Group" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:114 +msgid "User certificate (PEM encoded)" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:126 +msgid "User key (PEM encoded)" +msgstr "" + +#: modules/luci-base/luasrc/view/sysauth.htm:23 +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:106 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:50 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:56 +msgid "Username" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:975 +msgid "VC-Mux" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:923 +msgid "VDSL" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:173 +msgid "VLANs on %q" +msgstr "" + +#: modules/luci-base/root/usr/share/luci/menu.d/luci-base.json:54 +msgid "VPN" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:42 +msgid "VPN Local address" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:46 +msgid "VPN Local port" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:96 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:42 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js:58 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:39 +msgid "VPN Server" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:99 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:45 +msgid "VPN Server port" +msgstr "" + +#: protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js:103 +#: protocols/luci-proto-openfortivpn/htdocs/luci-static/resources/protocol/openfortivpn.js:60 +msgid "VPN Server's certificate SHA1 hash" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_vpnc.lua:9 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:9 +msgid "VPNC (CISCO 3000 (and others) VPN)" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:10 +msgid "VXLAN (RFC7348)" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js:53 +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:48 +msgid "VXLAN network identifier" +msgstr "" + +#: protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js:10 +msgid "VXLANv6 (RFC7348)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1498 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1556 +msgid "" +"Validate server certificate using built-in system CA bundle,
requires " +"the \"ca-bundle\" package" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:387 +msgid "Validation for all slaves" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:385 +msgid "Validation only for active slave" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:386 +msgid "Validation only for backup slaves" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:154 +msgid "Value must not be empty" +msgstr "" + +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:73 +msgid "Vendor" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/dhcp.js:55 +msgid "Vendor Class to send when requesting DHCP" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js:196 +msgid "Verifying the uploaded image file." +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:59 +msgid "Virtual dynamic interface" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1032 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1033 +msgid "WDS" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1217 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1306 +msgid "WEP Open System" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1218 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1307 +msgid "WEP Shared Key" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "WEP passphrase" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1070 +msgid "WMM Mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1931 +msgid "WPA passphrase" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1208 +msgid "" +"WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " +"and ad-hoc mode) to be installed." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:47 +msgid "Waiting for device..." +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:168 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:178 +msgid "Warning" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js:26 +msgid "Warning: There are unsaved changes that will get lost on reboot!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js:37 +msgid "Weak" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1460 +msgid "" +"When using a PSK, the PMK can be automatically generated. When enabled, the " +"R0/R1 key options below are not applied. Disable this to use the R0 and R1 " +"key options." +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm:166 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:468 +msgid "Width" +msgstr "" + +#: modules/luci-compat/luasrc/model/network/proto_wireguard.lua:9 +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:29 +msgid "WireGuard VPN" +msgstr "" + +#: modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json:17 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:87 +#: modules/luci-mod-status/root/usr/share/luci/menu.d/luci-mod-status.json:105 +msgid "Wireless" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2874 +#: modules/luci-compat/luasrc/model/network.lua:1419 +msgid "Wireless Adapter" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/network.js:2853 +#: modules/luci-base/htdocs/luci-static/resources/network.js:4057 +#: modules/luci-compat/luasrc/model/network.lua:1405 +#: modules/luci-compat/luasrc/model/network.lua:1868 +msgid "Wireless Network" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:753 +msgid "Wireless Overview" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:922 +msgid "Wireless Security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:735 +msgid "Wireless configuration migration" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:153 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:193 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:47 +msgid "Wireless is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:153 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:193 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:47 +msgid "Wireless is not associated" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:877 +msgid "Wireless network is disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:877 +msgid "Wireless network is enabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:275 +msgid "Write received DNS requests to syslog" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:160 +msgid "Write system log to file" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:204 +msgid "XOR policy (balance-xor, 2)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3643 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:295 +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:344 +#: protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js:109 +msgid "Yes" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:303 +msgid "Yes (none, 0)" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:176 +msgid "" +"You appear to be currently connected to the device via the \"%h\" interface. " +"Do you really want to shut down the interface?" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js:112 +msgid "" +"You can enable or disable installed init scripts here. Changes will applied " +"after a device reboot.
Warning: If you disable essential init " +"scripts like \"network\", your device might become inaccessible!" +msgstr "" + +#: themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm:65 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:223 +#: themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm:73 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:294 +msgid "" +"You must enable JavaScript in your browser or LuCI will not work properly." +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:115 +msgid "" +"You must select a primary interface which is included in selected slave " +"interfaces!" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:96 +msgid "" +"You must select at least one ARP IP target if ARP monitoring is selected!" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:192 +msgid "ZRam Compression Algorithm" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:199 +msgid "ZRam Compression Streams" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:185 +msgid "ZRam Settings" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js:187 +msgid "ZRam Size" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:331 +msgid "any" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:908 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:916 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:921 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1157 +#: protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js:78 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:48 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:51 +#: protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js:103 +msgid "auto" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:85 +msgid "automatic" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:82 +msgid "baseT" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:981 +msgid "bridged" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:146 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:401 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:35 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:99 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:31 +msgid "create" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:69 +msgid "create:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:55 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:57 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:58 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:62 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:63 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:83 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:84 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:87 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:185 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:186 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:187 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:171 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:173 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:174 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:178 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js:179 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:261 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:264 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:267 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:271 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:274 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:277 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:303 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:304 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:305 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:309 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:310 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:311 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:313 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:314 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/wireless.js:315 +msgid "dBm" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1014 +msgid "disable" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/protocol/static.js:185 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:626 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:632 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:638 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:91 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js:25 +msgid "disabled" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:519 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:553 +msgid "driver default" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:81 +msgid "e.g: --proxy 10.10.10.10" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:83 +msgid "e.g: dump" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:524 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:545 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:42 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:69 +msgid "expired" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:182 +msgid "" +"file where given DHCP-leases will be stored" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:85 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:195 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:61 +msgid "forward" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:84 +msgid "full-duplex" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:84 +msgid "half-duplex" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:569 +msgid "hexadecimal encoded value" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1738 +msgid "hidden" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:629 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:635 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:640 +msgid "hybrid mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/routes.js:36 +msgid "if target is a network" +msgstr "" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js:63 +msgid "ignore" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:69 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:191 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:46 +msgid "input" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:395 +msgid "key between 8 and 63 characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:407 +msgid "key with either 5 or 13 characters" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:189 +msgid "local DNS file" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1316 +msgid "medium security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1465 +msgid "minutes" +msgstr "" + +#: protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js:422 +msgid "netif_carrier_ok()" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +msgid "no" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:76 +msgid "no link" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:59 +msgid "non-empty value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3007 +msgid "none" +msgstr "" + +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:41 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:55 +#: modules/luci-mod-system/htdocs/luci-static/resources/view/system/mounts.js:69 +msgid "not present" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:347 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:901 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:905 +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:197 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:245 +msgid "off" +msgstr "" + +#: themes/luci-theme-material/luasrc/view/themes/material/header.htm:196 +#: themes/luci-theme-rosy/luasrc/view/themes/rosy/header.htm:242 +msgid "on" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1317 +msgid "open network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:69 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:46 +msgid "output" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:241 +msgid "positive decimal value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:233 +msgid "positive integer value" +msgstr "" + +#: protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js:80 +msgid "random" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:628 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:634 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:639 +msgid "relay mode" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:982 +msgid "routed" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1093 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1102 +msgid "sec" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:627 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:633 +msgid "server mode" +msgstr "" + +#: protocols/luci-proto-sstp/htdocs/luci-static/resources/protocol/sstp.js:53 +msgid "sstpc Log-level" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:649 +msgid "stateful-only" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:647 +msgid "stateless" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:648 +msgid "stateless + stateful" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1315 +msgid "strong security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:352 +msgid "tagged" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1448 +msgid "time units (TUs / 1.024 ms) [1000-65535]" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:559 +msgid "unique value" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:534 +msgid "unknown" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:340 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:522 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:543 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:40 +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js:67 +msgid "unlimited" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/form.js:3372 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:76 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:138 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:369 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:393 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:428 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:465 +#: modules/luci-base/htdocs/luci-static/resources/tools/widgets.js:561 +#: modules/luci-compat/luasrc/view/cbi/firewall_zonelist.htm:53 +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:38 +msgid "unspecified" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/network_netlist.htm:71 +msgid "unspecified -or- create:" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/switch.js:350 +msgid "untagged" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:246 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:121 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:132 +msgid "valid IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:246 +msgid "valid IP address or prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:281 +msgid "valid IPv4 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:254 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:125 +msgid "valid IPv4 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:254 +msgid "valid IPv4 address or network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:374 +msgid "valid IPv4 address:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:314 +msgid "valid IPv4 network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:276 +msgid "valid IPv4 or IPv6 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:267 +msgid "valid IPv4 prefix value (0-32)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:286 +msgid "valid IPv6 CIDR" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:262 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:129 +msgid "valid IPv6 address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:262 +msgid "valid IPv6 address or prefix" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:304 +msgid "valid IPv6 host id" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:319 +msgid "valid IPv6 network" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:272 +msgid "valid IPv6 prefix value (0-128)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:340 +msgid "valid MAC address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:411 +msgid "valid UCI identifier" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:362 +msgid "valid UCI identifier, hostname or IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:383 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:386 +msgid "valid address:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:533 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:537 +msgid "valid date (YYYY-MM-DD)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:237 +msgid "valid decimal value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:405 +msgid "valid hexadecimal WEP key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:393 +msgid "valid hexadecimal WPA key" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:368 +msgid "valid host:port" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:355 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:357 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:73 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:79 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:107 +msgid "valid hostname" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:345 +msgid "valid hostname or IP address" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:229 +msgid "valid integer value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:309 +msgid "valid network in address/netmask notation" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:508 +msgid "valid phone digit (0-9, \"*\", \"#\", \"!\" or \".\")" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:332 +#: modules/luci-base/htdocs/luci-static/resources/validation.js:335 +msgid "valid port or port range (port1-port2)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:324 +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:136 +msgid "valid port value" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:513 +msgid "valid time (HH:MM:SS)" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:435 +msgid "value between %d and %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:416 +msgid "value between %f and %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:420 +msgid "value greater or equal to %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:424 +msgid "value smaller or equal to %f" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:429 +msgid "value with %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:440 +msgid "value with at least %d characters" +msgstr "" + +#: modules/luci-base/htdocs/luci-static/resources/validation.js:445 +msgid "value with at most %d characters" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js:1317 +msgid "weak security" +msgstr "" + +#: modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js:46 +msgid "yes" +msgstr "" + +#: modules/luci-compat/luasrc/view/cbi/delegator.htm:20 +msgid "« Back" +msgstr "" diff --git a/luci-mod-dashboard/Makefile b/luci-mod-dashboard/Makefile new file mode 100755 index 000000000..6a6d84166 --- /dev/null +++ b/luci-mod-dashboard/Makefile @@ -0,0 +1,21 @@ +# +# Copyright 2019-2020 ZHANG Zhao +# Copyright 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the Apache License, Version 2.0 . +# +# Based on openwrt luci commit 03c77dafe3cfb922b995adfe9c0f8a75c98a18af +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Dashboard Pages +LUCI_DEPENDS:=+luci-base +libiwinfo + +PKG_BUILD_DEPENDS:=iwinfo +PKG_LICENSE:=Apache-2.0 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature + diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css new file mode 100755 index 000000000..f20713832 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css @@ -0,0 +1,300 @@ +/** + * Dashboard Principals Styles +**/ + +.Dashboard { + color: #212529!important; +} + +.Dashboard h3 { + color:#000; + background: transparent; +} + +.Dashboard hr { + border: 0; + height: 0; + overflow: visible; + margin: 0; + box-sizing: content-box; + border-top: 1px solid rgba(0,0,0,.1); +} + +.Dashboard .box-s1 { + min-height: 550px; +} + +.Dashboard .internet-status-self .internet-status-info .title { + height: 97px; +} + +.Dashboard .dashboard-bg { + border-radius: 16px; + background-color: #e0e0e0; +} + +.Dashboard div > table > tbody > tr:nth-of-type(2n), div > .table > .tr:nth-of-type(2n) { + background-color: transparent; +} +.Dashboard .tr { + background-color: transparent; +} + +.Dashboard .title { + text-align: center; +} + +.Dashboard .section-content { + display: flex; + vertical-align: top; + padding: 20px 0 0 0; + align-items: flex-start; + justify-content: space-between; +} + +.Dashboard .section-content > div { + width:100%; + padding:1.5em; +} + +.Dashboard .section-content .settings-info { + padding-top:1em; +} + +.Dashboard .section-content .internet-status-info .settings-info { + display: flex; + justify-content: space-around; +} + +.Dashboard .section-content .internet-status-info .settings-info > div > p > i{ + padding: 0 0 0 5px; +} + +.Dashboard .section-content > div:nth-child(2) { + margin-left:20px; +} + +.Dashboard .devices-list .devices-info { + margin-bottom: 0; +} + +.Dashboard .devices-list .devices-info .tr .td{ + padding:0px 0 0 10px; +} + +.Dashboard .devices-list .devices-info .tr .td:first-child { + width: 33%; + word-break: break-all; +} + +.Dashboard .devices-list hr:nth-child(4) { + margin-top: 0; + margin-bottom: 8px; +} + +.Dashboard .router-status-lan .devices-list .table-titles .th:first-child { + width: 35%; +} + +.Dashboard .router-status-self .router-status-info .settings-info { + padding-left:27px; +} + +.Dashboard .router-status-self .router-status-info .title h3 { + margin-top:-2px; +} + +.Dashboard .router-status-info svg { + width: 70px; +} + +.Dashboard .internet-status-self .settings-info p:first-child span:first-child{ + font-size: 12px; + font-weight: 500; +} + +//.Dashboard .internet-status-self .settings-info p:first-child span:first-child, +.Dashboard .router-status-wifi .wifi-info .settings-info p:first-child span:first-child, +.Dashboard .router-status-wifi .wifi-info .settings-info p:nth-child(2) span:first-child{ + font-weight: 700; +} + +.Dashboard .settings-info p span:first-child { + width: 35%; + font-size: 12px; + text-align: right; +} + +.Dashboard .settings-info p span:nth-child(2){ + display: inline-block; + word-break: break-all; + overflow: hidden; + max-height: 16px; + position: relative; + top:2px; +} + +.Dashboard .router-status-info .settings-info p span:nth-child(2){ + max-width: 283px; +} + +.Dashboard .settings-info p span.ssid { + max-height: 18px; + top: 3px; +} + +.Dashboard .settings-info p span.encryption { + max-width: 82px; +} + +.Dashboard .router-status-wifi .wifi-info .settings-info, +.Dashboard .router-status-lan .lan-info .settings-info +{ + display: flex; + justify-content: space-around; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .tr .td { + padding: 0 10px 0 10px; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .tr .td:first-child { + width: 30%; + word-break: break-all; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .tr .td:nth-child(2) { + width: 21%; + overflow: hidden; + padding-left:0; + word-break: break-all; +} + +.Dashboard .router-status-wifi .wifi-info .settings-info{ + padding:1em 0 1em 0; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .tr .td:nth-child(3) { + width: 22%; + overflow: hidden; + position: relative; + top: -3px; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .tr .td:nth-child(5) { + width: initial; +} + +.Dashboard .router-status-wifi .wifi-info > hr:last-child { + margin-bottom:0; +} + +.Dashboard .router-status-wifi .wifi-info .devices-info .device-info .progress { + padding: 0; + width: 100%; + margin: 0; +} + +.Dashboard .wifi-info .devices-info .table-titles { + border-bottom:1px solid rgba(0,0,0,.1); +} + +.Dashboard .label-success { + background-color: green; +} + +.Dashboard .label-danger { + background-color: red; +} + +/** + * Responsive + **/ +@media screen and (min-width: 200px) and (max-width: 640px) { + + .Dashboard .cbi-section-1 > .section-content { + padding-top:10px; + } + + .Dashboard .section-content { + display:block; + } + + .Dashboard .section-content > div{ + padding: 1em; + } + + .Dashboard .section-content > div:first-child { + margin-bottom:10px; + } + + .Dashboard .section-content > div:nth-child(2) { + margin:0; + } + + .Dashboard .router-status-self .router-status-info .settings-info { + padding:0; + } + + .Dashboard .section-content .internet-status-info .settings-info { + display:block; + } + + .Dashboard .section-content .internet-status-info .settings-info > div:first-child { + margin-bottom: 10px; + border-bottom: 1px solid rgba(0,0,0,.1); + } + + .Dashboard .section-content .router-status-lan .devices-info .table-titles { + display:block; + } + + .Dashboard .router-status-wifi .wifi-info .settings-info > div{ + flex:1; + } + + .Dashboard .section-content .router-status-lan .devices-info .table-titles .th:last-child{ + padding-left: 70px; + } + + .Dashboard .section-content .router-status-lan .devices-info .td:first-child{ + flex: 2 2 31%; + } + + .Dashboard .section-content .router-status-lan .devices-info .td:nth-child(2){ + flex: 1 1 24%; + padding: 0; + } + + .Dashboard .section-content .router-status-lan .devices-info .td:last-child{ + word-wrap: normal; + } + + .Dashboard .router-status-wifi .wifi-info .settings-info > div p:nth-child(6) > span:last-child{ + display: inline-block; + overflow: hidden; + height: 14px; + width: 52%; + word-break: break-word; + line-height: 15px; + } + + .Dashboard .wifi-info .devices-info .table-titles { + padding: 0; + margin: 0; + display: flex; + border-radius: initial; + } + + .Dashboard .wifi-info .devices-info .table-titles .th { + flex: 2 2 24%; + } + + .Dashboard .wifi-info .devices-info .tr .td { + flex: 2 2 10%; + } + + .Dashboard .wifi-info hr:nth-child(4) { + margin-bottom: 0; + } +} diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/devices.svg b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/devices.svg new file mode 100755 index 000000000..2ab09176b --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/devices.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/internet.svg b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/internet.svg new file mode 100755 index 000000000..8563603c9 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/internet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/not-internet.svg b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/not-internet.svg new file mode 100755 index 000000000..d66f8379f --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/not-internet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/router.svg b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/router.svg new file mode 100755 index 000000000..1ff29ee56 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/router.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/wireless.svg b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/wireless.svg new file mode 100755 index 000000000..576baafe8 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/icons/wireless.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js new file mode 100755 index 000000000..cf69d4d0e --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js @@ -0,0 +1,384 @@ +'use strict'; +'require baseclass'; +'require fs'; +'require rpc'; +'require network'; + +var callSystemBoard = rpc.declare({ + object: 'system', + method: 'board' +}); + +var callSystemInfo = rpc.declare({ + object: 'system', + method: 'info' +}); + +var callOpenMPTCProuterInfo = rpc.declare({ + object: 'openmptcprouter', + method: 'status' +}); + + +return baseclass.extend({ + + params: [], + + formatBytes: function(a,b=2){if(0===a)return"0 Bytes";const c=0>b?0:b,d=Math.floor(Math.log(a)/Math.log(1024));return parseFloat((a/Math.pow(1024,d)).toFixed(c))+" "+["Bytes","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"][d]}, + load: function() { + return Promise.all([ + network.getWANNetworks(), + network.getWAN6Networks(), + L.resolveDefault(callSystemBoard(), {}), + L.resolveDefault(callSystemInfo(), {}), + L.resolveDefault(callOpenMPTCProuterInfo(), {}) + ]); + }, + + renderHtml: function(data, type) { + + var icon = type; + var title = 'router' == type ? _('System') : _('Internet'); + var container_wapper = E('div', { 'class': type + '-status-self dashboard-bg box-s1'}); + var container_box = E('div', { 'class': type + '-status-info'}); + var container_item = E('div', { 'class': 'settings-info'}); + + if ('internet' == type) { + icon = (data.internet.v4.connected.value || data.internet.v6.connected.value) ? type : 'not-internet'; + } + + container_box.appendChild(E('div', { 'class': 'title'}, [ + E('img', { + 'src': L.resource('view/dashboard/icons/' + icon + '.svg'), + 'width': 'router' == type ? 64 : 54, + 'title': title, + 'class': 'middle' + }), + E('h3', title) + ])); + + container_box.appendChild(E('hr')); + + if ('internet' == type) { + + var container_internet_v4 = E('div'); + var container_internet_v6 = E('div'); + var container_internet_vps = E('div'); + + for(var idx in data['vps']) { + var classname = ver, + suppelements = '', + visible = data['vps'][idx].visible; + if ('title' === idx) { + container_internet_vps.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('h4', {'class': ''}, [ data['vps'].title ]), + ]) + ); + continue; + } + if (visible) { + container_internet_vps.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('span', {'class': ''}, [ data['vps'][idx].title + ':' ]), + E('span', {'class': ''}, [ data['vps'][idx].value ]), + suppelements + ]) + ); + } + } + + + for(var idx in data['internet']) { + + for(var ver in data['internet'][idx]) { + var classname = ver, + suppelements = '', + visible = data['internet'][idx][ver].visible; + + if('connected' === ver) { + classname = data['internet'][idx][ver].value ? 'label label-success' : 'label label-danger'; + data['internet'][idx][ver].value = data['internet'][idx][ver].value ? _('yes') : _('no'); + } + + if ('v4' === idx) { + + if ('title' === ver) { + container_internet_v4.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('h4', {'class': ''}, [ data['internet'][idx].title ]), + ]) + ); + continue; + } + + if ('addrsv4' === ver) { + var addrs = data['internet'][idx][ver].value; + if(Array.isArray(addrs) && addrs.length) { + for(var ip in addrs) { + data['internet'][idx][ver].value = addrs[ip].split('/')[0]; + } + } + } + + if (visible) { + container_internet_v4.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('span', {'class': ''}, [ data['internet'][idx][ver].title + ':' ]), + E('span', {'class': classname }, [ data['internet'][idx][ver].value ]), + suppelements + ]) + ); + } + + } else { + + if ('title' === ver) { + container_internet_v6.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('h4', {'class': ''}, [ data['internet'][idx].title ]), + ]) + ); + continue; + } + + if (visible) { + container_internet_v6.appendChild( + E('p', {'class': 'mt-2'}, [ + E('span', {'class': ''}, [data['internet'][idx][ver].title + ':']), + E('span', {'class': classname}, [data['internet'][idx][ver].value]), + suppelements + ]) + ); + } + } + } + } + + container_item.appendChild(E('p', { 'class': 'table'}, [ + E('div', { 'class': 'tr' }, [ + E('div', { 'class': 'td' }, [ container_internet_vps ]) + ]), + E('div', { 'class': 'tr' }, [ + E('div', { 'class': 'td' }, [ + container_internet_v4 + ]), + E('div', { 'class': 'td' }, [ + container_internet_v6 + ]) + ]) + ])); + } else { + for(var idx in data) { + container_item.appendChild( + E('p', { 'class': 'mt-2'}, [ + E('span', {'class': ''}, [ data[idx].title + ':' ]), + E('span', {'class': ''}, [ data[idx].value ]) + ]) + ); + } + } + + container_box.appendChild(container_item); + container_box.appendChild(E('hr')); + container_wapper.appendChild(container_box); + return container_wapper; + }, + + renderUpdateWanData: function(data, v6) { + for (var i = 0; i < data.length; i++) { + var ifc = data[i]; + + if (v6) { + this.params.internet.v6.ipprefixv6.value = ifc.getIP6Prefix() || '-'; + this.params.internet.v6.gatewayv6.value = ifc.getGateway6Addr() || '-'; + this.params.internet.v6.protocol.value= ifc.getI18n() || E('em', _('Not connected')); + this.params.internet.v6.addrsv6.value = ifc.getIP6Addrs() || [ '-' ]; + this.params.internet.v6.dnsv6.value = ifc.getDNS6Addrs() || [ '-' ]; + this.params.internet.v6.connected.value = ifc.isUp(); + } else { + var uptime = ifc.getUptime(); + this.params.internet.v4.uptime.value = (uptime > 0) ? '%t'.format(uptime) : '-'; + this.params.internet.v4.protocol.value= ifc.getI18n() || E('em', _('Not connected')); + this.params.internet.v4.gatewayv4.value = ifc.getGatewayAddr() || '0.0.0.0'; + this.params.internet.v4.connected.value = ifc.isUp(); + this.params.internet.v4.addrsv4.value = ifc.getIPAddrs() || [ '-']; + this.params.internet.v4.dnsv4.value = ifc.getDNSAddrs() || [ '-' ]; + } + } + }, + renderUpdateOpenMPTCProuterData: function(data, v6) { + if (data.openmptcprouter != undefined) { + if (data.openmptcprouter.wan_addr != '') this.params.omrvps.internet.v4.connected.value = true; + if (data.openmptcprouter.wan_addr) this.params.omrvps.internet.v4.addrsv4.value = data.openmptcprouter.wan_addr || [ '-']; + if (data.openmptcprouter.wan_addr6) this.params.omrvps.internet.v6.addrsv6.value = data.openmptcprouter.wan_addr6 || [ '-']; + if (data.openmptcprouter.vps_kernel) this.params.omrvps.vps.version.value = data.openmptcprouter.vps_kernel + ' ' + data.openmptcprouter.vps_omr_version || [ '-']; + if (data.openmptcprouter.vps_loadavg) { + var vps_loadavg = data.openmptcprouter.vps_loadavg.split(" "); + this.params.omrvps.vps.load.value = '%s, %s, %s'.format(vps_loadavg[0],vps_loadavg[1],vps_loadavg[2]); + } + if (data.openmptcprouter.vps_uptime) this.params.omrvps.vps.uptime.value = String.format('%t', data.openmptcprouter.vps_uptime) || [ '-']; + if (data.openmptcprouter.proxy_traffic) this.params.omrvps.vps.trafficproxy.value = this.formatBytes(data.openmptcprouter.proxy_traffic) || [ '-']; + if (data.openmptcprouter.vpn_traffic) this.params.omrvps.vps.trafficvpn.value = this.formatBytes(data.openmptcprouter.vpn_traffic) || [ '-']; + if (data.openmptcprouter.total_traffic) this.params.omrvps.vps.traffictotal.value = this.formatBytes(data.openmptcprouter.total_traffic) || [ '-']; + if (data.openmptcprouter.ipv6 != 'disabled') this.params.omrvps.internet.v6.connected.value = true; + } + }, + + renderInternetBox: function(data) { + + this.params.omrvps = { + vps: { + title: _('Server'), + + version: { + title: _('Version'), + visible: true, + value: [ '-' ] + }, + + load: { + title: _('Load'), + visible: true, + value: [ '-' ] + }, + + uptime: { + title: _('Uptime'), + visible: true, + value: [ '-' ] + }, + + trafficproxy: { + title: _('Proxy traffic'), + visible: true, + value: [ '-' ] + }, + + trafficvpn: { + title: _('VPN traffic'), + visible: true, + value: [ '-' ] + }, + + traffictotal: { + title: _('Total traffic'), + visible: true, + value: [ '-' ] + } + }, + + internet: { + + v4: { + title: _('IPv4 Internet'), + + connected: { + title: _('Connected'), + visible: true, + value: false + }, + + addrsv4: { + title: _('IPv4'), + visible: true, + value: [ '-' ] + } + }, + + v6: { + title: _('IPv6 Internet'), + + connected: { + title: _('Connected'), + visible: true, + value: false + }, + + ipprefixv6 : { + title: _('IPv6 prefix'), + visible: false, + value: ' - ' + }, + + addrsv6: { + title: _('IPv6'), + visible: true, + value: [ '-' ] + } + + } + } + }; + + //this.renderUpdateWanData(data[0], false); + //this.renderUpdateWanData(data[1], true); + this.renderUpdateOpenMPTCProuterData(data[4], true); + + return this.renderHtml(this.params.omrvps, 'internet'); + }, + + renderRouterBox: function(data) { + + var boardinfo = data[2], + systeminfo = data[3]; + + var datestr = null; + + if (systeminfo.localtime) { + var date = new Date(systeminfo.localtime * 1000); + + datestr = '%04d-%02d-%02d %02d:%02d:%02d'.format( + date.getUTCFullYear(), + date.getUTCMonth() + 1, + date.getUTCDate(), + date.getUTCHours(), + date.getUTCMinutes(), + date.getUTCSeconds() + ); + } + + this.params.router = { + uptime: { + title: _('Uptime'), + value: systeminfo.uptime ? '%t'.format(systeminfo.uptime) : null, + }, + + localtime: { + title: _('Local Time'), + value: datestr + }, + + load: { + title: _('Load Average'), + value: Array.isArray(systeminfo.load) ? '%.2f, %.2f, %.2f'.format(systeminfo.load[0] / 65535.0,systeminfo.load[1] / 65535.0,systeminfo.load[2] / 65535.0) : null + }, + + kernel: { + title: _('Kernel Version'), + value: boardinfo.kernel + }, + + model: { + title: _('Model'), + value: boardinfo.model + }, + + system: { + title: _('Architecture'), + value: boardinfo.system + }, + + release: { + title: _('Firmware Version'), + value: (typeof boardinfo.release !== "undefined") ? ((typeof boardinfo.release.description !== "undefined") ? boardinfo.release.description : null) : null + } + }; + + return this.renderHtml(this.params.router, 'router'); + }, + + render: function(data) { + return [this.renderInternetBox(data), this.renderRouterBox(data)]; + } +}); diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js new file mode 100755 index 000000000..c673fa681 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js @@ -0,0 +1,152 @@ +'use strict'; +'require baseclass'; +'require rpc'; +'require network'; + +var callLuciDHCPLeases = rpc.declare({ + object: 'luci-rpc', + method: 'getDHCPLeases', + expect: { '': {} } +}); + +return baseclass.extend({ + title: _('DHCP Devices'), + + params: {}, + + load: function() { + return Promise.all([ + callLuciDHCPLeases(), + network.getDevices() + ]); + }, + + renderHtml: function() { + + var container_wapper = E('div', { 'class': 'router-status-lan dashboard-bg box-s1' }); + var container_box = E('div', { 'class': 'lan-info devices-list' }); + var container_devices = E('table', { 'class': 'table assoclist devices-info' }, [ + E('tr', { 'class': 'tr table-titles dashboard-bg' }, [ + E('th', { 'class': 'th nowrap' }, _('Hostname')), + E('th', { 'class': 'th' }, _('IP Address')), + E('th', { 'class': 'th' }, _('MAC')), + ]) + ]); + + var container_deviceslist = E('table', { 'class': 'table assoclist devices-info' }); + + container_box.appendChild(E('div', { 'class': 'title'}, [ + E('img', { + 'src': L.resource('view/dashboard/icons/devices.svg'), + 'width': 55, + 'title': this.title, + 'class': 'middle' + }), + E('h3', this.title) + ])); + + for(var idx in this.params.lan.devices) { + var deivce = this.params.lan.devices[idx]; + + container_deviceslist.appendChild(E('tr', { 'class': 'tr cbi-rowstyle-1'}, [ + + E('td', { 'class': 'td device-info'}, [ + E('p', {}, [ + E('span', { 'class': 'd-inline-block'}, [ deivce.hostname ]), + ]), + ]), + + E('td', { 'class': 'td device-info'}, [ + E('p', {}, [ + E('span', { 'class': 'd-inline-block'}, [ deivce.ipv4 ]), + ]), + ]), + + E('td', { 'class': 'td device-info'}, [ + E('p', {}, [ + E('span', { 'class': 'd-inline-block'}, [ deivce.macaddr ]), + ]), + ]) + ])); + } + + if (this.params.lan.devices.length > 0) { + container_box.appendChild(E('hr')); + container_box.appendChild(container_devices); + container_box.appendChild(E('hr')); + container_box.appendChild(container_deviceslist); + container_wapper.appendChild(container_box); + } + + return container_wapper; + }, + + renderUpdateData: function(data, leases) { + + for(var item in data) { + if (/lan|br-lan/ig.test(data[item].ifname) && (typeof data[item].dev == 'object' && !data[item].dev.wireless)) { + var lan_device = data[item]; + var ipv4addr = lan_device.dev.ipaddrs.toString().split('/'); + + this.params.lan.ipv4 = ipv4addr[0] || '?'; + this.params.lan.ipv6 = ipv4addr[0] || '?'; + this.params.lan.macaddr = lan_device.dev.macaddr || '00:00:00:00:00:00'; + this.params.lan.rx_bytes = lan_device.dev.stats.rx_bytes ? '%.2mB'.format(lan_device.dev.stats.rx_bytes) : '-'; + this.params.lan.tx_bytes = lan_device.dev.stats.tx_bytes ? '%.2mB'.format(lan_device.dev.stats.tx_bytes) : '-'; + } + } + + var devices = []; + leases.map(function(lease) { + devices[lease.expires] = { + hostname: lease.hostname || '?', + ipv4: lease.ipaddr || '-', + macaddr: lease.macaddr || '00:00:00:00:00:00', + }; + }); + this.params.lan.devices = devices; + }, + + renderLeases: function(data) { + + var leases = Array.isArray(data[0].dhcp_leases) ? data[0].dhcp_leases : []; + + this.params.lan = { + ipv4: { + title: _('IPv4'), + value: '?' + }, + + macaddr: { + title: _('Mac'), + value: '00:00:00:00:00:00' + }, + + rx_bytes: { + title: _('Upload'), + value: '-' + }, + + tx_bytes: { + title: _('Download'), + value: '-' + }, + + devices: { + title: _('Devices'), + value: [] + } + }; + + this.renderUpdateData(data[1], leases); + + return this.renderHtml(); + }, + + render: function(data) { + if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd')) + return this.renderLeases(data); + + return E([]); + } +}); diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js new file mode 100755 index 000000000..fe5e843f0 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js @@ -0,0 +1,269 @@ +'use strict'; +'require baseclass'; +'require dom'; +'require network'; +'require rpc'; + +return baseclass.extend({ + + title: _('Wireless'), + + params: [], + + load: function() { + return Promise.all([ + network.getWifiDevices(), + network.getWifiNetworks(), + network.getHostHints() + ]).then(function(radios_networks_hints) { + var tasks = []; + + for (var i = 0; i < radios_networks_hints[1].length; i++) + tasks.push(L.resolveDefault(radios_networks_hints[1][i].getAssocList(), []).then(L.bind(function(net, list) { + net.assoclist = list.sort(function(a, b) { return a.mac > b.mac }); + }, this, radios_networks_hints[1][i]))); + + return Promise.all(tasks).then(function() { + return radios_networks_hints; + }); + }); + }, + + renderHtml: function() { + + var container_wapper = E('div', { 'class': 'router-status-wifi dashboard-bg box-s1' }); + var container_box = E('div', { 'class': 'wifi-info devices-list' }); + var container_radio = E('div', { 'class': 'settings-info' }); + var container_radio_item; + + container_box.appendChild(E('div', { 'class': 'title'}, [ + E('img', { + 'src': L.resource('view/dashboard/icons/wireless.svg'), + 'width': 55, + 'title': this.title, + 'class': 'middle' + }), + E('h3', this.title) + ])); + + container_box.appendChild(E('hr')); + + for (var i =0; i < this.params.wifi.radios.length; i++) { + + container_radio_item = E('div', { 'class': 'radio-info' }) + + for(var idx in this.params.wifi.radios[i]) { + var classname = idx, + radio = this.params.wifi.radios[i]; + + if (!radio[idx].visible) { + continue; + } + + if ('actived' === idx) { + classname = radio[idx].value ? 'label label-success' : 'label label-danger'; + radio[idx].value = radio[idx].value ? _('yes') : _('no'); + } + + container_radio_item.appendChild( + E('p', {}, [ + E('span', { 'class': ''}, [ radio[idx].title + ':']), + E('span', { 'class': classname }, [ radio[idx].value ]), + ]) + ); + } + + container_radio.appendChild(container_radio_item); + } + + container_box.appendChild(container_radio); + + var container_devices = E('div', { 'class': 'table assoclist devices-info' }, [ + E('div', { 'class': 'tr table-titles dashboard-bg' }, [ + E('div', { 'class': 'th nowrap' }, _('Hostname')), + E('div', { 'class': 'th' }, _('Wireless')), + E('div', { 'class': 'th' }, _('Signal')), + E('div', { 'class': 'th' }, '%s / %s'.format( _('Up.'), _('Down.'))) + ]) + ]); + + var container_devices_item; + var container_devices_list = E('div', { 'class': 'table assoclist devices-info' }); + + for (var i =0; i < this.params.wifi.devices.length; i++) { + container_devices_item = E('div', { 'class': 'tr cbi-rowstyle-1' }); + + for(var idx in this.params.wifi.devices[i]) { + var device = this.params.wifi.devices[i]; + + if (!device[idx].visible) { + continue; + } + + var container_content; + + if ('progress' == idx) { + container_content = E('div', { 'class' : 'td device-info' }, [ + E('div', { 'class': 'progress' }, [ + E('div', { 'class': 'progress-bar ' + device[idx].value.style, role: 'progressbar', style: 'width:'+device[idx].value.qualite+'%', 'aria-valuenow': device[idx].value.qualite, 'aria-valuemin': 0, 'aria-valuemax': 100 }), + ]) + ]); + } else if ('rate' == idx) { + container_content = E('div', { 'class': 'td device-info' }, [ + E('p', {}, [ + E('span', { 'class': ''}, [ device[idx].value.rx ]), + E('br'), + E('span', { 'class': ''}, [ device[idx].value.tx ]) + ]) + ]); + } else { + container_content = E('div', { 'class': 'td device-info'}, [ + E('p', {}, [ + E('span', { 'class': ''}, [ device[idx].value ]), + ]) + ]); + } + + container_devices_item.appendChild(container_content); + } + + container_devices_list.appendChild(container_devices_item); + } + + if (this.params.wifi.devices.length > 0) { + container_devices.appendChild(container_devices_list); + container_box.appendChild(E('hr')); + container_box.appendChild(container_devices); + container_box.appendChild(container_devices_list); + container_wapper.appendChild(container_box); + } + + return container_wapper; + }, + + renderUpdateData: function(radios, networks, hosthints) { + + for (var i = 0; i < radios.sort(function(a, b) { a.getName() > b.getName() }).length; i++) { + var network_items = networks.filter(function(net) { return net.getWifiDeviceName() == radios[i].getName() }); + + for (var j = 0; j < network_items.length; j++) { + var net = network_items[j], + is_assoc = (net.getBSSID() != '00:00:00:00:00:00' && net.getChannel() && !net.isDisabled()), + chan = net.getChannel(), + freq = net.getFrequency(), + rate = net.getBitRate(); + + this.params.wifi.radios.push( + { + ssid : { + title: _('SSID'), + visible: true, + value: net.getActiveSSID() || '?' + }, + + actived : { + title: _('Active'), + visible: true, + value: !net.isDisabled() + }, + + chan : { + title: _('Channel'), + visible: true, + value: chan ? '%d (%.3f %s)'.format(chan, freq, _('GHz')) : '-' + }, + + rate : { + title: _('Bitrate'), + visible: true, + value: rate ? '%d %s'.format(rate, _('Mbit/s')) : '-' + }, + + bssid : { + title: _('BSSID'), + visible: true, + value: is_assoc ? (net.getActiveBSSID() || '-') : '-' + }, + + encryption : { + title: _('Encryption'), + visible: true, + value: is_assoc ? net.getActiveEncryption() : '-' + }, + + associations : { + title: _('Devices Connected'), + visible: true, + value: is_assoc ? (net.assoclist.length || '0') : 0 + } + } + ); + } + } + + for (var i = 0; i < networks.length; i++) { + for (var k = 0; k < networks[i].assoclist.length; k++) { + var bss = networks[i].assoclist[k], + name = hosthints.getHostnameByMACAddr(bss.mac); + + var progress_style; + var q = Math.min((bss.signal + 110) / 70 * 100, 100); + + if (q == 0 || q < 25) + progress_style = 'bg-danger'; + else if (q < 50) + progress_style = 'bg-warning'; + else if (q < 75) + progress_style = 'bg-success'; + else + progress_style = 'bg-success'; + + this.params.wifi.devices.push( + { + hostname : { + title: _('Hostname'), + visible: true, + value: name || '?' + }, + + ssid : { + title: _('SSID'), + visible: true, + value: networks[i].getActiveSSID() + }, + + progress : { + title: _('Channel'), + visible: true, + value: { + qualite: q, + style: progress_style + } + }, + + rate : { + title: _('Bitrate'), + visible: true, + value: { + rx: '%s'.format('%.2mB'.format(bss.rx.bytes)), + tx: '%s'.format('%.2mB'.format(bss.tx.bytes)), + } + } + } + ); + } + } + }, + + render: function(data) { + + this.params.wifi = { + radios: [], + devices: [] + }; + + this.renderUpdateData(data[0], data[1], data[2]); + + return this.renderHtml(); + } +}); diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js new file mode 100755 index 000000000..c3e3b7027 --- /dev/null +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/index.js @@ -0,0 +1,110 @@ +'use strict'; +'require view'; +'require dom'; +'require poll'; +'require fs'; +'require network'; + +document.querySelector('head').appendChild(E('link', { + 'rel': 'stylesheet', + 'type': 'text/css', + 'href': L.resource('view/dashboard/css/custom.css') +})); + +function invokeIncludesLoad(includes) { + var tasks = [], has_load = false; + + for (var i = 0; i < includes.length; i++) { + if (typeof(includes[i].load) == 'function') { + tasks.push(includes[i].load().catch(L.bind(function() { + this.failed = true; + }, includes[i]))); + + has_load = true; + } + else { + tasks.push(null); + } + } + + return has_load ? Promise.all(tasks) : Promise.resolve(null); +} + +function startPolling(includes, containers) { + var step = function() { + return network.flushCache().then(function() { + return invokeIncludesLoad(includes); + }).then(function(results) { + for (var i = 0; i < includes.length; i++) { + var content = null; + + if (includes[i].failed) + continue; + + if (typeof(includes[i].render) == 'function') + content = includes[i].render(results ? results[i] : null); + else if (includes[i].content != null) + content = includes[i].content; + + if (content != null) { + + if (i > 1) { + dom.append(containers[1], content); + } else { + containers[i].parentNode.style.display = ''; + containers[i].parentNode.classList.add('fade-in'); + containers[i].parentNode.classList.add('Dashboard'); + dom.content(containers[i], content); + } + } + } + + var ssi = document.querySelector('div.includes'); + if (ssi) { + ssi.style.display = ''; + ssi.classList.add('fade-in'); + } + }); + }; + + return step().then(function() { + poll.add(step); + }); +} + +return view.extend({ + load: function() { + return L.resolveDefault(fs.list('/www' + L.resource('view/dashboard/include')), []).then(function(entries) { + return Promise.all(entries.filter(function(e) { + return (e.type == 'file' && e.name.match(/\.js$/)); + }).map(function(e) { + return 'view.dashboard.include.' + e.name.replace(/\.js$/, ''); + }).sort().map(function(n) { + return L.require(n); + })); + }); + }, + + render: function(includes) { + var rv = E([]), containers = []; + + for (var i = 0; i < includes.length - 1; i++) { + + var container = E('div', { 'class': 'section-content' }); + + rv.appendChild(E('div', { 'class': 'cbi-section-' + i, 'style': 'display:none' }, [ + container + ])); + + containers.push(container); + } + + return startPolling(includes, containers).then(function() { + return rv; + }); + }, + + handleSaveApply: null, + handleSave: null, + handleReset: null +}); diff --git a/luci-mod-dashboard/po/fr/dashboard.po b/luci-mod-dashboard/po/fr/dashboard.po new file mode 100755 index 000000000..ee91c668b --- /dev/null +++ b/luci-mod-dashboard/po/fr/dashboard.po @@ -0,0 +1,223 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2022-02-19 07:53+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "Actif" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "Architecture" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "Débit" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "Canal" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "Connecté" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "Périphériques DHCP" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "Tableau de bord" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "Périphériques" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "Périphériques connectés" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "En panne." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "Téléchargement" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "Chiffrement" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "Version du micrologiciel" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "GHz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "Permettre l'accès à l'affichage de l'état DHCP" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "Permettre l'accès à l'affichage de l'état principal" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "Permettre l’accès au status de routage" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "Permettre l'accès du status WIFI" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "Nom d'hôte" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "Adresse IP" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "Internet IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "Internet IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "Préfixe IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "Version du noyau" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "Charge" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "Charge moyenne" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "Heure locale" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "Mac" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "Modèle" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "Non connecté" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "Trafic proxy" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "Serveur" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "Signal" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "Système" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "Trafic total" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "En ligne." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "Téléverser" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "Temps de service" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "Trafic VPN" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "Version" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "Sans-fil" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "non" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "oui" diff --git a/luci-mod-dashboard/po/ru/dashboard.po b/luci-mod-dashboard/po/ru/dashboard.po new file mode 100755 index 000000000..466e9ab42 --- /dev/null +++ b/luci-mod-dashboard/po/ru/dashboard.po @@ -0,0 +1,224 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "Активный" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "Процессор" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "Скорость" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "Канал" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "Подключено" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "Устройства DHCP" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "Дашборд" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "Устройства" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "Подключенные устройства" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "Не работает." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "Получение" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "Шифрование" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "Версия ПО" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "GHz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "Разрешить просмотр информации о DHCP" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "Разрешить просмотр информации основной информации" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "Разрешить просмотр информации о маршрутах" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "Разрешить просмотр информации о беспроводных сетях" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "Имя хоста" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "IP-адрес" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "IPv4 Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "IPv6 Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "Префикс IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "Версия ядра" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "Загрузка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "Средняя загрузка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "Время хоста" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "Mac" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "Модель" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "Не подключено" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "Трафик через прокси" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "Сервер" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "Сигнал" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "Система" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "Трафик всего" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "Работает." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "Отправка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "Uptime" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "Трафик VPN" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "Версия" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "Безпроводной" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "нет" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "да" diff --git a/luci-mod-dashboard/po/templates/dashboard.pot b/luci-mod-dashboard/po/templates/dashboard.pot new file mode 100755 index 000000000..018a75101 --- /dev/null +++ b/luci-mod-dashboard/po/templates/dashboard.pot @@ -0,0 +1,214 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "" diff --git a/luci-mod-dashboard/po/zh_Hans/dashboard.po b/luci-mod-dashboard/po/zh_Hans/dashboard.po new file mode 100755 index 000000000..4da85b2c8 --- /dev/null +++ b/luci-mod-dashboard/po/zh_Hans/dashboard.po @@ -0,0 +1,223 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-02 09:51+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "激活" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "构架" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "比特率" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "频道" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "连接" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "DHCP 设备" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "仪表盘" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "设备" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "连接的设备" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "下." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "下载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "加密" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "固件版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "Ghz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "授予访问 DHCP 状态显示的权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "授予访问主状态显示的权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "授予对系统路由状态的访问权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "授予访问无线状态显示的权限" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "主机名" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "IP地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "IPv4互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "IPv6互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "IPv6前缀" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "内核版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "负载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "平均负载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "本地时间" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "mac地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "型号" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "未连接" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "代理流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "服务器" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "信号" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "系统" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "总流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "上." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "上传" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "开机时间" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "VPN流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "无线" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "否" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "是" diff --git a/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json b/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json new file mode 100755 index 000000000..555884674 --- /dev/null +++ b/luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json @@ -0,0 +1,13 @@ +{ + "admin/dashboard": { + "title": "Dashboard", + "order": 1, + "action": { + "type": "view", + "path": "dashboard/index" + }, + "depends": { + "acl": [ "luci-mod-dashboard-index" ] + } + } +} diff --git a/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json b/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json new file mode 100755 index 000000000..1f331e7b4 --- /dev/null +++ b/luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json @@ -0,0 +1,41 @@ +{ + "luci-mod-dashboard-routes": { + "description": "Grant access to the system route status", + "read": { + "ubus": { + "file": [ "exec" ] + } + } + }, + + "luci-mod-dashboard-index": { + "description": "Grant access to main status display", + "read": { + "file": { + "/www/luci-static/resources/view/status/include": [ "list" ] + }, + "ubus": { + "file": [ "list", "read" ], + "system": [ "board", "info" ] + } + } + }, + + "luci-mod-dashboard-index-dhcp": { + "description": "Grant access to DHCP status display", + "read": { + "ubus": { + "luci-rpc": [ "getDHCPLeases" ] + } + } + }, + + "luci-mod-dashboard-index-wifi": { + "description": "Grant access to wireless status display", + "read": { + "ubus": { + "iwinfo": [ "assoclist" ] + } + } + } +} diff --git a/luci-proto-mbim/Makefile b/luci-proto-mbim/Makefile old mode 100644 new mode 100755 diff --git a/luci-proto-mbim/htdocs/luci-static/resources/protocol/mbim.js b/luci-proto-mbim/htdocs/luci-static/resources/protocol/mbim.js old mode 100644 new mode 100755 index f6f548cc6..72bb9f7ba --- a/luci-proto-mbim/htdocs/luci-static/resources/protocol/mbim.js +++ b/luci-proto-mbim/htdocs/luci-static/resources/protocol/mbim.js @@ -51,8 +51,7 @@ return network.registerProtocol('mbim', { renderFormOptions: function(s) { var dev = this.getL3Device() || this.getDevice(), o; - o = s.taboption('general', form.Value, '_modem_device', _('Modem device')); - o.ucioption = 'device'; + o = s.taboption('general', form.Value, 'device', _('Modem device')); o.rmempty = false; o.load = function(section_id) { return callFileList('/dev/').then(L.bind(function(devices) { @@ -62,22 +61,14 @@ return network.registerProtocol('mbim', { }, this)); }; - o = s.taboption('general', form.Value, 'apn', _('APN')); - o.validate = function(section_id, value) { - if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value)) - return _('Invalid APN provided'); - - return true; - }; - - o = s.taboption('general', form.Value, 'pincode', _('PIN')); - o.datatype = 'and(uinteger,minlength(4),maxlength(8))'; + s.taboption('general', form.Value, 'apn', _('APN')); + s.taboption('general', form.Value, 'pincode', _('PIN')); o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); - o.value('both', _('PAP/CHAP')); - o.value('pap', _('PAP')); - o.value('chap', _('CHAP')); - o.value('none', _('None')); + o.value('both', 'PAP/CHAP'); + o.value('pap', 'PAP'); + o.value('chap', 'CHAP'); + o.value('none', 'NONE'); o.default = 'none'; o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); @@ -91,62 +82,19 @@ return network.registerProtocol('mbim', { o.depends('auth', 'both'); o.password = true; - o = s.taboption('general', form.ListValue, 'pdptype', _('PDP Type')); - o.value('ipv4v6', _('IPv4/IPv6')); - o.value('ipv4', _('IPv4')); - o.value('ipv6', _('IPv6')); - o.default = 'ipv4v6'; - if (L.hasSystemFeature('ipv6')) { - o = s.taboption('advanced', form.Flag, 'mbim_ipv6', _('Enable IPv6 negotiation')); - o.ucioption = 'ipv6'; - o.default = o.enabled; - } - - o = s.taboption('advanced', form.ListValue, 'dhcp', _('Use DHCP')); - o.value('', _('Automatic')); - o.value('0', _('Disabled')); - o.value('1', _('Enabled')); - o.depends('pdptype', 'ipv4'); - o.depends('pdptype', 'ipv4v6'); - o.default = ''; - - if (L.hasSystemFeature('ipv6')) { - o = s.taboption('advanced', form.ListValue, 'dhcpv6', _('Use DHCPv6')); - o.value('', _('Automatic')); - o.value('0', _('Disabled')); - o.value('1', _('Enabled')); - o.depends('pdptype', 'ipv6'); - o.depends('pdptype', 'ipv4v6'); - o.default = ''; + o = s.taboption('advanced', form.Flag, 'ipv6', _('Enable IPv6 negotiation')); + o.default = o.disabled; } o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready')); o.placeholder = '10'; o.datatype = 'min(1)'; - o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); - o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; - o.datatype = 'max(9200)'; - - o = s.taboption('advanced', form.Flag, 'defaultroute', - _('Use default gateway'), - _('If unchecked, no default route is configured')); - o.default = o.enabled; - - o = s.taboption('advanced', form.Value, 'metric', - _('Use gateway metric')); - o.placeholder = '0'; - o.datatype = 'uinteger'; - o.depends('defaultroute', '1'); - - o = s.taboption('advanced', form.Flag, 'peerdns', - _('Use DNS servers advertised by peer'), - _('If unchecked, the advertised DNS server addresses are ignored')); - o.default = o.enabled; - - o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers')); - o.depends('peerdns', '0'); - o.datatype = 'ipaddr'; + o = s.taboption('general', form.ListValue, 'pdptype', _('PDP Type')); + o.value('ipv4v6', 'IPv4/IPv6'); + o.value('ipv4', 'IPv4'); + o.value('ipv6', 'IPv6'); + o.default = 'ipv4v6'; } }); diff --git a/luci-theme-argon/LICENSE b/luci-theme-argon/LICENSE new file mode 100755 index 000000000..261eeb9e9 --- /dev/null +++ b/luci-theme-argon/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/luci-theme-argon/Makefile b/luci-theme-argon/Makefile new file mode 100755 index 000000000..44702ea88 --- /dev/null +++ b/luci-theme-argon/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (C) 2008-2019 Jerrykuku +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Argon Theme +LUCI_DEPENDS:=+curl +jsonfilter +PKG_VERSION:=2.2.9.4 +PKG_RELEASE:=20220425 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-argon/README.md b/luci-theme-argon/README.md new file mode 100755 index 000000000..5eb85b2c3 --- /dev/null +++ b/luci-theme-argon/README.md @@ -0,0 +1,114 @@ +
+ +

+ A new LuCI theme for OpenWrt +

+

+ Argon is a clean HTML5 theme for LuCI. Users may
setup their own favorite logins, including beautiful
pics and customized mp4 videos.

+

+ + + + + + + + + + + + + + +
+
+
+ +
+ +
English | [简体中文](README_ZH.md) + +## Notice +It is strongly recommended to use the Chrome browser. Some new css3 features are used in the theme, and currently only Chrome has the best compatibility. +The mainline version of IE series currently has bugs to be resolved. +FireFox does not enable the backdrop-filter by default, see here for the opening method: https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter + +v2.x.x Adapt to official mainline snapshot. +You can checkout branch 18.06 for OpenWRT 18.06 or lean 19.07. + +## Update Log 2021.10.16 v2.2.9 + +- 【v2.2.9】Fix the problem that the menu could not pop up in mobile mode +- 【v2.2.9】Unify the settings of css spacing +- 【v2.2.9】Refactored the code of the login page +- 【v2.2.8】Fix the problem that the Minify Css option is turned on when compiling, which causes the frosted glass effect to be invalid and the logo font is lost. +- 【v2.2.5】New config app for argon theme. You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended] [Download](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- 【v2.2.5】Automatically set as the default theme when compiling. +- 【v2.2.5】Modify the file structure to adapt to luci-app-argon-config. The old method of turning on dark mode is no longer applicable, please use it with luci-app-argon-config. +- 【v2.2.5】Adapt to Koolshare lede 2.3.6。 +- 【v2.2.5】Fix some Bug。 +- 【v2.2.4】Fix the problem that the login background cannot be displayed on some phones. +- 【v2.2.4】Remove the dependency of luasocket. +- 【v2.2.3】Fix Firmware flash page display error in dark mode. +- 【v2.2.3】Update font icon, add a default icon of undefined menu. +- 【v2.2.2】Add custom login background,put your image (allow png jpg gif) or MP4 video into /www/luci-static/argon/background, random change. +- 【v2.2.2】Add force dark mode, login ssh and type "touch /etc/dark" to open dark mode. +- 【v2.2.2】Add a volume mute button for video background, default is muted. +- 【v2.2.2】fix login page when keyboard show the bottom text overlay the button on mobile. +- 【v2.2.2】fix select color in dark mode,and add a style for scrollbar. +- 【v2.2.2】jquery update to v3.5.1. +- 【v2.2.2】change request bing api method form wget to luasocket (DEPENDS). +- 【v2.2.1】Add blur effect for login form. +- 【v2.2.1】New login theme, Request background imge from bing.com, Auto change everyday. +- 【v2.2.1】New theme icon. +- 【v2.2.1】Add more menu category icon. +- 【v2.2.1】Fix font-size and padding margin. +- 【v2.2.1】Restructure css file. +- 【v2.2.1】Auto adapt to dark mode. + +## How to build + +Enter in your openwrt/package/lean or other + +### Lean lede + +``` +cd lede/package/lean +rm -rf luci-theme-argon +git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +### Openwrt official SnapShots + +``` +cd openwrt/package +git clone https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +## How to Install + +### For Lean openwrt 18.06 LuCI + +``` +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.3/luci-theme-argon-18.06_1.7.3-20220421_all.ipk +opkg install luci-theme-argon*.ipk +``` + +### For openwrt official 19.07 Snapshots LuCI master + +``` +opkg install luci-compat +opkg install luci-lib-ipkg +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.9/luci-theme-argon_2.2.9-20211016-1_all.ipk +opkg install luci-theme-argon*.ipk +``` +![](/Screenshots/screenshot_pc.jpg) +![](/Screenshots/screenshot_phone.jpg) + +## Thanks to + +luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ diff --git a/luci-theme-argon/README_ZH.md b/luci-theme-argon/README_ZH.md new file mode 100755 index 000000000..d66866711 --- /dev/null +++ b/luci-theme-argon/README_ZH.md @@ -0,0 +1,110 @@ +
+ +

+ 全新的 Openwrt 主题 +

+

+ Argon 是一个干净整洁的Openwrt主题,用户可以自定义登录界面,
包含图片或者视频,同时支持深色浅色的自动与手动切换 +

+ + + + + + + + + + + + + + +
+ +![](/Screenshots/screenshot_pc.jpg) +![](/Screenshots/screenshot_phone.jpg) + + +## 注意 +强烈建议使用Chrome 浏览器。主题中使用了一些新的css3特性,目前只有Chrome有最佳的兼容性。 +主线版本 IE 系列目前还有Bug有待解决。 +FireFox 默认不开启backdrop-filter,开启方法见这里:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter +当前master版本基于官方 OpenWrt 19.07.1 稳定版固件进行移植适配。 +v2.x.x 适配主线快照版本。 +v1.x.x 适配18.06 和 Lean Openwrt [如果你是lean代码 请选择这个版本] + + +## 更新日志 2021.10.16 v2.2.9 + +- 【v2.2.9】修复了在手机模式下无法弹出菜单的bug +- 【v2.2.9】统一css间距的设置 +- 【v2.2.9】重构了登录页面的代码 +- 【v2.2.9】为导航菜单添加滑动效果 +- 【v2.2.8】修复编译时打开Minify Css选项,导致磨砂玻璃效果无效,logo字体丢失的问题 +- 【v2.2.5】全新的设置app.你可以设置argon 主题的登录页面的模糊和透明度,并管理背景图片与视频。[建议使用 Chrome][点击下载](https://github.com/jerrykuku/luci-app-argon-config/releases/download/v0.8-beta/luci-app-argon-config_0.8-beta_all.ipk) +- 【v2.2.5】当编译固件时,将自动设置为默认主题。 +- 【v2.2.5】修改文件结构,以适应luci-app-argon-config,旧的开启暗色模式方法将不再适用,请搭配luci-app-argon-config使用。 +- 【v2.2.5】适配Koolshare lede 2.3.6。 +- 【v2.2.5】修复了一些Bug。 +- 【v2.2.4】修复了在某些手机下图片背景第一次加载不能显示的问题。 +- 【v2.2.4】取消 luasocket 的依赖,无需再担心依赖问题。 +- 【v2.2.3】修正了在暗色模式下,固件刷写弹窗内的显示错误。 +- 【v2.2.3】更新了图标库,为未定义的菜单增加了一个默认的图标。 +- 【v2.2.2】背景文件策略调整为,同时接受 jpg png gif mp4, 自行上传文件至 /www/luci-static/argon/background 图片和视频同时随机。 +- 【v2.2.2】增加强制暗色模式,进入ssh 输入 "touch /etc/dark" 进行开启。 +- 【v2.2.2】视频背景加了一个音量开关,喜欢带声音的可以自行点击开启,默认为静音模式。 +- 【v2.2.2】修复了手机模式下,登录页面出现键盘时,文字覆盖按钮的问题。 +- 【v2.2.2】修正了暗黑模式下下拉选项的背景颜色,同时修改了滚动条的样式。 +- 【v2.2.2】jquery 更新到 v3.5.1。 +- 【v2.2.2】获取Bing Api 的方法从wget 更新到luasocket 并添加依赖。 +- 【v2.2.1】登录背景添加毛玻璃效果。 +- 【v2.2.1】全新的登录界面,图片背景跟随Bing.com,每天自动切换。 +- 【v2.2.1】全新的主题icon。 +- 【v2.2.1】增加多个导航icon。 +- 【v2.2.1】细致的微调了 字号大小边距等等。 +- 【v2.2.1】重构了css文件。 +- 【v2.2.1】自动适应的暗黑模式。 + +## 如何编译 + +进入 openwrt/package/lean 或者其他目录 + +### Lean源码 + +``` +cd lede/package/lean +rm -rf luci-theme-argon +git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +### Openwrt 官方源码 + +``` +cd openwrt/package +git clone https://github.com/jerrykuku/luci-theme-argon.git +make menuconfig #choose LUCI->Theme->Luci-theme-argon +make -j1 V=s +``` + +## 如何安装 + +### Lean源码 + +``` +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v1.7.0/luci-theme-argon_1.7.0-20200909_all.ipk +opkg install luci-theme-argon*.ipk +``` + +### For openwrt official 19.07 Snapshots LuCI master + +``` +wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argon/releases/download/v2.2.5/luci-theme-argon_2.2.5-20200914_all.ipk +opkg install luci-theme-argon*.ipk +``` + +## 感谢 + +luci-theme-material: https://github.com/LuttyYang/luci-theme-material/ diff --git a/luci-theme-argon/Screenshots/screenshot_pc.jpg b/luci-theme-argon/Screenshots/screenshot_pc.jpg new file mode 100755 index 000000000..4c355449a Binary files /dev/null and b/luci-theme-argon/Screenshots/screenshot_pc.jpg differ diff --git a/luci-theme-argon/Screenshots/screenshot_phone.jpg b/luci-theme-argon/Screenshots/screenshot_phone.jpg new file mode 100755 index 000000000..8237a0368 Binary files /dev/null and b/luci-theme-argon/Screenshots/screenshot_phone.jpg differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/background/README.md b/luci-theme-argon/htdocs/luci-static/argon/background/README.md new file mode 100755 index 000000000..a86f27b06 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/background/README.md @@ -0,0 +1,2 @@ +Drop background here! +accept jpg png gif mp4 webm diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css new file mode 100755 index 000000000..14644d1f4 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/css/cascade.css @@ -0,0 +1,9 @@ +/*! +Pure v2.0.3 +Copyright 2013 Yahoo! +Licensed under the BSD License. +https://github.com/pure-css/pure/blob/master/LICENSE.md +*//*! +normalize.css v | MIT License | git.io/normalize +Copyright (c) Nicolas Gallagher and Jonathan Neal +*//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none !important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-0.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-0.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(40%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.1)));background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,0.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@font-face{font-family:'Google Sans';src:url('data:application/font-woff2;charset=utf-8;base64,d09GMgABAAAAAFW8ABIAAAAA2DgAAFVQAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGoI0G9x4HKUeBmAAhAIIgTwJnnURDAqB3UiBvQwLhQIAATYCJAOKAAQgBYRnB41NDIQAGz7EJ5hubiR/lNsGgFCW81d/0QXsVni3jdDeRWCO9bMDLTIPKCA+/y/Z//+fkJyM4UAPm1rm+7lslg6TcoycK1yhVF4Fd00lKYMnOBQOl+CKjFHEfIuq31ySSDU87HzeHbmNsgX6LmfjlEVKdIfIiz8bD8xUr+9MmpvlGb1NBxps4YKro8j/gJhCqGbPZIYkd4vYzcfT4a9PuRMK1fqG8BHfIPbCDjeuZ6suWAX5jxolVYEh44GfRhVJC1foEkk8ZPN8ThiPb2Zfje53BraN/ElOXvKI5mxmT3NJ7iJGEsIRQpAHr2BNUKtRatQcqkaVquqL1cT5Maf1erYl2ZYt2Y7NSexwE7dNZtIOdXbTBeauPmsJ8Aj0T4BwIkCe/3//nneufb+MkK7UgargKiNVKhgd+M71OfX3WU46s2sXGR/YVhOl6LTpR46u1rVA7ACCZBUAjp8o3Mb9lkK1dKPgAG3zf8E2llgYIAISdWTLHRx5CMgBCta0Z+Yi8y26//uuIl7Upl9vc3NFk6a+oqmuTstV4J34R2wRW6D7iC1iD4lt5DPMIndJQKjb7i/yLJQwkilFFrz0kxpam69aImwe0hqlvfiZvTRCyIsFK01LLM+5vft/iRJkBjXyID++8zyztHK0ApYyAN3XB5lsaKEsacguL5LNAiXRF8D/oLvjThiR0QEHbnKVpma4F8Ugg/DXnlLKlGXNsOzxP23mSrItA2l9zP8u3ycdwQYI5JSZecHdcFGlalI0R9D0KTqgok5+WAxd6f63u6eRj+q9CXdo69XN5KtJEAtaQtOFkr7K/9/rrE7t7tPTB4HLM8hMgI7y6cM5MBF33OIOaUVPiMtZzSxW79/3pP/ff/rSR+Cxvii5VFBBAocPsn2E7KmWhKtbklV1oMpTB9MhJwEdcCaUp1OIq0l5swghLpazXKawWK6Gf74//FfzZk+oL3saDF7HlHooeFOatUIB++qhUgkCJDmas3+bXh6TsM84QAmoZDsz6TTd5PoA8LOQmdmdDZQ+ALhvhD+oyYFTHHJazVNvizXT+8jAj7G0980AExtN61DFowRRiLv/PHayHp9a0B0WnsjDXSIiXQkllBBCF0oQEff/vSxnF7o5nXlFU5OJPj4V4GwYS234pLXfe5s1USMRFBQQBATU9LoBACfh4oM7vwQvu0sn4cpHYU92pYpIjb4EC92Zetc9xH33aYMe+I74EQ+MN17EJwZhakiSq1R7vY0w1WKrbbbbYaf95ZJbHnkF0TBpPIePCpt/djVsZWR5EC5ahdZT66M1dtMRTj/xncj3hKCBtuhttstvANajW3t2Bffxde26QMwp+b3LwYMGv3Cv+/d8PPnYnuXAMwDAy5E6ulMexR1DNflkFvod7PdoXGrqP3pUWEd+VHhn/szwKwL9hQYgcovi4ZGuvcHmW2mznTY77CzC0MDUDMVIYCHwwUCGZvi3Odz1CVetURG1FGMigUav2tHQlL29GxodFjmMA3S97S4TSQPTPWhmIMwNfHpKpDENIgOuXc+LviRYLaFSGPX7d2IikYGRiZmFDzt/AbxuhkYRSGQ0gMnu4ChAtXo9umo029STHgjT+J5xKDojxNjpNfUVjHgbLwg1ZkAT0CSEBtIidBgVUOXK+t0f0J8o/6BcQNy6w2CE+M3SE44BYUIxQxY8n2EAoodOHTbn3zAEShINLR2PMhUCRif/rCIXUqRPKYF3RF6odwIhpzF93wsQZIRdnzbYNRB9zKWRhKg0iXla1/N4SEAvWQ2NpEHfC1oJF+/YnojlTTEfq5iWEnCjwevU0gri4r9i88tF7WgwUiGkVD/tD1EiFDVB1dBDKWKiN886QDYU+0U24gIcIhHPl0SkJdLR0NMysDLetUGeYcyQOZ+t4wLkZhHKIhwvhkUNFrURcfzFoySgJWIkYaWvCpmyqeRSqkelPrUGVEpIepP14acftUGr3QhjoSqccavFTHNZzF8tFljM35KvsbLD5dZSWGcTle3NqrfHXir7qZxgcYbKnxyucLhBdIXgJpNHFzWJjuyJj+QkR35JnxMgN7dUexMQK/59ATlhgCIy6Gl7j+JtIjVUVoiotBQZvgUaDDljqIsFCJreUYsXU93H7f3BIWH4Xs7cgbtTCpfkRfNO5ahS61VRZ2WTynTcK82OpjwX2DLutqxe8kDLzbJ3tVpbETIjFt5i0c1bZHrtKlNcBAkQYIKCWwEI5zTjyAxXImpDrmCJxJUSg14yQFuawyhohzYjl28VKBVmmQhl8lbLX5TMBDbAksc8zlfiklGQMFEb2BoFGDVXQkOEM40sDBqGEZwLhimh4cDXipjs+t4RkoXziEweUaLttfbzL2iaFMiJPaoQYkeXjT+Zndk0QNdCj6yNkAQwiqp3sSrWQev9CDxmwWOCqwW6ZWG/l6Np7NnoO0bJO7eQPmf5D7VBAKvYlsBPBpVNoq2iXTFVn/SayBX5o8ejvmMNq9TEer1EBsyI61ulMz0eE2hGxm6aNkcLW+mLSt9Lxo5SUAagLYpaiuJV3dxiEHEAXh52/qC1m3I9PuNjakm/bgx14REhjDWacX3cjR4/AJipRwvxYCdJltYUP0iBgzzlB8vrVgMlDMNIMvA90+qCYEjCIDkhvDgUxT8gOcfUBmL6oWdA3wTMyiM3diwB5bjLAYiHADPuj89t2E0QHLshBatAAw68p7GCx/zrj1mAGMsFZTDuAmdOaEl+WGXNtOTQ8prKKNiJGqQ83ETJ0c4YyAgA4INZGWIZ6ofaTE0nL7CrNwkkrpJDueV+GJZSiizdVEw+GLupU7XzfR/51FIWeUgcTg8MMALKwXJuG1ru/NwUSocY65eyrkuSDHsWYIZp9sJxe7OdJVnYTHAugQPkRgShBKOFYISurN+E4YRTiCCIXJWiROPEUImlVoNKTaJaJLVpxNGKp5NAL5FBEqM6TKrQxq3EeJPQJq+cKabhTUeZMdwJL1WqtNtoKZid+DoNMT7Tqg0gjnmJhsDrbwEQIUEEf0l8ASSLAlAHgJddCigg9pjj4thYLg8DazG/8fEICo0hY9UA4AMAIBZAgCDK3uUptpRLOL2876ukphQyqqO/7JNOOcHfvHpxVKKdnIBzRK08X9MqiW5hJMfU4weBqjkwEGjFHgBE/egsgCABrcrtgdwClQ1/xPUAKOlzJkFMJ4DlHXK+T6IR8z5gFSEarS0EzX8gNM5PNJjoJgmai8eVRpjLar6loqVw/jhkSHs0UGwxaCO7UIPDPTU9LPS/RzUx42XW1PveqTa3s7HcbO5zZ3pCJozeQjP5QOu+OQDcCiOjE6m+F5zlxszn6onYZRjr6bARPii1VwI1E9ZhOLfeANB7bM+5IV9SYwulUhY+ETS+U4i0KzvtSKNtKImXiJzbXXy44wTXL6OFG1pjRl9nsEuR2u3XrBbOz8DUSiVPV95Apkmbwd5S0/ZXG2ebGG4OChhPecLXNYkrFPOBmSJvsywSji+xyDEZGMaAollBZ5HR8ZglBOjHZpDgOYGWfygwMZUy1O0mQEZxNLrw6VjXuS1A02MuG8a43W4jjKvvwzAk0m6hoZJrdkbuCzAqv7smhjUxEtA3w8Y571NNvZ9zn16mKq/vSQqUuAEjDPXox7GRlKo3oakoLz01Ga3nhAYX5uayOa8TuP6tBIJG2a+P7K6JL4gkGQOUichCyUbLwcjFyiPKxysgKKRUtKoUq0tUj6Q+jQa0GtIpodeIQSmjxkyaMGvKohkfzVn1Y7QMZy3aupVYbxPa5pW3xTYK29nsGPHWJ+lzyQGHGR0BH0ehY3wcp3YS7Qn0FOMZ9JzoBd5LgleUXlN5w+At0Tu89wQfKH2k8mk1+OwLxlcG3zC+X25A5FDwo2Ij8aXlS8fMwp9VCCeD2gLEc0kQKImbl0oym1Q+0qGMJ1qZ3EWi0qY+aB4U0bKWLjp9dKaY2Cxx8SkStlJLYtONUz96QwSrJFvCbdlob+3C62yeEq/Qp5KtthE5zZouOjpLQtqE07o7f4LRX4L8ff3Gbxv9C0H+43CBr4ucLgl2jd2tvzN74hPis690vvmOReRVuuagoC9bLbOXzX7HxWacpAc0P66DDGiNBuyYfg+YBJjZ/4OXLnH5Xqd1d2JA1rbvgxsFW6f4hDhcP0+4NSBgNA9UwBUqzHpLS5TudCMpe/3EymcWNERMAjqAFPacDiG7qEs0ggNa4J2NU4qNMezqqwUAsh7E9YCa9y75E/D1YTYZwb4xAHo/jt3UpjuXC1zHC9nAaRUvcBNDEYx975NNMzEa6WAMY0NwXsEBGjopxKrnAklrztkM76JkdGzy8+neLexww/SDoCUHsKUJIqp33q4tscdwNA4wo69nJhz7K8KJng4MNZaeQE0FqZNwNChaHN0q8uVAOCl4aSRDqYxaQm3odMOoQBmANwSrcgyP5IZqjClTJaRMtQX/E60LOBcxLg3rPhQRXgYwceG4SUJPSo+FkpJi0sRGpdi0OuCUPrJpSQjHbFeyDjEq+SZkSciRT9r80qVPlXr82/hYHhrFJSYlJaWJTh7BZ8ueLWW+CQn5jdqnHt+ry5G6EbqMY2Ah4xhMSJhv8KQWChLRA7MESirqx5AoEeakx104WaoyLbXRTYUBhjyRPNNf/vaPf/3nfxdcfMzsEpfcdoCOhiqlCjTodEbc0pY9KwkrbMzU+FhOITIvCAo/oCiggAMhckHhiNpo8RgJWIkESTiN8ZqNgrNwKG6GozcFNUIr5mL+4gJ00R1xFA0gVAykfrajeIiJkcH51hAsJMyP4WSio6Oih74JiYmNi0+RMEo5n1QhHiK06OjoODy28q4D2R9VQeIu3BoRgQZg4kZBUmsJnWkEczVdPHUGdayAszgDntZSljwRBxBmjRJFmeUq9F+PuaGuDeLJ+QPOj0xr0MLWjnEz5fmfxuLwuy8NAW69ZQMZ5IA7opCv+egju/aGuGOqKrqB5/9pvC5IP6VTh1bQ+pTyPt2g4ykVbbpC+TrWE3qfsUkMPOethkMpgyMaWw1rM0NcUbNKPFb6N9VSoBLF30x0LGIkSNXXUGNMNvuPI5zzk19hUUQTFgAS8XCE9bvanCZ5UUM7mhrfh6aH9nnRt0nfg/0c/Xr3O9/f0L+s/8L+1waoeM+AtgPGD1g54HD6rgF7F+0//5etA0O1jv7tWwfxWmf/la2D60W64A+YxiFOp4VqMdtGoC8dyl86nL71iGGA2rTgJkCNEgaBKbkPGqGKfNsDvu8jsvnfxJU/4BynJWnm/5fKorTVHueqdjoQ3TTPPjJ/fnopx+uEINHGCnBqYgkoSsFiJMlUrIm2yvU3wkTICQAAIR0C6dnBV5FFUe7YlhOTHpqdwC1KgnSFSrXWVV/DuXIYBShpyDhUENwVXCLESZWvREud9YYcoOeWXjpys7NueE5hakmWq4EyHeGRDbQSC3s+Yqafc2ShavDIVk8zyAr6WEpqzcEBnyyHUgxkQT9lnZg7LLB1Az5l2Kv3e8iEMj62lgmqHpDHNGtF/SgyoLFjaBjSYyY+oFhEjivOass10aWYoz8mTGQjw6MfstTEBUZAmd9DIohMdeKRuvsYWVN2u+CMJrxc2mNkj1PyTy6T7YgotWNwfxYONZGPTajaCwlhSU8saBUKClaA71kxmm0KdrAf2LFNMFKwA/+IA2c9ogd7lh/KeE38DdvrHuwZs7OYk6KxPFx6Ghwe/NkXdxFa+MNxqKrw4EciqkzpNicDmPNuJy67/JR+hgWsYmpuhKq9y1nH5bddsR7w7p+knReQnzYoQhgZEBAIRWKJVCZXKCFYp9FiFE6bDHqOJ1EmoZA/6rz3lEUSLU7EqPzQuG21I9kBo+V6+XfHVTdh3uCZ9Dc3ckZkeY7nFgovQm68t3a5XEWyPX6V9Rzk/yKSrpFSDWW7S73/yPFSJsdTh6cS0R6kvBNJZMGixEmWrVipMm111l1fg43wBiVHI6+XziKvOgu97CzwojPf8848z/IzfEQUce4Wet99UeBdvrd5PjXyNMcThu+GzCDhPvHwnn2ER/fsY0Q3oWHypdNFfcVPP+cTLJXvG/pNoZbJbFa5YNMaagQTs5KOR7GVdjub0pgD7aJ3sSyWb166NIFTDZnJtfxe/dBu8VwPM9R/5HZ+jIhXlt2jUqq+bA1BjVBptzYXRrGEiN4uae6ED9LulJzxN2+ndDkc8qhAAZWoQjWKKKEmUJ2I2Pw5P/1SHQEGCVJII4MsEMRQuQB63BJEF49TMYBcXqUA8pZfbTxMg8QAMpihKIbQhAYAzuvdlLV7URYcpZ41ljrZuweoH+KYAXgPAMBe/QFApjMraQr0OYAfKADwsv74BKhBRjNQG6o6mpD6dbqu1Y0ZRB4oD5bHyFbZITtlt5wgp1N6Uzb6O/2n+c9w6pzG6i4EarKliU69hDuMli2y/R7E/8F8+729tf3W03r8fLV/+f/5F6fvHL1zpAPtbU8729bS5lRY+O1iOVbO+/utc4Bee7Af/FwQsO4eAdxP9WFY7i/2ifwVP5G/7Ot/CRpTU2l0BpPF5nB5AF8gFIklUplcoVSpNVqd3mBMM4GQ2QJbbXaH04W40z1eX4YfDQRDmVnhSHaSJRpJW2DMhHETZsxdvGL5ytWr1qzbsH7jpi2bt27bsWvn7r17Dh44dBjq2u7Y1XqurEH39nKoWgz1AMf3A8Apg2Htoco2FIBTh9jD6HFzTnBtXVNzfUM2J7k8nRiAC//+h1FTR04aP2XqtMmzZsPcpYsWHD+sbFgP4PRFAJBX8L5DUxsD+XU7UN0KtBj3xJrfb8i6Q7ChAvw+WqzBIEtE1iNVckRyjs7kMUyMvBiuIaqpAOc2kckHipTIRMhMBPMVjWbJ2cr62J4hV8GOSTzSZMpH/z4/UmTJU6B4i9x5vXNmjx0zetTIEZXDhyVDBg8aONh1HrvRSgrOKMEIgm1d5mkc+q5tBLIj4azMUDCA+jO8nnQ34nI67DYrzCZv70+3t54lMQpTvp1vVysiYrSaOyYvgUyhdN4QtGmC7xrV6ZnsTiplJSt4cJstr/azMKVr2kopLiQg3a/U6XOnmxvKwjjoSe1AIazix8bhfRKUiotaLaV9Wmd0SH0ZQIOAJZkA7SGfjsBsbtzLiLtTi/SnAbRpy5jUrNjM62ZEDbuVgbu9t8RLJdQApVRcEBO/b/oRFwgzcgPjFrZJqnIcyOLtoH4Bz/nz/KIczJQI0vLkQxMqwHGWxWDP8PITMlRYkbVF+Zc9Zo+3S7USCW5ikvzQEX3yQ1dulheEMD90m58JKXU3Nj7IswwY6n2ECcY+s110kk7PpzNWLn0ZzRQ/4sn4tgLhuUUHEvBT9EIn1LEsKfk59TqRVb+OZpDaI7Lpu5B3D4QgMvGSiDApp6ttr/nN2lZtt1RFtyMey59N0T2CCBB+WSLYHmS0lykw+1c3LJdY7N4DyfCUZvypnaAUiWk/xKCreqg/UuTmlxj28PanfmrdvLyQaiWL1KpZpplPguwO4Jizkn8Ck8TsKNE3cFc4qaw69u4aKtYtJsNzyTZeeRjWM7RpjhPrbzgdJAyfkpyeUhGYbU257s664FZl6zk5HZFxJ51eJyith1oVsDzkWwXXIjEbkdvkUlxGJBkXYTK/QZTcVH7DlbjySVCXAa/x+HXOOKPy0zDFEyL4D80TubAeZgrPHjy5ub1eHG6UsuWkWqEsQqu+q1Y63eg/0B+OTQIYopBX08TqG37qD4fcKckqlD9ycndnoc2MncLXSHcayCxHJXknW8OeZtmZXXBLgC5eE3kO7x3kJsTTPDh989VbCxM09bKftDIMTPmbuatWEgVRtWaLwolV0nDXThefBxdGTBxPjlAXKz7XfRLJRUVZlOB2V/ybYi40cjY7xXfT26NY2jOKZlZCEtBuJY6xwUA0aU9ZxHvChbOChrrR20VCMZe0zlv19+0O3D7mScIR0gdSWJRYtrp+OY9skoJJ+ZQ/+IWkAQ0p5lQ25U2RJdVOfyLtQjITqSy4ezEWlI0ZPTZ6WYhVjY4b0OnYbRTIDsWDrJ2cVeky0OEoGYhI0cJLFhpZ9eFY2BTMDbk+dF2zYL7kJFS3KUrOWUV4qixPcVKw21O1AV0GcDvkSShwIJH1wiKCcJCu9aW3Reua/RzG9WUaYDu9JBo4g5iyMmNld3WHfESmjRUEk4931jQknjDiNIQ9DJeCOQn99zCSCsHddOQ0K0qpTmJ2vIyQAVYLOPYMolEgsLwtfzvKYUXHkY3XTwwwsqYbtmt3OAE6DdrrlYpAmBuJS9ePD3DgSezMb4oLKQFWl205gr+SULLlOIG6I5s/Wq3LbHkC3C+5kbXUS4RWGoU7VPKNxhCAdlY12CvhOksNJYIPcyRYwAOLbhCPMXZjU6VP2O5Hitv5o1j8kHic9JT3/O6RRflnsVkSjgFj7FrpThCao1XhgIPF++NrNmCl8eaLVIv8sjIVRkrRi9ViODWC6Qbnxpfln8A1fhAZVqaZ/V4jwzoHMzAfnbWw1623SzRt2afqhhbmuCSnWG3IHUIHe0KXDlPjin7P0WjbMujLtSips6hDJEVwTQCSZvKREQS0DohbkyL+mSDRyfEtBNMjoSrwmiHypHu7+RTriJsty1M/NIBX8nwfGSED5tNq7ZqlvG6zJletvLAkuidO5T6x1kisPX2MKS5aujoeUmQivxAkSPxEcPzNFjdDrjsCraI3KwDcEv0k3OZDdEU40baoRtolrLLteTbB3TTkZi0VR/a1043dYc57hNCeQHlBIfJl4lgD2rtV+oTfJgZmEHYksiG7syvTOvWXXOtfiQKpJARmY8vyGTRzSMEAjPAZ30RduCVXTIyktVb9Xbp3qw7CWmTvaGhtbPEN1BDgW4WaOCPCRd5mbKLgROQzDcyqXLMIHaVg9pSXpnuTKnbCm8OtyvkE0J6QR7Yfk8klgBe+5KIwEI5eGjjR1UrIdVVl3c0KtZeGJ9je+xYl4bkwEaaI0tAF3ZIVCP+QxxD2m//szXxuxy2ObwQs21OGtnlWaJEj7TQHs9p85Tg4MN8gl9z/QIFgSjj1LuVvm+gJ1XvXmvZrrW8mVr77VvjZn+ipB08TToy73DWeKvWWGzg35BM7lv8nVi1m2SY6vVD4lfRzwykl5+J87WPzpsJjCNyaneITCxwvyv/ttgrjhG28TxkEQ+nhPgt5R8AJfGRtuFrxKRvTkA5CX/THSMhhkPKi3VLe1Ad32y9z28pta6ynTvjP0zqL2hYBE4zx54oNOfTyF2pnB4ahj41SU+pesiE3g5Vsm0ZG5hPLA/gMfZEfzybh4HY1/4T4awwFThTlL12semo5gk3+Xyzc3zSmIlSwIRxqxRsnfTy+ENy3/hTu0BOGwyCrIYHyfDsVNOBPEPEipMI394MEiOAIrUsAANwCAJCLAe4IjI8B+A4EoG8F1MXA711BAOATrp1+7BQGgdVkISRIIZEVJRo1gadbT04U6UjCsbMm6jh2kdYdeGdsB1E2JAALhT5o4AFKcujkVq7PAhTHcm9LPYYOYEHEgdNRcwzvmalLETJhpyKktZdj2lcjbyFDJU0tuFpaBwatRPMOn8/uYRAwxhFY4OC9QHEfkfOABYTkF3cJu6H8ihyKZAlAWPKLwXUpLVPDeEaouC5LbRoMunQdBnGYYwwIAVi3I61GmobJVmOCJeN0JI2Gf3O7i9koFDbxgMPC0C3801Iz4LmQ0mSTnaQGIoHKucRVn072jURpOYmxpJuH0L6T2IrgJDZjYa6jQiRHxhigFDqH29B5D3PY1WHYCtK5rr/1c8sPPl/+XnDG42Z0O6mzevsw86KfniasB/RTcsAEgjQRZwr8QWrMSO4QB8psh0H3N7ylbf8wYUyGAZ0RBNApQLOQrHwwDw0CVAcdHGwhvoVjGyoZtqs9tzkgi8WkOuVMYV3nUzHTdZcxAsfpww8XTDVnhb95BUtrgtnKzJaVcP/8EFnZYm0bAylrku+nDkbo0dlML89Vl1bnfyVWSxsjj1et63r9dqPkBB57g7xmI4JK2ItCWTb4okXkWw5USq2xT9g1U1ROMjMm12HNcl11lf3MboygixK8892LfBsCsgHoMCChzl9mhnOwe+kifvBxZ7HN6NCpXORmrLft7ptxqciLyt3UWspDtxt29/SWRxonuB8d6zID1Smnl+5ptiSGyFZEwIzZVBaLor1sOlRjL9rmY2HyENCY1jDQMtI8VTdckng579JIjiAvuUgXO43l0niwSvExPyTDpVaxnK/K3Ubv40fouXQ3zyjVNYvLufBdzQ/cr77Pteo7cVlVnQCzixTbBkmwBUYjwReqbWwr2wJJ+iO1rrBUIsrZ86Szs24C6lv7lJ4cRhr6Xh2NEu8IYuRJvbZUoNK1Vol/c0rH9vOWQrtQ+jiGQxJ5wPCzZNIXthqjgl2AEPxX0vHCDetLMCeVt8nGjUkYQSU2F72Gs+E9kld76F+4YH0BimJ33hW3n4/5D40akU31+DXyolYujTDuxKRSiKRGnkOeLEdhgu07AEMcMuwhRQnUsEhTuBkTUVyW2kUSh7W7cH2eKnbpCCY8qFuN0gsNi3m+smXhpbNe8NgqqURh27zJnYOAIQQtrunc0hPVLaWeI6fiSvfgxydll5jS9XQDmR/Qq+Z8sBVGnUkQpGAl/x0dQIM+GeucHIjj6TWHQxQknQJBDGGgsMuD2jDDD77fCDDeb44SKWEBtUFG8WhQECVyBA5GxQxDyqJDZCY1eu2NwkEwkOFVpkXPE/yLsJmexsYiYBwBpxt8FdiEYau5PuWPPE7ctG1OZgxJBqOLWduLp9HOvlOyh5em9MO3Ifb215HR2bEhcP68+fSQAnrwpdGJ6hgD5zOcL3QMmoFKk2iMZBIGamapvlQ/nonsrEIx+4/bvnNb3g0WR95U6TSVCfCgX16JOgG6qjFIoQXqyv4aEGWdXjebLFoYdS9WJDYWBeBriJvYpkb+kLx4D0/0BPs4PYJ19NqE2bB0acXBcFBQtyd/irDL+2pGFjBtqfEAelJ7XDLPZBTsPYuOFPNUCDeqK6b4Ducy1L5SSUIRD6LkqJTXTDa+sNruXIoZMwuQWYVMQk9PgJEi4Fk0GdKLgWfxyYzfKB4nkNV6miudxjJKgmpZhqRDbj7BXws0nx58XjMzI8P2utodzdLaTPWM9PTxRd7oRalFVcjs+F6dgoCBQXVFQIAcWK/0ZDb2E8+cJVqZDZeNPlbrMrOrLNjf8zqnho+3aEvm1ph9XYYCAoRUe3iXt6a5vdSmEmYu8m3a0MjmmjG0vhicX7zxoo2RtR63UTTQ4KtL1ZNire6LQyQW0CJFASwIUN6GEGA/n/4qaWp4Ep+lPqqPuflWVVfBeuEMfzaPpc+4EIXzdE0rgnXdmFfMM7sEXkSrIK8Y5tRrVJuwyRjLHjF8/9xDNl9ljZqR18awJZ1Vw2VJmmwsZdWqIiBK1NMkXz9PPyo0KRu5OrizAJQIqKwLzLyMCAvNBu43lDCztJGs+mKwqA6jhfIiqInr0jkKyI3d5RzDc+JZ+uOxDca7cI/T0HPVvkvGuoLbG+k+U9H4C9GjbwabCKw4UWUo1AO4qYVPc6OMkaRW5xXZzpTV2s9+qXbuOGmcv/5QrYgPuzo4dhHsUiUs1NUp7tRiy/e1NBwf+Gzz3rTUjZDZWGzJnvv/5ektzSX/fwrZcxzNnXN+vWql5Dyh5nAxW/K/bc3VMm3tok6OFNCa+S+cOeGajtQ3Yam526vtaQk2CWK41vGnQ9k5KS33FQ/YsGEcX23+WHFZuqZutIwa1HKXYBWpvznx0/5uYaixF6yGn/OrwQo31djj+zIDfd4R3a6XzOQTVc1S5Qg1gUvGsYaP9Xggbr/mas9KYOW4gjtdIVwx+okzQs/xPamNofTk+nLLP0+n4GeeYHLUcNFCewILomw9zs0L7K/4vKyhSABuxPX4uEWVxVM0yl2u0O7jDLdme6MZrT0xV8TFVj9KtZExFhiP6R2gPWOmH+mlZvBzl7I6RhhtuxIg4YWz6moNF6uVkusElylrkn21rERGhx+y1xR1BWJx4zLT5gR4EOxB3DOWuYcWqGKKBK0ON8v6IUeJfQANVAK9OI/iyEtrpTjj3XzhD1t3taoE1pd6yeUNHIWOHIvb7t3q4lyJpYSl7WaPJO7CwugOa0+rj+dy1MUTGQFuz+QtFB89top/VGh+0zzkw3mDKyqmUxjVwHf/ix+BfnFdfU6nEE3tz0qwyw/42PxbA1c/enTDmnk1NOD7Nf9HEES3CA7t5AJ8pxfqf/v3vL18mzbdM8N7OyOb70d0zCRm4NT3AbGfMGIU9B3ODD4nB+4+epo+lP7xzRJeF3Tt1EOK/eFr54/NjnDCNIAvlZCMeMOIMiJCIRLdWwaID3AA4DRufCkEPI9m6Qr/ubF6rrrwUldXbhjcV1ndV54wljeKhpu//rVnA1cdyjbvC5mZg5Q5vtHoirTx0fRqmJRSBUnXGGv7L2zoOy6AA1v5iB/IRHmzDj2uZ9FRak0a4HVlJOc1JTduDAtygBoAN85d66npuobCaZNkJdnX1F4S3tzVN4dz96Ei7ZrUPQLf2MH3X6jo36f5uuy1622HPUTdm6QrfNX+Z33pbbbeeQxH5Hx2NwlMJB7YUZ6IfxUebXjUvJzkba+aFyNwBcf6q2taca6nC8zMn5enrr8s9TwzwMdM0evy+7oL67SzswRZUT16AOTf+e7/3p8x9bljJhK0g2gmzCQOivkdeYhMfyCbGbLoz46Blva4qZ0DLB3JZ5ykM9PTXR0DSqZ2ki46Uy5Oh9Mz9smc3n7cWj7nluW7BwThANyvKSfO7SRdtVn/+rcvkxbOhgGeO0M6FoWDlgGo+4GDPOVT6fsgPS/oGMrv7f7vXCHz9oESgBHDfJCwusgtANx8PuB2CwQCRMDfOvhu5DcZvv3IfOjwvNRNywXCZTzeVqFgG69sd8PqrQ0+GaS9+0OhbgloAfOtjSZzHWwEa+b0mLYwBeA7EJ5A5zX3tjEJbi3jPwZjxheNqQZkPTnz4uKQdbEevkSY7gMkeJ54setjSz9NmOD72zLuQ57gvbo6Fh75Pja2aYHlI+fXgnWtdBYnVDPiwUqmt9nabKpiruyrl+UqXuQo7qffYdDn9/v2wUclSHxyX8zlhGn4WUY/um4qGKgv1cN6bNM+k5MdcL3LfZcKB3zBDc4BVxUW2q72HJ9PQhsDSwu9Kk+Gjd/pdqMrw6ZWS4B9wP+a8FdkzSgv7dQUxRZ0ENDg9JlhTD1AuvkLR2EyzHWlzJCagyKdMU8uz5SVVVZfuAh5d+Dv4jJpNtffLvLfLqOMaaKU02llIIWtTZcr7QaZyKqWy9aeQyj44oBXlytUoHK53N6AoacEtDpdbqncyGqYbUsz3on8GvKE5vifI5hnLuJTXDbb6vvgIP2XblNBfi9oyvCD9C86lMELDfUmEy6JXIi2UK0tSUvTlZbrIMY1XLlJU6pRAoXLdg2CBJu/RLPksgK1odCgM5aWGw0sD8RkgRw2C4SYbLa5CbA5YH5bEF3xBijXeyDoLIy+hiuTayNqjSHAxvSTuHkKWTBHrNOCBUfBiwtLMGxPQKPWRSqapcmWQXqJxKyRyVnnAr1c5/LBaiV66fUZsFL9KHrtzhQKiGGu0UzgXCsKqtmUucTwmD/EyNtcwiShzsO1Kr9R8zlJaBKl+GwYvt/NGI/hGW6s7ugx+FiLzRA14+jPQGd5vX0XYf/XSxJoGlyfShfdU0o2vEUo9sKQRxcWSVC5UuFaN/gmnRuM0nYfoQkhyu3dVVK8o6zMv892l1RU7Cgp2lEWdjVYGQu/NdiYAnlIKoloNdLsgFTKAilTMaK0PqTnKVxKSBtCZ83yh0Kz/YE5Royah6zt2yxkP+9Pm02vRy+ZzG7X6ZrJlCldebiubOsZhemXfTQutycxH/O+ze2pKurqqSgTK4NKmQw5g/FCQa1GExkqVeNgNj3vRjLxjIm248UxC33Mm5SUv2YzD/8uU+LWtcrbVFYGxquXesZqsedH5vGN7lE219hgEAxrcI/OKr8/YHZ6EJ/edadqdVZwZSEjRoVVd257RsydNWYM3BFjuAcrLvfaP3I8nI9273JOgfzeTIESNbh1rQo2l5YSC6sXpU9WnjrCKQP0zjE299hgEAxvE6ctD6AvIbuN/YtCzkSQ0/FoaPkaeXoXKq+RoxdQuAZGyZHevx6D1kuNgQR3OoXWWKaFvdAf6GenojxPYYw+Wk8rxtRSicGKbbMwJR/9NaOvoezMFe1q7/S3TPtzB0abtF/wn+89gX7rhhsTMyfP+PHZJUuL1Rhq0lb0QqjJD1ZdGCvDrWmTu7m42LMwt6QkL3B5RjocY1GUGM1FkKgZPr3rq65IrsvT60mnjS2lo98a2GeJVCrxLHt5X2IuwcPNwTJvUwnGX5uAac5psd3EXVr5KDDKBKAjx/OrQMxdfue4EZC05Zt2sxIAdav/jvmVjml7ilZDRz/UMdKoFcwe/m+DZdzFFQJIYLCHgmvqNRhQUCOxpfmIl52E3KBbqgwUSA2GMF9h2u6mroG1GiWiF3JNMjD+cxalaChqgbOH8dSaZ22/el95/9eOxv6F6webhmecRs8HwxWBQKQieB49nWEY0Wzx4gf/nrOjb0ImJjHzQN+cPl3BIVG/54wavIN+smJwaOHgJ5ipnpwTXaEFff7EcMuYEL53j+eZxbvjMTtMRc8zv9YWnuJiTnALY3s4vo4s2MfD7Pit4ONIJzqEUTqKWue9kTmKOt77Bt+HSjwHd2A74F+jHtw1zsMDLAVzrmTPdUGHxCWf348xI29nDpp9A36Aze/Klg53YjdKQZ7QJfa2ZmUL3LEusjrdrOfa6GndD4E0rbSxIgfy2jH+oFQpcdh5PDswwhLLgmG1gPtdvLkfLiIrwji9F9DrvWFMcUSmsVRZjO2I29hWZbGkuhAhP6jR8IOIEOC7hIKNeRZeZz7pPq4RNrUhiKm90eLIqHGNcJEFDpGcj4gEQbUaDGvkKxAx30leXof48NdwVRZjmxsxtje/qhZNWNaE6Q1fRy94nZjGsEwjd2H1AohQEFKridG/JQDpDq7ektaG2HUdNXa7sxLUNLoGkWZyxOkuFrdQEram/ldr88w2k7t3Ml2G65K0dUcOkqMU8ax2Jp/3b0b8X/HUn1zBGGTMTlR45nVDhgah/OtWKNIDYb8aM6aJSANWQMZWN2Jsq4BATZZoAsbufdc+YWQ1n+vgA6hWB6AOQCBw5l1aIOD87WgydKHXe1swcJZUkZ1fkWVFNRaLScUGhUwnJxlNCoalSQRJEiGVkEQjcLLRn6jk+J3Xb4UH9jY0DiDvZsIojDhcoMzQhZ76/L0Cc/7XizxM+9W/BYPL0ASD1r+TDT+9TkwgKBWrfPLkLSG5NhQqj1j9GusKNfN+qp1HQdW2FSrmg1QHLwWlQk6xhGWySF4FoGuCjFpOGp/m4JDRpEe4ZivY7nR6FpgrzQsELo9AFNRqmXFaKPRG4H3yeM0Pr0sdLI20PJd6Wx6ijDjJkGfP+KTWtYj8ueTy3kKb40T9P1HDD68P8xZVCGmTIt1sxl06zCGhSctxla5hTirfIeaLICadElj2+BJiVQMyMEiTQqXqDDuVCgW5r1KSdx2yxzhinA6FUA6HGSr7835QVCPEy0QyZ6IzO5HOeO53Bp08MuPVy0TSElzesHwTKrObIBUP5NPtHAr60+vAWMJSWVLfn+Fli3qtmJd5+UdgSN8foZbZPUdOD46c1bNlVmDNj8CY+aPno/gTvbZ/yxt9ZPiRwl3/7O1VMOb06NMFsffI1x5GVrT1WjQworkZGkLPBkroyFQ7UCJHluEPtAdDju2cKVSYOoWz3REMOeNhPPM7sF2YQMTYTKLtwHcmHo6P6kMlFsxEsC/xzN75NlHfABfp613f2fqWRRW8Hz0r/VJ0wgk8xCJWpyTV7TQeK7xQXi5Z2aNH02m+wOvLqcPGpfSPe+8f+Gh9xAH2Q2H0Th4sr4QgeVUefPvO0v8KMu3FLnKK04ortVZ/d5A7JY78SGnEkW+J/auKU9Ugt/eR1BVh/VpZ4dg3SwggTybJish1nnw/CyHvWyNSplkEqS0TFctnRCZbmwZyZc8jyUFmxVYaNP1glgnMPBS9oc1ua9sQvdEOgfaN0RvWmOJptikbngRe0UEWiw6+YjD/FjBZv2/YDG9G/b8/ww9S86e8TsTwEx/n76O2w+vR9fD6jX59+nekA/EjSxHsV35Ia0SLAKV7xND4LDd5SD6iUiE6gdRlCBJCRDRg4gC2CUFZmCtMj0iMchSQgzMR8uo0rZBWdi+BcdyEL6HURAI8uv1l1NQVaXFbanPWJslcuhAx3/FrSlI48gWf8DM+4VFC/OOEGT0e4VOzzwnq/+PK9PoygwEsMFcaZ0h+sVhNiR3yi6wpIimJ9TTDT4Ms7V/chcyS5PrU91umxKUcoVCOpDBG9DcmjFiJc9IBkGepQDwsMIYbJTGpRSzN4KxUZkhhUYS4Up+mbyGIkeQCYr7laTmjR3VOiv4Em9bIhFYqh8Hb8eZBtLxNnexc0sGUhNOWaK2/l6S2n4ACWR2DjWpVtBiVKNbtxoP4pOEHT3FpNN5JH1jJa8ZdRTsUIpFCycktslJLcuwH7j543zJ42Z+17rXugncRL3Vlw8MdRBoL0BdLdLlGI1i/kp6yxp2RmYFEpfVWRRGSvq2wo18wtuDdhVFxLTGxrXH4K7tTI3JPTB93Boe9gJd7CleoVZWaTMx4rtGYe2n2P5kwn097/qQzHk5iRD2W9mFdY7h6diY5zX5w8Eu6OmCU0MHkQmpIG7rrpqiLhnDxHx7C9GzrGbmsMbt75SorkXeYx+viJdoFno5FMTGLohsSM9E5IKdnssfJpkeS7+664vf9lM5iG88UPo0rxpzcL+VPlk83+3tEez3KuF42JHd2/7ntM1bmB56WhyDdH+gVYOpO0VR1LhQwW2FHL6DjU2VywS6zh3rE2O8X4AtfafHDy5jqly8eOj6tWMJaczH43zUNOZHlWJxVkrtpQ0FJ2Ml0zHWA0qdoOFzbbNjFisxz/lsla3gtfr8ZREY4nOP8RXQv7UhYWn9b8m6ziUYk+py1S0NB2Djg7w8uTdtvVPFuos6DaBjTzDQWy03UmdPkYlgv1YI2A6YEY4jOz1WCuhyxLKAsDwGYdCjTZFAPLVGaWJTXJwQ5v9pOs45zK9pKG1qsN1mGymb8zJXpnZWmECHAKziNLXVwD6vHXm3+v3XEeIWvYNqSSZ/z0oW/Q6Hb5sBx7OdqxztDNeIR2/PSczfXLqu1hDw2+XEoscbAD3hIH2POwadInf+nH3qKq7WYGixWsK4qzSiEqQyw/w/uCOWyEHP6FqK1IBkWFwLLIBJkhLaXeg0dNRY74LHzuOkSCddtAwC+A5jp6QhAFO/wb5M3gEKvnvmd0C5419HbG8ODYn5uFlUanf7RBtvCqsNnRRWmn2dJU2/KPZL1k2iddM4gYgYBw09Oegb5AcVZAy7YfzwvnrYLvdUbwjSFQ4KOsKyxHXpsuPMK4IUT4B/oT3SQTNoOrCVzpk2Q1rbC6/jI9XA/OrwrWj8ntZnbDaFuYkNQa/Rhimy14IB35aDZL5xV3C81uNr077+xyebf7Ab/DBs9PHWwqN6pS/fx5WDdvvZlqsM84NC/fwSvJ/NwXNymuNjDsbFHYus/ZQimnRxIdcHMb4lJ5MH/9F/zlKCGc7LHQ6KO8cvZ+IZhYSw244eZGHXxhiGrVeSIOZZANBMGRZhlDuhibBOrV8bO/A8EBULQJBCYwPcCrFs8c4f0yybXi4RNaLNiUwfp/J2PTewW29V90NW9Q3ISYXbEOUoTqYyz58E+Ek4i1YPz4uzZlaM0DhaCf86CjgEpSIePiLyAv9MTE+nf4RdEpNOHgCsQ12oLezcbPATMeaozru5l++uecduIvdLWpqyhF3Egl3y0acHBg4cOLvwAY0sXiPNh4bYGrD56F7wL2wN8PsYdL685XF3tWVi1enVjjdvtT2/0jk9HJnq9YFiz1zaUL+0x8BxU05rNtvKnpFbW7SCOYh+rTh6rrSVGq9b6pijrm5rT9DlQDWSqg2DW418MKKs5PNj+ZOXEYmFTwf49JU08ww+vF5PcUCzDPwv2JqV4UAsR5dzCNVugFjsCNteC5nB1WeXRvFns9KBHbMvUPqi0ekK1C3NSySYax4KLOvhfc/ayQs7vkFIMOtKdTEyOjcoH6y1wi80OtzTAJr6NasPwyu9NnjqxSuBPY9NtfAFCaRwWG1zazuezbCCbTe61gm9wmVu4VvMFx+GkrlbIZmNhyOnYsmYbqwSqSNoEAta5mh2/6qiRuIisEeP0jpnD/LD+uKidOUiOyJEddL251xvCFGfLNObq2cP4oTFTXTrTgHZDY75JOrhWR4hDzFC+jn3qwHzj9yq1V6LCPbfMtfylx9+JBOkJON+KGX3dV382Es2O5gTf3F4dCVYYxFx/y7jgZ0L/88DhD5mE0pKSaFupLuOap8UwLr2a+fe5G2InthcKI3YXhJkTh6lxeEj1zm3QKg6kcW3Lulea/jSoVFCwaVESMZ1HdP6bmejMDqRjI5NH+iXjj5uJHBRyxfnuC5A86r/7nJNQ+fkV6U0Vb+pVsJuVUd5sW9eG/iZX6be01QqChs994RpcgHY7h+aiPJiaK6UjLMbW7di4Et7QfR3v2zORftuRi+Q2Cilf41M/PUejkdE70d3W5ASVOZvDmzD0gb0f4fOKk2KItRRDrRz6slcz/T1Ab5LyNd5MJGdESVJpvFf3xWLND1TsAC3KNWmng0N+HYsDEmVKKQ2TuA8l5f6SukP7l3KbZdCEhmY5LSgWexbSIpElB0t2E88rkdAIjxv9S8qNqm7WpOe7VVUmbOKs8eMt+XFx/yYmCrIPLLFIAIlNIyLLF+XlrdT+GVWB2sU79o2YnkTIS0p0ETkqetL7ePzbeCB5/JkuvhzUCAQPV8jkLqOCeG79FmD7n/oPYpXYYRo9CZM/MaEq4AAunsusICYHSaRAMnt0U+KRy6pFA9FFhBiZ1ayiq0/QiC3oVXUqqTh72LzUQNW46NQ6LMVp30k7ZE0mBpNfYu1RVlICo3Jp6pYBfojb0Pu+VMLRFYQWvMimFYutWlFcC3HFUYI0XS/HP/03Lu5DQuJ7PP6fhMR1IxMTZiYSZiQmjSCq/TXBqrVRmK86SaOf7O+WiE5bicnWZFIwmRgkEad7lr9o+SXjZxle6p0+pKO1sPC+Azty5MbkRVD7tym5b8V2ns4lTNr3flwGA4QEXMehbo3e4LGbXyAMhvs5k3HdzWAgNxg5M47Mlx6eZ/24hULZkkLeDu4h4z418D0/6gXj3VIKZSm5Zp6Q51lumYGzPq4QRqncx/uCiaO3t18erKe8qMGpr6yPLxeb7hvy3XmEt7ZpzrvAU26OizsUG3s4Ng7pGctL/JrbKE1qDv6b5L6L2T0W14N86X/pTMhIbMA25F2pu2b5bORb1c11+4XzvnkW1C94aLq8tNZdN9I5bqRDYFA4ReOEiz3QdOMdOQ00BZptqPiVEKpP6A+XB6ijl+glc1YPPlNmw+VoyQ9GxK4+xa2hOsrXBLtV5DuXBRfQRoMTSxqcVPbBdco42FOmzoTSU+jswVq8PViHLwbr8WGnBu/bQBuaoAE0SwNosi3umYbYEoppM01CO2kS2lqT0DaahLa0VRgoq6moXlNRla2KqWDraKSfqHmhHE8UBivwn8FKPDdYjecHy/BMpwr/sG346A3NRp9qNvseEBjoHftUGxqjnaJe7RSNs7100Be2D9Bnmo9+1nz0jebT3oqe6SstRC9pIXpfC9EbdgjQa3YEqvrvQlBG5eR0R3/4a+jnXRn1p8oH/7SGEf2L/gXzndY553B0TUJbSr5N68k4aPOX7hDlaIHugUT27Q8DvGZQ92GCT9Njan/kqru9+4PGawpN0JRERe6z1UCTqCZHQN8HunbjZu2m5e3mce2Whe0+S5X1TLttZbt9WZt21mO0/Yn2f4H9B9puCO1HA7cWrvaDdptAh3kgLoWby2HeWpDngv8u4LcDlK/gX9MGnab2h869k73c2benOk/1+nSc6fWs8TKDGWp+0btkibd9OydHTy4VYOwf0OK725+LDwhUK4/zhCf6DEpjxpRFJBeYUhI/OnVii73LL+aU2VZ/iK8l3/Oj2l+trP+B/4+hDvHckQC5phsFtCpvpWKAv+WOBViV8QisigLwqK29jvYDS5BzuirhrdUpm9lj41xHJW9bFc4OeB9BINuYTnpscqPuRNp9/42uzsbllIRjAVNv4AAshMwC3GprJfgV4B3HP+o+jIyi2SMDdNyQ2JZ3swMdIb7FfoTBqW6IbAO2GSA8v1IKA7BcW0pz8e2/RmNpW8oSX38gABc1pJh8Bt43gB5XFzjab+qmLxOArSlnAji8qBPxA2s7bsCB6gZG5QwFyh8m2Ips1gxLVGkd1AWQyY0sIeJD0jrX10bpBmlihcc6ZACTMhJGmsoInK1x++aqAULasCsG/plRNFgAOaRWNgdZnm2kecX061S/LazATiOgtapdHdQakLUgNeXe/Lbrolb55oluXpRfYvSTUcZc1dqhknPMWHHF4iPD0JZfb58OOpUpQ7VrloLqRm+na2zcVTZRY6pHulG9La6y+qh5HWe4qurnruo9SP4LTmpEaoCYierT20ptkADaiA2xxEAyw9Y4+dBGo0BmJSLI/LTdlpzYYSZQuzCZDZmd2WZShIlregqRJRsuLjL7s703c0fWfm6iPh1Z2/RZPKJGsULMzrzqe01aDTZ6uoH1kb4h66xLIcuSdSapr6aNBBFRuMhkbmxq7mUaXpZhThau1XP6TW2QqodLGbWfy23pNdoTftEytg2YSIw1syGiG3L2OF/kIEALhwEo6Z5TjDIYib60AwW8fOSIUtJEUqyESxQybNoORSvsFLC2d5HCt6SvimN+s+70sz7Px3/E83pPaLnqqjJFiUmMy/X1WSUrcw4mlqZp6YayWtqGtFWjOCvJLAv7tSQGGJ3+DkGEwEhYf4NZdHE+EfbhNKXjhBSr0L3D8iJL16RuKFLCj7Kjf9wQ7T0d4zqGHP4D18ApX/t0Wm6to+Uq3pOcOtYl45g+sQswUoYRZhEQ7n3pXa05TDDz0MKR/Xobq74UCK4GCIcc7PCosR6kFgXqDaaBrlHw1TiLpnTspz17zuAw8foJD02JBv+Gd/lQhgfLrk1ZDptdTWWdGuuwZx172AqYdEVSpZtBjbO49kHSRnmInp51sQO3KxwOIZgbczTsSozBxBgpZSokNxFJK/Y+tPBsJQrypnaMJgybuG+Ilw5hOAz8UfimMndZYGmoEy3S6/GcL1x0HqcZg3K9RldNS+zTHLshUdh4t22WrCenhiwpnEUf8IRSVNCSHdgKpbi13taIiMsotcqVdXFE0G9kb2ePIO24R7ba2N0SRivslmarpYcxhpaiwUBkNajD9LweZRjlSFoWQ3KTmfIhZpTcSamOynJXAktbU8JqltomN5V2Zw8PVvipPo/qJiY3adf9LZbodwJrDxTjRR6bOj6GhPpoCPDWNV2StrilegU6tfjo78hOpG07qKXV4eUBbcTKuwJT2VQTaUckmju+SYAQqBT5EWGlyNqDmkt/k1rL2lJRCxEVmH3oX8RhSeFpuAwuhQOAutxEfyG45KfdWfVYQlgDqVHCFdPLuNGwpIFogwQEu3e56bJsixAPqYNoiPYQObCzhREW4yYYcywi520YC78f2+NoqQy2NtgjW2iasLIDYLQaV3EESaP3TDYoCL6safNE12UG8A+FQ7PWYDwso6z8mPMOwBYY8Fd4CU6Dg2EOuDch4YgEbt6u0WYqs9XJVTisCXmHumA3CV0ZUvWZnXED9lq69OON463zLY1Y8I/GAdYnV+hbJriSoPUGQ4fif9N2qv1ZDlNhZnimC8Z6v4kgGobbki5V2FYEJRHLwtoVbc2521HVYhwaqCtslavHwevVuUs+U4Ur4JXknKYBUqbubqHVArPVwc2I8komZs3yZZJXEETQAqLukZJVD+WayaUtzJtMzQSFSuT2Ft0eYl9tlZCYDIleEXmCgvcoXLbxWL9Y1/RKqIKoeAkxVXwmJxw4Wcqnlh2rWAZM50x5VJhBYdSmmytLpsttJW+cei/GlyzivyZvT3hPwrcyEGzKjmE6o8rKuSnM32q5gZsLFROFDQYfVHjGuhm2qGQLdg4zzExMxYiraZ/mWNTVScfE5Qm3DQCa3bThdw4XI+mQUqKq2xCqBiPkskMiziIiqrWoXMeBlgoLOBBkhICmPFwDGNzeDaIwU25riH3c1kSZaCe/+RrtJP3z/c86xte3wiofO+/1p5Y6ouO+3uL9CjvgvfDkdHeJyCWmPAmbks9lb6uZn86L22ughHHJiLKyA/CodTTEMa5HppTt1sktn8XfgYHMJrVzNuPYSiiPzP2MyTD0lEUAkLvLgbTa2QAZ3Fe7B0TAg1UdIIOWYM1Rt06Di6HE2C0aKAwXdl/owjaGd8ML8ETCRTMtkSRLplgiGI1saZy1xbTdTVsvhaF05yKiUF+Vw3GeSdvWoyYifCZKQRRXiqWbzSWaLSPLmrXdL2KTHflZyjyI4O2d0Qu1BqDJBDyGiWzgCsDCYAIGbKaOEqbhSfIEE5EMkzdgwBL+2Ti78KKddmR7iDZGHBp6Bv5XBp9RYPAfuBOug9/At869gY/A2hgDxglD7BxbGjPpMM7ud87CGkMPIjDWYu7cjt3LYrnKskMHyzhtHo5qYA+Mu04ewIGwDkNn58AsqXeU90qtfF91fli5jCil2J08TLSkHSo7ejKWfxehcfhFj1U993DWb27l06MzajwS9gjISA7J11264T0LWRlOSbNcQfk5V25sLWSaJF8UAQi/3Np2TJbBBwyqT18vgO2Eaifqivq0UQJFV7EETFqgEU4YiWBjE6g10P6erEPgtQ46Yj+fAUlbFMaK/PG0QKx1k8KRxFoIg4YIUrzIc0I3Z/K+g9xE4+D9KI2EdjeqQVrRrkZpcWmxG+6SRhilK/pkOPAn3cv5JNc4sOWAU9n80NCRpzZBFIowrH4n7nJz3GU3F5MriXYigQMIrBPoE2gQyInMvf5tYmmYH9H60d4zOLbQjH27IU6MlZyPY10a92hLO0XzEeDukxHNiHot88P4gva7k0BXpDFgsSWqSK9lc8LTNa+burqWWd9hmDLbtKP3JVJ40Md6VhW+Bg/BD4/Qdey0pQOh04jlMNCK9ZMHjRgmXlC4oaSGdKlLUUUrH/CZImYANlx155UYInwR1lIsX0zxdoXT+m+kl1PtPxPZm5V6bW2Ffo2+rq4KIQwEC+QGA4Y4rh1ffGERRv6EwOGsuF8QTwGEywYVbuQVcD/gT3ga8Or+JA0STiBst0F0UodieAwU63squl1Tr2osvMuwpDDpVFO44JphYk4T8kJqkCfI87IRh2c3wk1jhXR2VaWKBnq4anMqt1dd1WJAq8YVP0yvo3rd476qyGDAdMtoO1mvnilDort2zxCoaevuo7eVCqxbiJno5aJYqqWgG1Ggtg15OaklsSYYs3AcCmPVFPMTlzWPIYlUv6K7laoKsnJhJOKle4b7Vxohl0Gf3LeLz9dwMuk4HMkbUtM4YqRt7DreZxPIllMF0m1f1XK7CZmt2qCWnWJ4/c5nW2h5VTXTwDQccMJjmK6oYUX3+kx1yLYBp26Z70M2q08HidXNewa58x6/APDHAWsD9m1yEg1Qz45Y/LnCt+AVOAS9N0sLeT10cckCDiTQ4E/O2mJl5g00dkFnF+x1yNdxSD908v6OpvpZWWfKdsE0y8KD5AkDziYmwqdoq/4OMzFDDw1YIFMstfAaqphQTGGTQp2eajK2X86Mx9DvqkHF8GSgamQ48NRLe+tkuZEL9G3nC2o2IgNonZYtc9U277feSR43n0z2XWO8U+GtcAocDDshfKVJkVcpUT7DgANkDHCNwevmZyuqGeiSpLQKharYjgXKa9eoeSAfmJDa03VSa+58gta/xycMPJVuI2v3zOmtF8zck1RSiAIXbVi9p4RRmJnIPhMTZT9uG1BFIreTEKey0LRyBj6GLJGDiu4ylxUpqre0sjOdyEBH3+mybseGAXFaLkgGYkj72lIwtWEoDY8R0XbWgorcTwgLdoD155tNiIBAyOVAnKNAThcEOp8gt1TcQGyq0PcaTdHuVYXwbI5sV5rk7Ta0+zMI92rvcEgvS3f3OKWqzxbbqjOX+FVPuaCvpt/0k1Cgvzbez3AdHA7fgc/DmXBwroYN0A7gG/DB5LNmfQT3wE1wlLkgqKEFdn8AS0f/sY9ZOJSVrtMnA/hikii3gK35+NZEkARYIpnlZ0Za2JfvwrjZg+Hs/SnDh83HAW+AE1VUkf2BdTk+z5y0cwyggJ/Bu2AfM2clTPVodBJNXtDPEX4VdvcF98gzZp+W+JtJccH2IbaMsaEtdqVONbSXE1KWsBG7hBkGk1enYMv4HKIGWIbhEzEU2mJn5RTxcvlcloqRuKtQkZA7CZDPDEUrRnyn/rpXK57qb/nahi++Ur3aU7PnK2r3VLzJhzcht/Cv+1phUeELywffn4XiJfaU5iy/bf62emV3sQXAXLdMdpPaLzC+D9pmOV/xK8TpDU683upXjiAT+anDd5F4Sg9WM+/+7YP57DdC1JRLtLOr/M2c4LIt1igMKdRiQ2hUUKGFBUKstFpqV1iFt8xXAC1+hYiHWcbVODF3Y1IEceCpzCtSahMqeGXprseFHTA5XjJOAR9r6CAWNAuzvRB5odPyQe1IuoUyTHA2v8OKc1oty5FluhPhoQ52qDtNpUgR+xrGPsGGM4EEEibNx90F14xASOBr7joSkM8TrnbGbdXuyiBKmkoaFnjNlr6M5DNN8Gp3IF51XmV2tit7se+cqB8UuGwwosopSqpYycp0dB7Ys9Uo1VKkkKKrC/FpaMi9B7yiYQ5caoxumk3bCNLhymw97HiOwSHt2LUgFtP+s7g8CpCw0dtrfoB0VC1TOZpPTrpR1dq4LJeZavVQiha0QHk4tBWy3OzH6bqsgWj6eIcI9mDef6Y9Qhs/X8kUQbu1tSdU5t5dUwOUMMM+ZkGwYm++uEiiO0KgdcfR0U0HHtLKeCgtT4Wf9W5d2vfMgSGf27LXcBk1nmI+duPtC2kJu+r2XhQigwyU4wXBwmG4B1TUWRHBNkzyYWSTIYJkeErZ+XSol3rjwvCDU/a60RGqxN9cfDxoTyoKYfXRzgqtmFybVftGJlERNTG5cMv6qb1y/5y7FHchFTHEw2ZCiSsT/h4j+vVAbwit5zbIE8mp6vEep0utUJdSUKAIGImhNEWp2+6Bt8kVE6cdDtcM97VUlndWKQ4i6V3m1IKi/tl1Rqg71J+e+XBnSVs4CB1fcNNA7oW8Babl9sXMc12GFRqTwshve8fgNaB5z9rzdGRRpxEmIilsdfMFkSUraHNFYSamRrHit6IhfPBBmYjZSyjOt1a136dSuYQeG9mDyeLZpXhKwkmEGKvYJxrKqRRXAzBWxe01waQyazIPEAp7MJo6Zdtu68qC3ThRCytbZVF0qJBm89kEgivbBlKcYcZmzFrJu1vR4hYSskgFrCSb9RkK0+JhyrEVMrHMN7CMMefXlyQqRdsCttbIMOKePYsRnGostTkePiDS5XhW7qBoRjGwlHH7V6y49f9rCA1tJ3H0WSU91Rq8NvCwRomM4aqsphv3dYgmTzTYOSS+QdDf8KSP9YkYTb5NmkyK/ZlIZ0gnPWLLjFOok/jfE7F3N8H1Ur5zVV3MGiyTDDHhJn76DicgYDutsb8dUjG9rTXvDoCbzQOscvc+TGGxyogayn7NlNOSWX7JnB76nzHU+KrUI//Gbnqj43hu8Z1QUIDStfwqa5OtL8mZpCsTuERhCFFU826a3V3P+q+ea3zY+tmAMeTgFprYlwzD7r9a8yuAF/vX+DqshRg+BffB5bDR7HX73H47d1k8p4Ea7AMmRtz4yAn3oqThUya8X/gKZUm4KwWfUXg/vAinwRHwT/gFfH5V28iNiaGbhmEbHDZOsuaBgJ/1fynvzuSujFcmIz5YwVizGXLJQtgIzbEGp95r7yEN9X/5FeC7v/U+qr+9nhN6m4536F5PCK+sStPzAxs3LrDhZBu221DZ8M6IL0ac2fCt6NPR7RHPsWHZBvuTTaSDrNuknuOm6YrF70TGh+RuMy8K4GaRRC+TRu/X0V1Oi9MCWmm/zubyzs4ppJxVrlSGrGvLrdZQYG95IBAiWsuJxJBwUrlQGDIuKjcaQzlby3NyptWMKq+pKf3saCm9gaKpcS79uuzREwDCqfP5kuO5ON1HrB/1pFHOF/g5p1vxRu+JbdwAeKR6v6kv9/4CqndOoP7J0Ow74haVrgj69/q+UjtpYquSoxwcXaLg6i3MTrFJ4/VnNmSDoIrg8VZs9vE4XzoMqdGiM1h4iZDmc1k3yFgi4UQbDTqiU49P4vKWuytOnfUk5ouwrreatZhUZYrrIeQRyCAPeqvD5/Yr9jHur2Otnorzs61rLU9yT5zwSobcKRXDUdaapSbxVj9it5UWy+uqPqmSuONRHF8d6wnMv1S5AfAqrUvPWU3qXScXmIfYKRnEXg03bw1e99RAv4Z85fV/oOvaVtF9G3BVicTX35V+vLnKmnL2ipZYBLhOAVweUxcNPO8YmHhmLxXv9yuLwHw/bem5Sg3uaiO9kkjWGy6nqFRJKp2AXBNSLoFVR23g2h2nqJM0fiWvFMGYVKZMsiDc1689sz3smSHba+aiILBc4uuGqI71ED+eVyLzvCLAovHuKK4caJAB3T6SoDjQmochdYN/GVSEonJK7eKFS2WAgOU1XomK8nw2KdDN4VKdWOh2HwdZr6GV3Gt/lS+iDCoB5gluMS/Kpek08NVIEkF/Xo8+k4R3z7kyQUKma53J/LMEwHjqDwDkAJ5u1O3cEXn7VAlfaojC2i8+zQQ1G0u0qdXHErYazDfv8Tkh6AtvG7zsxgHA5fv6NRfWPVE/PXiLgK1qMTkgtFKZuv9h7vWBvlKgz5P2brK+kU1krHwB2Nhe9XSQHiRPbkXoA2+fkLZ6KnfE0bWX4hLpweE5U8KIJH/rBqyJY9obxJz4o15D/IiZmImZ2IhZM3O4osaryaSKdCEldtrWbqIlZbmmkSCGrh2RKI0TIYTMqKEsyQDnsjmRRqQ+CSCt7Zp40k32g93ViIy1hylJB+Kfawd+PUPwbqC60Pbr8af0Rqb2ZpD35g3ZBWEQ4BZ2E6SjERqR5gOypWcoBIBo8yMzHanlsQcpre0hOCd7KD6BHpo+qT0MdXp6WbqsRklbH0W6DEAPMpnaQ4h29lBi/NFDc8faw7Cm5PVnuTJcmgrdDdBTJx101JssRpRoNV0uS4WKXLCrdn3z5UsTIVMS0jVeD6F6Kdx2enm3p74i21bFgXc85JxCMPR2Vb4rLYIRW7Yf6/Uv0qkHoY3W16rybRtcTdTPL+8FYeinso/sa6UnEJBBBVxNosLwo244EX5GEzfosx3u0zHF4vgyWsQqLhNVkgNuL51YleemjBAm6VjAssPzTUxEVFQsxLBy1IaJ2Y/06ysNdOAWGsSWrhht1LkOdaC/MU4BXAK5BQkWItRvwoSLEHmGXGyMWDXUVEttceIlSJSkTpt3ZIr8xDTpMmTKqkN7Mk++gpaOYe/Lt576GmioRCOlGmuiqWaaK9NCS61CYIVRRjtktifGmGyCRdZZGQrGu2akGaGRgUlhocoJt8LBYut99MEny21yzhmbtdbGVG39rp2zzvu77T2TT7X3f/t7+m7RwRvT3Asudpt/7qVxOuuki266KrdUhR66F+rfhvvora9+nulvoAEGGWKwvZYZZqjhKr3wyn6XbbXNFTddDY8KFGC7HXbb46SddjllrA0OO+JglKiCiVGjCH+pz4pRHff5lRoA67p3CeqmcoKketMwSrwG/L6d3mD88p8tVpvd4XS5PV6fnwkIYmYBs7Kxc3ByQbil8/DyyeCHCggKyZQlLCJbjlx58g1VoFCRYiVKlSk3TIVKVarV1DjwXTeJtn7zVlCiSTW5T23+WlsCmtoPppQyDAeVdxrmX7LD8Bgbnc/NxqxYjhE2uOO5nlMjrIOHuPuGw4fg/LK+/MyvEDqPBOvGjym7wl3awQcWX3/nMt0ooJAiigPalRsRQCBBgPWcKU+kT8yxRY9A66x06sakIFQJG6RcjCfPksmS0Vk5Xx9Wqubtt7xvVW3/r6C6kbId/4AKnJz9gfIxZ2qgfGxWhXJQRSwjItPBHslLFUgNiJbUkFVBS0ZIS3FIS4DTUiWnpS6RloAKqdtQHPxUcINxYFBR4HqvwlD1gMGhlf7jIPAAcMd9RlP9WyLE4u/FBy8MM393CIi2YUajMdsEekcj3HETHXbmiJ/YOesEw2D1mwtM5BLkdeGSWMq6AYYjeGBAC7yEEXZQepYY0HU4uGJnhZwZ6CYQEb6Lpfwgc7RgJwHNODsKl9gJvwzoDjlBwLih+4hbO2fuIkFZVOyE5Qo8hLlDQOBn5skiVX9BG7IM6/KGuB+N3oeNbQnNM/XXAE/UThEHBAX5PEdxBSINCDuhEk4MQ/5EEzfk+/zv5bmQHBH+Qxd2Cwk7yZlCCTkk6Kb43SRPQEZ5frKf120Tbz1T+oBuXuAfsodrI6dzu7m5aROEayS72H6yk705Dna+l53dzcZxrBwEYJZjYXEvM6uQDDE9IJNCNjHiXmmMbka6Y6DBo6fZyLpUOFpqLqChOmoqHBWlNqCkeBSUTrKcDEdGzgekZEeSQo6Y5AOi5F4Az0jmsB0Gnbx0NjEpQiPaXqkEFZlKcChJlCSndJpsYjdSAgLJ8csR1UmmVRmXz5/7evzi3vf8J/qjF2pZ7blneY2OhoeUDo9savdod7hGq8Ndu2oPaH+4Q9vDDVofJldiuG+37boVdos2hytUGm7akl2p1daS//gbunWnUGXvMnT7GPilsH0567s5pF039ORjExF/Dnz74wfcvengd5f5mcHqsZEo7R4EOMsJLbT2VOgkBuFedTIXSkF4BwQfos3IrF5yEu4bxCoDAAAA') format('woff2'),url('data:application/font-woff;charset=utf-8;base64,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') format('woff');font-weight:normal;font-style:normal}@font-face{font-family:'TypoGraphica';src:url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'),url('../fonts/TypoGraphica.woff') format('woff'),url('../fonts/TypoGraphica.ttf') format('truetype'),url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'argon';src:url('../fonts/argon.eot?u6kthm');src:url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'),url('../fonts/argon.ttf?u6kthm') format('truetype'),url('../fonts/argon.woff?u6kthm') format('woff'),url('../fonts/argon.svg?u6kthm#argon') format('svg');font-weight:normal;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"}:root{--primary:#5e72e4;--dark-primary:#483d8b;--main-color:#09c;--header-bg:#09c;--header-color:#fff;--bar-bg:#5e72e4;--menu-bg-color:#fff;--menu-color:#5f6368;--menu-color-hover:#202124;--main-menu-color:#202124;--submenu-bg-hover:#d4d4d4;--submenu-bg-hover-active:#09c;--blue:#5e72e4;--indigo:#5603ad;--purple:#8965e0;--pink:#f3a4b5;--red:#f5365c;--orange:#fb6340;--yellow:#ffd600;--green:#2dce89;--teal:#11cdef;--cyan:#2bffc6;--gray:#8898aa;--gray-dark:#32325d;--light:#ced4da;--lighter:#e9ecef;--secondary:#f7fafc;--success:#2dce89;--info:#11cdef;--warning:#fb6340;--danger:#f5365c;--light:#adb5bd;--dark:#212529;--default:#172b4d;--white:#fff;--neutral:#fff;--darker:black;--background-color:#f4f5f7;--login-form-bg-color:rgba(244,245,247,0.8);--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--blur-radius:10px;--blur-opacity:.5;--blur-radius-dark:10px;--blur-opacity-dark:.5;--font-family-sans-serif:"Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;--font-family-normal:Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif}html,body{margin:0px;padding:0px;height:100%;font-size:16px;font-family:"Google Sans","Microsoft Yahei","WenQuanYi Micro Hei","sans-serif","Helvetica Neue","Helvetica","Hiragino Sans GB";font-family:var(--font-family-sans-serif)}html{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{font-size:.875rem;background-color:#f4f5f7;background-color:var(--background-color);color:#32325d;color:var(--gray-dark);-webkit-tap-highlight-color:transparent}*{margin:0;padding:0;box-sizing:border-box}::selection{background-color:#5e72e4;background-color:var(--primary);color:#ffffff;color:var(--white)}a:link,a:visited,a:active{color:#5e72e4;color:var(--primary);text-decoration:none}a:hover{text-decoration:underline}li{list-style-type:none}.table{position:relative;display:table}.tr{display:table-row}.thead{display:table-header-group}.tbody{display:table-row-group}.tfoot{display:table-footer-group}.td,.th{line-height:normal;display:table-cell;padding:.5em;text-align:center;vertical-align:middle}.th{font-weight:bold;white-space:nowrap}.tr.placeholder{height:4em}.tr.placeholder>.td{line-height:3;position:absolute;right:0;bottom:0;left:0;padding:.4rem 0 !important;text-align:center !important;background:inherit}.td[width="33%"]{padding:1.1em 1.5rem}.table[width="33%"],.th[width="33%"],.td[width="33%"]{width:33%}.table[width="100%"],.th[width="100%"],.td[width="100%"]{width:100%}.col-1{flex:1 1 30px !important}.col-2{flex:2 2 60px !important}.col-3{flex:3 3 90px !important}.col-4{flex:4 4 120px !important}.col-5{flex:5 5 150px !important}.col-6{flex:6 6 180px !important}.col-7{flex:7 7 210px !important}.col-8{flex:8 8 240px !important}.col-9{flex:9 9 270px !important}.col-10{flex:10 10 300px !important}*{box-sizing:border-box;margin:0;padding:0}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:normal;line-height:1.1 !important;color:inherit}select{padding:.36rem .8rem;color:#555;border:thin solid #ccc;background-color:#fff;background-image:none}.btn,button,select,input,.cbi-dropdown{line-height:1.5rem;padding:.5rem .75rem;margin:.25rem .1rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;transition:box-shadow .15s ease}select,.cbi-dropdown{width:inherit;cursor:default}select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus{border-color:#5e72e4;border-color:var(--primary);box-shadow:0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1)}.cbi-dropdown,select[multiple="multiple"]{height:auto}pre{overflow:auto}code{font-size:1rem;font-size-adjust:.35;padding:1px 3px;color:#101010;border-radius:2px;background:#ddd}abbr{cursor:help;text-decoration:underline;color:#5e72e4;color:var(--primary)}hr{margin:1rem 0;opacity:.1;border-color:#eee}.login-page{height:100%}.login-page .video{position:absolute;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#000;background-color:var(--darker);overflow:hidden}.login-page .video video{width:100%;height:auto}.login-page .volume-control{position:fixed;right:1rem;top:1rem;width:1.5rem;height:1.5rem;z-index:5000;cursor:pointer;background-size:contain;background-image:url(../img/volume_high.svg)}.login-page .volume-control.mute{background-image:url(../img/volume_off.svg)}.login-page .main-bg{position:absolute;width:100%;height:100%;left:0;top:0;background-image:url(../img/blank.png);background-repeat:no-repeat;background-position:center;background-size:cover;transition:all .5s}.login-page .login-container{height:100%;margin-left:4.5rem;position:absolute;top:0px;display:flex;flex-direction:column;-webkit-box-pack:center;justify-content:center;align-items:flex-start;min-height:100%;z-index:2;width:420px;box-shadow:rgba(0,0,0,0.75) 0 0 35px -5px;margin-left:5%;background:transparent}.login-page .login-container .login-form{display:flex;flex-direction:column;-webkit-box-align:center;align-items:center;position:absolute;top:0px;width:100%;min-height:100%;max-width:420px;background-color:#fff;background-color:var(--white);-webkit-backdrop-filter:blur(var(--blur-radius));backdrop-filter:blur(var(--blur-radius));background-color:rgba(244, 245, 247, var(--blur-opacity))}.login-page .login-container .login-form .brand{display:flex;-webkit-box-align:center;align-items:center;margin:50px auto 100px 50px;color:#525461;color:var(--default)}.login-page .login-container .login-form .brand .icon{width:50px;height:auto;margin-right:25px}.login-page .login-container .login-form .brand .brand-text{font-size:1.25rem;font-weight:700;font-family:"TypoGraphica"}.login-page .login-container .login-form .brand:hover{text-decoration:none}.login-page .login-container .login-form .form-login{width:100%;padding:20px 50px;box-sizing:border-box}.login-page .login-container .login-form .form-login .errorbox{text-align:center;color:#fb6340;color:var(--warning);padding-bottom:2rem}.login-page .login-container .login-form .form-login .input-group{margin-bottom:1.25rem;position:relative}.login-page .login-container .login-form .form-login .input-group::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#525461;color:var(--default);font-size:1.5rem;position:absolute;z-index:100;left:10px;top:10px}.login-page .login-container .login-form .form-login .input-group .border{position:absolute;width:100%;height:1px;bottom:0;border-bottom:1px #5e72e4 solid;border-bottom:1px var(--primary) solid;transform:scaleX(0);transition:transform .3s}.login-page .login-container .login-form .form-login .input-group input{font-size:1rem;line-height:1.5em;display:block;width:100%;padding:.5rem .75rem .5rem 3rem;margin:.825rem 0;box-sizing:border-box;transition:all .3s cubic-bezier(.68, -0.55, .265, 1.55);color:#525461;color:var(--default);border:0;border-radius:0;border-bottom:1px solid #fff;border-bottom:1px solid var(--white);background-color:transparent;background-clip:padding-box;box-shadow:0 3px 2px rgba(233,236,239,0.05);outline:none}.login-page .login-container .login-form .form-login .input-group input:focus+.border{transform:scaleX(1)}.login-page .login-container .login-form .form-login .input-group .cbi-input-password{margin-bottom:2rem;position:relative}.login-page .login-container .login-form .form-login .user-icon::before{content:"\e971"}.login-page .login-container .login-form .form-login .pass-icon::before{content:"\e910"}.login-page .login-container .login-form .cbi-button-apply{width:100% !important;box-shadow:rgba(0,0,0,0.1) 0 0 50px 0;font-weight:600;font-size:15px;color:#fff;color:var(--white);text-align:center;width:100%;cursor:pointer;min-height:50px;background-color:#5e72e4 !important;background-color:var(--primary) !important;border-radius:6px;outline:none;border-width:initial;border-style:none;border-color:initial;border-image:initial;padding:10px 0px;margin:30px 0px 100px;transition:all .3s !important;letter-spacing:.8rem}.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus{opacity:.9}.login-page .login-container footer{box-sizing:border-box;width:100%;text-align:center;line-height:1.6rem;display:flex;justify-content:space-evenly;margin-top:auto;padding:0px 0px 30px;z-index:10;color:#525461;color:var(--default);position:absolute;bottom:0}.login-page .login-container footer .ftc{position:absolute;bottom:30px;width:100%}.login-page .login-container footer .luci-link{display:block}header,.main{width:100%}footer{font-size:.8rem;overflow:hidden;padding:1rem;text-align:right;white-space:nowrap;color:#aaa}footer>a{text-decoration:none;color:#aaa}small{font-size:90%;line-height:1.42857143;white-space:normal}.main{position:relative;top:0;bottom:0;overflow-y:auto;height:100%}.main-left{top:0;float:left;width:15%;width:calc(0% + 15rem);height:100%;background-color:#fff;background-color:var(--menu-bg-color);box-shadow:rgba(0,0,0,0.75) 0 0 15px -5px;overflow-x:auto;position:fixed;z-index:100}.main-left .sidenav-header{padding:1.5rem .5rem;text-align:center}.main-left .sidenav-header .brand{font-size:1.8rem;color:#5e72e4;color:var(--primary);font-family:"TypoGraphica";text-decoration:none;text-align:center;cursor:default;vertical-align:text-bottom}.main-left::-webkit-scrollbar{width:5px;height:1px}.main-left::-webkit-scrollbar-thumb{background-color:#f6f9fc}.main-left::-webkit-scrollbar-track{background-color:#fff}.main-right{float:right;width:85%;width:calc(100% - 15rem);height:100%;transition:all .2s}.main-right>#maincontent{position:relative;z-index:50}.pull-right{float:right}.pull-left{float:left}.nowrap:not(.td){white-space:nowrap}[disabled="disabled"]{pointer-events:none}header{color:#fff;color:var(--header-color);padding:0;position:relative}header.bg-primary{background-color:#5e72e4 !important;background-color:var(--primary) !important}header::after{content:"";position:absolute;height:2rem;width:100%;background-color:#5e72e4 !important;background-color:var(--primary) !important}header .fill{padding:.8rem 0;border-bottom:0 solid rgba(255,255,255,0.08) !important;display:flex}header .fill .container{height:2rem;padding:0 1.25rem;display:flex;align-items:center;width:100%}header .fill .container .flex1{flex:1}header .fill .container .flex1 .showSide{display:none;color:#fff;font-size:1.4rem}header .fill .container .flex1 .showSide:hover{text-decoration:none}header .fill .container .flex1 .brand{font-size:1.5rem;color:#fff;font-family:"TypoGraphica";text-decoration:none;padding-left:1rem;cursor:default;vertical-align:text-bottom;display:none}header .fill .container .pull-right{float:right;margin-top:0rem;display:flex}header .fill .status span{display:inline-block;font-size:.8rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;text-shadow:none;border-radius:4px;cursor:pointer;transition:all .3s;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);margin:0 .25rem}header .fill .status span:last-child{margin-right:0}header .fill .status span[data-indicator="poll-status"]{color:#32325d;background-color:#fff}header .fill .status span[data-style="active"]{background-color:var(--green)}header .fill .status span[data-style="inactive"]{color:#ffffff !important;background-color:#32325d}#xhr_poll_status{display:flex;margin-left:.5rem}#xhr_poll_status *{color:#fff}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{border:0 !important}.danger{background-color:#ff7d60 !important}.warning{background-color:#f0e68c !important}.success{background-color:#5cb85c !important}.notice{background-color:#11cdef !important;color:#fff}.error{color:#f00}.alert,.alert-message{font-weight:bold;margin-bottom:1.25rem;padding:1rem 1.25rem;border:0;border-radius:.375rem !important;background-color:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12);text-shadow:1px 1px rgba(0,0,0,0.1)}.alert.error,.alert-message.error{background-color:#ffd600}.alert h4,.alert-message h4{padding:.25rem 0;border-radius:4px;background-color:#ffd600}.alert .btn,.alert-message .btn{height:auto}.alert-message>h4{font-size:110%;font-weight:bold}.alert-message>*{margin:.5rem 0}.alert-message .btn{padding:.3rem .6rem}.container .alert,.container .alert-message{margin-top:0rem}.main .main-left{transition:all .2s}.main .main-left .nav{margin-top:.5rem}.main .main-left .nav>li>a:first-child{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav>li>a:first-child.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child.active::before{color:#fff !important}.main .main-left .nav>li>a:first-child.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav>li>a:first-child:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav>li>a:first-child:hover::before{color:#fff !important}.main .main-left .nav>li>a:first-child::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li{padding:.5rem 1rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0}.main .main-left .nav li a{display:block;color:#5f6368;color:var(--menu-color)}.main .main-left .nav li.slide{padding:0}.main .main-left .nav li.slide ul{display:none;overflow:hidden}.main .main-left .nav li.slide:hover{background:none}.main .main-left .nav li.slide .slide-menu{margin:0 .5rem 0 2.5rem;padding:0 .5rem}.main .main-left .nav li.slide .slide-menu.active{display:block}.main .main-left .nav li.slide .slide-menu li{position:relative;border-radius:.375rem;margin:0;padding:.5rem 0;background:none;list-style:none}.main .main-left .nav li.slide .slide-menu li a{text-decoration:none}.main .main-left .nav li.slide .slide-menu li::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu li:hover{background:none}.main .main-left .nav li.slide .slide-menu li:hover::after{width:100%}.main .main-left .nav li.slide .slide-menu .active{background:none;color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active a{color:var(--menu-color)}.main .main-left .nav li.slide .slide-menu .active::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#5e72e4;background-color:var(--primary);transition:all .2s}.main .main-left .nav li.slide .slide-menu .active:hover{background:none}.main .main-left .nav li.slide .slide-menu .active:hover::after{width:100%}.main .main-left .nav li .menu{display:block;margin:.1rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;cursor:default;font-size:1rem;transition:all .2s;position:relative}.main .main-left .nav li .menu.active{color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu.active::before{color:#fff !important}.main .main-left .nav li .menu.active::after{transform:rotate(90deg);color:#fff !important}.main .main-left .nav li .menu:hover{cursor:pointer;color:#fff;background:#5e72e4;background:var(--primary)}.main .main-left .nav li .menu:hover::before{color:#fff !important}.main .main-left .nav li .menu::before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e915";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu::after{position:absolute;right:.5rem;top:.8rem;font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-moz-osx-font-smoothing:grayscale;content:'\e90f';transition:all .15s ease;color:#ced4da;text-rendering:auto;-webkit-font-smoothing:antialiased;transition:all .3s}.main .main-left .nav li .menu[data-title=Status]:before{content:"\e906";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=System]:before{content:"\e90a";color:#fb6340}.main .main-left .nav li .menu[data-title=Services]:before{content:"\e909";color:#11cdef}.main .main-left .nav li .menu[data-title=NAS]:before{content:"\e90c";color:#f3a4b5}.main .main-left .nav li .menu[data-title=VPN]:before{content:"\e90b";color:#8965e0}.main .main-left .nav li .menu[data-title=Network]:before{content:"\e908";color:#8965e0}.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before{content:"\e90d";color:#2dce89}.main .main-left .nav li .menu[data-title=Docker]:before{content:"\e911";color:#6699ff}.main .main-left .nav li .menu[data-title=Statistics]:before{content:"\e913";color:#8965e0}.main .main-left .nav li .menu[data-title=Control]:before{content:"\e912";color:#5e72e4;color:var(--primary)}.main .main-left .nav li .menu[data-title=Asterisk]:before{content:"\e914";color:#fb6340}.main .main-left .nav li a[data-title=Logout]:before{content:"\e907";color:#adb5bd}.lg{margin:0;padding:0 !important}.logout{display:block;margin:.8rem .5rem .1rem .5rem;padding:.675rem 0 .675rem 2.5rem;border-radius:.375rem;text-decoration:none;font-size:1rem;transition:all .2s;position:relative}.logout:before{font-family:'argon' !important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;left:.8rem;padding-top:3px;transition:all .3s;content:"\e907";color:#32325d !important}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before{transition:transform .1s ease-in-out}body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before{transition:transform .2s ease-in-out}.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before{display:none}#maincontent>.container{margin:0 1.25rem 1rem 1.25rem}ul{line-height:normal}li{list-style-type:none}h1{font-size:2rem;padding-bottom:10px;border-bottom:thin solid #eee}h2{margin:0 0 1rem 0;font-size:1.25rem;letter-spacing:.1rem;padding:1rem 1.25rem;color:#32325d;border-radius:.375rem;background:#fff;box-shadow:0 4px 8px rgba(0,0,0,0.03);font-weight:bold}h3{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark);border-radius:.375rem;background:#fff;font-weight:bold}h4{margin:0;padding:.75rem 1.25rem;font-size:.7rem;font-weight:600;color:#525f7f;background-color:#e9ecef;background-color:var(--lighter);font-weight:bold}h4 em{padding:0 .5rem}h5{font-size:1rem;margin:2rem 0 0 0;padding-bottom:10px}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{font-family:inherit;font-weight:normal;font-style:normal;line-height:normal;min-width:inherit;margin:1.25rem 0;padding:0rem;border:0;border-radius:.375rem;background-color:#fff;box-shadow:0 0 1rem 0 rgba(136,152,170,0.15)}.cbi-modal .cbi-section,.cbi-section .cbi-section{padding:0;box-shadow:none}.cbi-modal .cbi-tabmenu{margin-left:0}.cbi-map-descr{font-size:small;line-height:1.5;padding:0 1.25rem}.cbi-section-descr:not(:empty){font-size:small;line-height:1.5;padding:1rem 1.25rem 0 1.25rem}.cbi-map-descr+fieldset{margin-top:1rem}.cbi-map-descr>abbr{cursor:help;text-decoration:underline}.cbi-section>legend{display:none !important}fieldset>fieldset,.cbi-section>.cbi-section{margin:0;padding:0;border:0;box-shadow:none}.cbi-section>h3:first-child,.panel-title{font-size:1.1rem;line-height:1;display:block;width:100%;margin:0;margin-bottom:0;padding:.8755rem 1.25rem;color:#32325d;color:var(--gray-dark)}.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child{padding:1rem 1.25rem}.cbi-section p{padding:1rem}.cbi-tblsection{overflow-x:scroll}table{border-spacing:0;border-collapse:collapse}table,.table{overflow-y:hidden;width:100%;font-size:90%}.table .table-titles th{background-color:#e9ecef;background-color:var(--lighter)}table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell{padding:.5rem}.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td{padding:.6rem}.cbi-section-table-cell{line-height:1.1;align-self:flex-end;flex:1 1 auto}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:thin solid #ddd;padding:1.1em 1.25rem}#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{border-top:0 !important;background-color:#f6f9fc;padding:1.1em 1.25rem;line-height:1.3rem}.table[width="100%"]>.tr:first-child>.td{margin:auto 0}.cbi-section-table-row{margin-bottom:1rem;text-align:center !important;background:#f4f4f4}.cbi-section-table-row:last-child{margin-bottom:0}.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{width:100%}.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password{min-width:80px}.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password{width:calc(100% - 1.5rem)}.cbi-section-table-row .td{text-align:center !important}.control-group{display:inline-flex;width:100%;flex-wrap:wrap;gap:2px}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#f9f9f9}table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td{border:0}.btn,.cbi-button,.item::after{font-size:.8rem;display:inline-block;width:auto !important;padding:.45rem .8rem;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:all .2s ease-in-out;text-align:center;vertical-align:middle;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:rgba(0,0,0,0.87);border:0;border-radius:.2rem;background-color:#f0f0f0;background-image:none;-webkit-appearance:none;-ms-touch-action:manipulation;touch-action:manipulation}.cbi-button-up,.cbi-button-down{font-size:1.2rem;display:inline-block;min-width:0;padding:.2rem 1rem;font-size:0;color:transparent !important;background:url(../icon/arrow.svg) no-repeat center;background-size:12px 20px}.cbi-button-up{transform:scaleY(-1)}.cbi-button:not(select){-webkit-appearance:none !important}.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active{text-decoration:none;outline:0}.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after{box-shadow:0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2)}.btn:active,.cbi-button:active,.item:active::after{box-shadow:0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23)}.cbi-button-up:hover,.cbi-button-up:focus{box-shadow:0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2)}.cbi-button-up:active{box-shadow:0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23)}.btn:disabled,.cbi-button:disabled{cursor:not-allowed;pointer-events:none;opacity:.5;box-shadow:none}.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"]{font-weight:bold;color:#fff;border:thin solid #8898aa;background-color:#8898aa}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{font-weight:normal;color:#fff !important;border:thin solid #5e72e4;border:thin solid var(--primary);background-color:#5e72e4;background-color:var(--primary)}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{font-weight:normal;color:#fff;border:thin solid #f5365c;border:thin solid var(--red);background-color:#f5365c;background-color:var(--red)}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid #eea236;background-color:#f0ad4e}.cbi-button-success,.cbi-button-download,.cbi-button[name="backup"],.cbi-button[value="Download"],.cbi-button[value="Save mtdblock"]{font-weight:normal;color:#fff;border:thin solid #4cae4c;background-color:#5cb85c}.cbi-page-actions .cbi-button-link:first-child{float:left}.a-to-btn{text-decoration:none}.cbi-value-field .cbi-button-add{font-weight:bold;margin:4px 0 4px 3px;padding:1px 6px;display:flex;align-items:center}.tabs{margin:0 0 1rem 0;padding:0 1rem;background-color:#FFFFFF;border-radius:.375rem;box-shadow:0 4px 8px rgba(0,0,0,0.03);white-space:nowrap;overflow-x:auto}.tabs::-webkit-scrollbar{width:1px;height:5px}.tabs::-webkit-scrollbar-thumb{background-color:#f6f9fc}.tabs::-webkit-scrollbar-track{background-color:#fff}.tabs li[class~="active"],.tabs li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0;border-radius:0}.tabs li[class~="active"] a,.tabs li:hover a{color:#5e72e4;color:var(--primary)}.tabs li{font-size:.875rem;display:inline-block;padding:.875rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0;transition:all .2s}.tabs li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.tabs li:hover{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary)}.cbi-tabmenu{color:white;padding:.5rem 1rem 0 1rem;white-space:nowrap;overflow-x:auto}.cbi-tabmenu::-webkit-scrollbar{width:1px;height:5px}.cbi-tabmenu::-webkit-scrollbar-thumb{background-color:#f6f9fc}.cbi-tabmenu::-webkit-scrollbar-track{background-color:#fff}.cbi-tabmenu li{background:#dce3e9;display:inline-block;font-size:.875rem;border-top-left-radius:.25rem;border-top-right-radius:.25rem;padding:.5rem 0;border-bottom:.18751rem solid rgba(0,0,0,0);margin:0 .2rem}.cbi-tabmenu li a{text-decoration:none;color:#404040;padding:.5rem .8rem}.cbi-tabmenu li:hover{cursor:pointer;border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0}.cbi-tabmenu li:hover a{color:#525f7f}.cbi-tabmenu li[class~="cbi-tab"]{border-bottom:.18751rem solid #5e72e4;border-bottom:.18751rem solid var(--primary);color:#5e72e4;color:var(--primary);background-color:#dce1fe;margin-bottom:0}.cbi-tabmenu li[class~="cbi-tab"] a{color:#5e72e4;color:var(--primary)}.cbi-tab-descr{padding:.5rem 1.5rem}.cbi-section-node{padding:1rem 0}.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n){background-color:#f9f9f9}[data-tab-title]{overflow:hidden;height:0;opacity:0;margin:0;padding:0rem 0rem !important}[data-tab-title] p{margin-left:1rem;margin-bottom:1rem}[data-tab-active="true"]{overflow:visible;height:auto;opacity:1;transition:opacity .25s ease-in;margin:inherit !important}.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4){background-color:#f9f9f9}.cbi-section-node-tabbed{margin-top:0;padding:0;border:0 solid #d4d4d4;border-radius:.375rem}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#f9f9f9}.cbi-value-field,.cbi-value-description{line-height:1.25;display:table-cell}.cbi-value-field abbr,.cbi-value-description abbr{color:#32325d;color:var(--gray-dark)}.cbi-value-description{font-size:small;padding:.5rem;opacity:.5}.cbi-value-title{display:table-cell;float:left;width:23rem;padding-top:.25rem;padding-right:2rem;text-align:right;word-wrap:break-word}.cbi-value{display:inline-block;width:100%;padding:.35rem 1rem .2rem 1rem;line-height:2.4rem}.cbi-value ul{line-height:1.25}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:18rem}.cbi-value input[type="password"]{border-bottom-right-radius:0;border-top-right-radius:0;margin-right:0}.cbi-value input[type="password"]+.cbi-button-neutral{height:42px;border-bottom-left-radius:0;border-top-left-radius:0;margin-left:0;border:0}#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select{min-width:11rem}#cbi-network-switch_vlan .cbi-input-text{max-width:3rem}.cbi-input-invalid{color:#f5365c;border-bottom-color:#f5365c}.cbi-section-error{font-weight:bold;line-height:1.42857143;margin:18px;padding:6px;border:thin solid #f5365c;border-radius:3px;background-color:#fce6e6}.cbi-section-error ul{margin:0 0 0 20px}.cbi-section-error ul li{font-weight:bold;color:#f5365c}.td[data-title]::before{font-weight:bold;display:none;padding:.25rem 0;content:attr(data-title) ":\20";text-align:left;white-space:nowrap}.tr.placeholder .td[data-title]::before{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-weight:bold;display:table-cell;align-self:center;flex:1 1 5%;padding:.25rem;content:attr(data-title) "\20";text-align:center;vertical-align:middle;white-space:normal;word-wrap:break-word}.cbi-rowstyle-1{background-color:#f9f9f9}.cbi-rowstyle-2{background-color:#eee}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#fff !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{width:auto !important}.td.cbi-section-actions{text-align:right !important;vertical-align:middle}.td.cbi-section-actions>*{display:inline-flex}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:0 5px;display:flex;align-items:center}.td.cbi-section-actions>*>form{display:inline-flex;margin:0}.cbi-checkbox{margin:0 .25rem}.cbi-dynlist{line-height:1.3;flex-direction:column;min-height:30px;cursor:text}.cbi-dynlist>.item{position:relative;max-width:25rem;pointer-events:none;color:#8898aa;outline:0}.cbi-dynlist[name="sshkeys"]>.item{max-width:none}.cbi-dynlist>.item::after{position:absolute;width:2.2rem !important;height:calc(100% - .5rem - 2px);right:0;bottom:0;content:"\00D7";pointer-events:auto;background-color:var(--red);font-weight:normal;font-size:1.2rem;display:flex;align-items:center;justify-content:center;line-height:1.5rem;padding:0;margin:.25rem .1rem .25rem 0;color:#fff;border:1px solid #f5365c;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.item>span{white-space:normal;word-break:break-word;line-height:1.5rem;padding:.5rem .5rem;margin:.25rem .1rem;color:#8898aa;border:1px solid #dee2e6;border-radius:.25rem;outline:0;background-image:none;box-shadow:none;display:block;transition:box-shadow .15s ease;box-sizing:border-box;min-width:15rem}.cbi-dynlist>.add-item{display:inline-flex;align-items:center;width:100%;min-width:16rem}.cbi-dynlist>.add-item input{border-top-right-radius:0;border-bottom-right-radius:0;margin-right:0;border-right:none}.cbi-dynlist>.add-item .cbi-button-add{font-weight:normal;font-size:1.2rem;display:flex;align-items:center;line-height:1.5rem;padding:.5rem .75rem;margin:.25rem .1rem .25rem 0;color:#fff;border:1px solid #5e72e4;border:1px solid var(--primary);border-radius:.25rem;outline:0;background-image:none;box-shadow:none;border-top-left-radius:0;border-bottom-left-radius:0}.cbi-dynlist>.add-item:not([ondrop])>input{overflow:hidden;width:100%;min-width:15rem;white-space:nowrap;text-overflow:ellipsis}.cbi-dynlist>.add-item[ondrop]>input{min-width:13rem}.cbi-dynlist,.cbi-dropdown{position:relative;display:inline-flex;padding:.2rem .2rem}.cbi-dropdown[placeholder*="select"]{max-width:25rem;height:auto;margin-top:-3px}.cbi-dropdown>ul{display:flex;overflow-x:hidden;overflow-y:auto;width:100%;margin:0 !important;padding:0;list-style:none;outline:0}.cbi-dropdown>ul.preview{display:none}.cbi-button-apply>ul.preview{display:none}.cbi-button-apply>ul.preview li{color:#fff}.cbi-button-apply>ul:first-child li{color:#fff}.cbi-dropdown>.open{flex-basis:15px}.cbi-dropdown>.open,.cbi-dropdown>.more{font-size:1rem;font-weight:900;line-height:2;display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;justify-content:center;padding:0 .25em;cursor:default;text-align:center;outline:0}.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder]{font-weight:bold;display:none;color:#777;text-shadow:1px 1px 0 #fff}.cbi-dropdown>ul>li{display:none;overflow:hidden;align-items:center;align-self:center;flex-grow:1;flex-shrink:1;min-height:20px;padding:.25em;white-space:nowrap;text-overflow:ellipsis}.cbi-dropdown>ul>li .hide-open{display:initial}.cbi-dropdown>ul>li .hide-close{display:none}.cbi-dropdown>ul>li[display]:not([display="0"]){border-left:thin solid #ccc}.cbi-dropdown[empty]>ul{max-width:1px}.cbi-dropdown>ul>li>form{display:none;margin:0;padding:0;pointer-events:none}.cbi-dropdown>ul>li img{margin-right:.25em;vertical-align:middle}.cbi-dropdown>ul>li>form>input[type="checkbox"]{height:auto;margin:0}.cbi-dropdown>ul>li input[type="text"]{height:20px}.cbi-dropdown[open]>ul.dropdown{position:absolute;z-index:1100;display:block;width:auto;min-width:100%;max-width:none;max-height:200px !important;border:0 solid #918e8c;background:#ffffff;box-shadow:0 0 4px #918e8c;border-bottom-left-radius:.35rem;border-bottom-right-radius:.35rem;color:var(--main-menu-color);margin-left:-0.2rem !important}.cbi-dropdown[open]>ul.dropdown li{color:#000}.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more{display:flex;align-items:center;flex-grow:1}.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form{display:block}.cbi-dropdown[open]>ul.dropdown>li .hide-open{display:none}.cbi-dropdown[open]>ul.dropdown>li .hide-close{display:initial}.cbi-dropdown[open]>ul.dropdown>li{border-bottom:thin solid #ccc;padding:.5rem .8rem}.cbi-dropdown[open]>ul.dropdown>li label{margin-left:.5rem}.cbi-dropdown[open]>ul.dropdown>li[selected]{background:#dce1fe}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#dce1fe;outline:none}.cbi-dropdown[open]>ul.dropdown>li:last-child{margin-bottom:0;border-bottom:0}.cbi-dropdown[open]>ul.dropdown>li[unselectable]{opacity:.7}.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child{width:100%}.cbi-dropdown[disabled]{pointer-events:none;opacity:.6}.cbi-dropdown .zonebadge{width:100%}.cbi-dropdown[open] .zonebadge{width:auto}.cbi-progressbar{position:relative;min-width:11rem;height:1.5rem;margin:0 0;border:thin solid #999;background:#eee;border-radius:4px;overflow:hidden}.cbi-progressbar>div{width:0;height:100%;transition:width .25s ease-in;background:#5bc0de;background:var(--bar-bg)}.cbi-progressbar::after{font-family:monospace;font-size:1em;font-weight:bold;font-size-adjust:.38;line-height:1.5rem;position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;content:attr(title);text-align:center;white-space:pre;text-overflow:ellipsis}#modal_overlay{position:fixed;z-index:900;top:0;right:10000px;bottom:0;left:-10000px;overflow-y:scroll;transition:opacity .125s ease-in;opacity:0;background:rgba(0,0,0,0.7);-webkit-overflow-scrolling:touch}.modal{display:flex;align-items:center;flex-wrap:wrap;width:90%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>*{line-height:normal;flex-basis:100%;margin-bottom:.5em;max-width:100%}.modal>pre,.modal>textarea{font-size:1rem;font-size-adjust:.35;overflow:auto;margin-bottom:.5em;padding:8.5px;cursor:auto;white-space:pre-wrap;color:#eee;outline:0;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.modal>h4{margin:.5em 0}.modal ul{margin-left:2.2em}.modal li{list-style-type:square;color:#808080}.modal p{word-break:break-word}.modal .label{font-size:.6rem;font-weight:normal;padding:.1rem .3rem;padding-bottom:0;cursor:default;border-radius:0}.modal .label.warning{background-color:#f0ad4e !important}.modal .btn{padding:.45rem .8rem}.modal.cbi-modal{max-width:90%;max-height:none}body.modal-overlay-active{overflow:hidden;height:100vh}body.modal-overlay-active #modal_overlay{right:0;left:0;opacity:1}.spinning{position:relative;padding-left:32px !important}.spinning::before{position:absolute;top:0;bottom:0;left:.2em;width:32px;content:"";background:url(/luci-static/resources/icons/loading.gif) no-repeat center;background-size:16px}.hidden{display:none}.left,.left::before{text-align:left !important}.right,.right::before{text-align:right !important}.center,.center::before{text-align:center !important}.top{align-self:flex-start !important;vertical-align:top !important}.bottom{align-self:flex-end !important;vertical-align:bottom !important}.inline{display:inline}.cbi-page-actions{padding-top:1rem;text-align:right;justify-content:flex-end}.cbi-page-actions>form[method="post"]{display:inline-block}.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"]{flex:1 1 2em;text-align:center}.ifacebadge{display:inline-flex;gap:.2rem;padding:.5rem .8rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);border-radius:4px}td>.ifacebadge,.td>.ifacebadge{font-size:.8rem;background-color:#f0f0f0}.ifacebadge>em,.ifacebadge>img{display:inline-block;align-self:flex-start}.ifacebadge>img+img{margin:0 .2rem 0 0}.network-status-table{display:flex;flex-wrap:wrap}.network-status-table .ifacebox{flex-grow:1;border-radius:4px;overflow:hidden;margin:0 1.25rem 1rem 1.25rem}.network-status-table .ifacebox-body{display:flex;flex-direction:column;height:100%;gap:.5em}.network-status-table .ifacebox-body>span{flex:10 10 auto;height:100%}.network-status-table .ifacebox-body>div{display:flex;flex-wrap:wrap;gap:.5rem}.network-status-table .ifacebox-body .ifacebadge{align-items:center;flex:1 1 auto;min-width:220px;padding:.5em;background-color:#fff}.network-status-table .ifacebox-body .ifacebadge>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cbi-input-textarea{font-family:monospace;width:100%;font-size:.875rem;min-height:14rem;padding:.8rem;color:#000}#syslog{font-size:small;line-height:1.25;overflow-y:hidden;width:100%;min-height:15rem;padding:1rem;resize:none;color:#242424;border:0;border-radius:.375rem;background-color:#ffffff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}#syslog:focus{outline:0}.uci-change-list{font-family:monospace}.uci-change-list ins,.uci-change-legend-label ins{display:block;padding:2px;text-decoration:none;border:thin solid #0f0;background-color:#cfc}.uci-change-list del,.uci-change-legend-label del{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #f00;background-color:#fcc}.uci-change-list var,.uci-change-legend-label var{font-style:normal;display:block;padding:2px;text-decoration:none;border:thin solid #ccc;background-color:#eee}.uci-change-list var ins,.uci-change-list var del{font-style:normal;padding:0;white-space:pre;border:0}.uci-change-legend{padding:5px}.uci-change-legend-label{float:left;width:150px}.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var{display:block;float:left;width:10px;height:10px;margin-right:4px}.uci-change-legend-label var ins,.uci-change-legend-label var del{line-height:.4;border:0}.uci-change-list var,.uci-change-list del,.uci-change-list ins{padding:.5rem}#iwsvg,#iwsvg2,#bwsvg{border:thin solid #d4d4d4 !important}#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg{border-top:0 !important}.ifacebox{line-height:1.25;display:inline-flex;overflow:hidden;flex-direction:column;border-radius:4px;min-width:100px;border-bottom:thin solid #ccc;background-color:#f9f9f9;box-shadow:inset 0 1px 0 rgba(255,255,255,0.4),0 1px 2px rgba(0,0,0,0.2)}.ifacebox-head{padding:.25em;background:#eee}.ifacebox-head.active{background:#5e72e4;background:var(--primary)}.ifacebox-head.active *{color:#fff;color:var(--white)}.ifacebox-body{padding:.875rem 1rem;line-height:1.6em}.cbi-image-button{margin-left:.5rem}.zonebadge{display:inline-block;padding:.2rem .5rem;border-radius:4px}.zonebadge .ifacebadge{margin:.1rem .2rem;padding:.2rem .3rem;border:thin solid #6c6c6c}.zonebadge>input[type="text"]{min-width:10rem;margin-top:.3rem;padding:.16rem 1rem}.zonebadge>em,.zonebadge>strong{display:inline-block;margin:0 .2rem}.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio{margin-top:.1rem}.cbi-value-field>ul>li{display:flex}.cbi-value-field>ul>li>label{margin-top:.5rem}.cbi-value-field>ul>li .ifacebadge{margin-top:-0.5rem;margin-left:.4rem;background-color:#eee}.cbi-section-table-row>.cbi-value-field .cbi-dropdown{min-width:3rem}.cbi-section-create{display:inline-flex;align-items:center;margin:.25rem 1.25rem}.cbi-section-create>*{margin:.5rem 0}.cbi-section-remove{padding:.5rem}div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var{font-style:italic;color:#0069d6}.cbi-optionals{padding:1rem 1rem 0 1rem;border-top:thin solid #ccc}.cbi-dropdown-container{position:relative}.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label{cursor:help !important}.cbi-tooltip{position:absolute;z-index:1000;left:-1000px;padding:2px 5px;transition:opacity .25s ease-out;white-space:pre;pointer-events:none;opacity:0;border-radius:3px;background:#fff;box-shadow:0 0 2px #444}.cbi-tooltip-container:hover .cbi-tooltip{left:auto;transition:opacity .25s ease-in;opacity:1}.zonebadge .cbi-tooltip{margin:-1.5rem 0 0 -0.5rem;padding:.25rem;background:inherit}.zonebadge-empty{color:#404040;background:repeating-linear-gradient(45deg, rgba(204,204,204,0.5), rgba(204,204,204,0.5) 5px, rgba(255,255,255,0.5) 5px, rgba(255,255,255,0.5) 10px)}.zone-forwards{display:flex;min-width:10rem}.zone-forwards>*{flex:1 1 45%}.zone-forwards>span{flex-basis:10%;padding:0 .25rem;text-align:center}.zone-forwards .zone-src,.zone-forwards .zone-dest{display:flex;flex-direction:column}.label{font-size:.8rem;font-weight:bold;padding:.3rem .8rem;white-space:nowrap;text-decoration:none;text-transform:uppercase;color:#fff !important;border-radius:3px;background-color:#bfbfbf;text-shadow:none}label>input[type="checkbox"],label>input[type="radio"]{position:relative;top:.4rem;right:.2rem;margin:0;vertical-align:bottom}label[data-index][data-depends]{padding-right:2em}.showSide{display:none}.darkMask{position:fixed;z-index:99;display:none;width:100%;height:100%;content:"";top:0;background-color:rgba(0,0,0,0.56);transition:all .2s}.darkMask.active{display:block}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1.2rem;font-size-adjust:.35;line-height:normal;display:block;overflow-y:hidden;width:100%;padding:8.5px;white-space:pre;color:#eee;background-color:#101010;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}[data-page="admin-network-diagnostics"] .table{box-shadow:none}input[name="ping"],input[name="traceroute"],input[name="nslookup"]{width:80%}.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3){white-space:normal}[data-page="admin-system-reboot"] p{padding-left:1.5rem}[data-page="admin-system-reboot"] .cbi-button{background:#fb6340 !important}[data-page="admin-system-reboot"] p>span{position:relative;top:.1rem;left:1rem}[data-page="admin-vpn-passwall"] h4{background:transparent}#cbi-samba [data-tab="template"] .cbi-value-field{display:block}#cbi-samba [data-tab="template"] .cbi-value-title{width:auto;padding-bottom:.6rem}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{margin-left:0;color:#32325d;color:var(--gray-dark)}[data-page="admin-system-opkg"] h2{margin-left:0;color:#32325d;color:var(--gray-dark)}.controls{margin:.5em 1rem 1em 1rem !important}.controls>*>.btn:not([aria-label$="page"]){flex-grow:initial !important;margin-top:.25rem}.controls>#pager>.btn[aria-label$="page"]{font-size:1.4rem;font-weight:bold}.controls>*>label{margin-bottom:.2rem}[data-page="admin-system-opkg"] div.btn{line-height:3;display:inline;padding:.3rem .6rem}[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{margin-top:2rem;padding-top:.1rem}[data-page="admin-system-opkg"] #maincontent>.container{margin:0 1.25rem 1rem 1.25rem;margin-bottom:1rem}.td.version,.td.size{white-space:normal !important;word-break:break-word}.cbi-tabmenu+.cbi-section{margin-top:0}[data-page="admin-system-crontab"] #view p{margin-bottom:1rem}[data-page="admin-system-flash"] .cbi-value{padding:0}[data-page="admin-system-flash"] .cbi-section .cbi-section{margin-top:0}[data-page="admin-system-flash"] .cbi-map-tabbed{border-radius:.375rem}[data-page="admin-system-flash"] legend{display:block !important;font-size:1.2rem;width:100%;display:block;margin-bottom:0;padding:1rem 0 1rem 1.5rem;border-bottom:1px solid rgba(0,0,0,0.05);line-height:1.5;margin-bottom:0rem;letter-spacing:.1rem;color:#32325d;font-weight:bold}[data-page="admin-system-flash"] .cbi-section-descr{font-weight:600;padding:1rem 0 1rem 1.5rem;color:#525f7f}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important}#cbi-wireless>#wifi_assoclist_table>.tr{box-shadow:inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td{right:33px;bottom:33px;left:33px;border-top:thin solid #ddd !important}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles{box-shadow:inset 1px 0 0 #ddd,inset -1px 0 0 #ddd}#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th{border-bottom:thin solid #ddd;box-shadow:0 -1px 0 0 #ddd}#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"]{width:23rem}[data-page="admin-network-dhcp"] .cbi-value{padding:0}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 0 !important}#iptables{margin:0}.Firewall form{margin:2rem 2rem 0 0;padding:0;box-shadow:none}#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table *{font-size:small}#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"]{width:5rem}#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select{min-width:3.5rem}#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td{flex-basis:12%}#cbi-firewall-zone .table,#cbi-network-switch_vlan .table{display:block}#cbi-firewall-zone .td,#cbi-network-switch_vlan .td{width:100%}[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p{padding:0 1.5rem;margin-bottom:1rem}[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea{padding:1rem;border-radius:.375rem}#applyreboot-container{margin:2rem}#applyreboot-section{line-height:300%;margin:2rem}.OpenVPN a{line-height:initial !important}.commandbox{width:24% !important;margin:10px 0 0 10px !important;padding:.5rem 1rem;border-bottom:thin solid #ccc;background:#eee;box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.commandbox h3{line-height:normal !important;overflow:hidden;margin:6px 0 !important;white-space:nowrap;text-overflow:ellipsis}.commandbox div{left:auto !important}.commandbox code{position:absolute;overflow:hidden;max-width:60%;margin-left:4px;padding:2px 3px;white-space:nowrap;text-overflow:ellipsis}.commandbox code:hover{overflow-y:auto;max-height:50px;white-space:normal}.commandbox p:first-of-type{margin-top:-6px}.commandbox p:nth-of-type(2){margin-top:2px}[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide{display:none}#command-rc-output .alert-message{line-height:1.42857143;position:absolute;top:40px;right:32px;max-width:40%;margin:0;animation:anim-fade-in 1.5s forwards;word-break:break-word;opacity:0}@keyframes anim-fade-in{100%{opacity:1}}input[type="checkbox"]{appearance:none !important;-webkit-appearance:none !important;border:1px solid #dee2e6;width:16px !important;height:16px !important;padding:0;cursor:pointer;transition:all .2s;margin:1rem 0 0 0}input[type="checkbox"]:checked{border:1px solid #5e72e4;border:1px solid var(--primary);background-image:url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important;background-color:#5e72e4;background-color:var(--primary);background-size:70%;background-repeat:no-repeat;background-position:center}.fb-container .cbi-button{height:auto !important}#cbi-usb_printer-printer em{display:block;padding:1rem;text-align:center}pre.command-output{padding:1.5rem}[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"]{padding:1.5rem !important}[data-page="admin-nlbw-backup"] form{padding-left:1.5rem}[data-page="admin-status-iptables"] .right{margin-bottom:0 !important}@media all and (-ms-high-contrast:none){.main>.main-left>.nav>.slide>.menu::before{top:30.25%}.main>.main-left>.nav>li:last-child::before{top:20%}.showSide::before{top:-12px}}@media screen and (max-width:1600px){header>.fill>.container>#logo{margin:0 2.5rem 0 .5rem}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}.btn:not(button),.cbi-button{font-size:.8rem}.label{padding:.2rem .6rem}.cbi-value-title{width:15rem;padding-right:.6rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:18rem}#cbi-firewall-zone .cbi-input-select{min-width:9rem}.cbi-input-textarea{font-size:small}.node-admin-status>.main fieldset li>a{padding:.3rem .6rem}}@media screen and (max-width:1366px){header>.fill>.container{cursor:default}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}.tabs>li>a,.cbi-tabmenu>li>a{padding:.2rem .8rem}.panel-title{font-size:1.1rem;padding-bottom:1rem}table{font-size:.7rem !important;width:100% !important}.table .cbi-input-text{width:100%}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"]{min-width:16rem}#cbi-firewall-zone .cbi-input-select{min-width:4rem}.main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Logout"]{font-size:.9rem}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.7rem}#modal_overlay{top:0rem}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table){display:block}[data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table{overflow-y:visible}.commandbox{width:32% !important}.btn:not(button),.cbi-button{font-size:.8rem}}@media screen and (max-width:1152px){header>.fill>.container>#logo{display:none}header>.fill>.container>.brand{position:relative}html,.main{overflow-y:visible}.main>.loading>span{top:25%}.main-left{width:calc(0% + 13rem)}.main-right{width:calc(100% - 13rem)}body:not(.logged-in) .showSide{visibility:hidden;width:0;margin:0}.node-main-login>.main .cbi-value-title{text-align:left}.cbi-value-title{width:12rem;padding-right:1rem}.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"]{width:16rem;min-width:16rem}.cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2){width:13rem !important;min-width:13rem}#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code{font-size:1rem}.table{display:block}.Interfaces .table{overflow-x:hidden}#packages.table{display:grid}.tr{display:flex;flex-direction:row;flex-wrap:wrap}.Overview .table[width="100%"]>.tr{flex-wrap:nowrap}.tr.placeholder{border-bottom:thin solid #ddd}.tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td{border-top:0}.th,.td{display:inline-block;align-self:flex-start;flex:2 2 10%;text-overflow:ellipsis;word-wrap:break-word}.td select,.td input[type="text"]{width:100%;word-wrap:normal}.td [data-dynlist]>input,.td input.cbi-input-password{width:calc(100% - 1.5rem)}.td[data-type="button"],.td[data-type="fvalue"]{flex:1 1 12.5%;text-align:left}.th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell{flex-basis:auto;padding-top:1rem}.cbi-section-table-row{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.td.cbi-value-field,.cbi-section-table-cell{display:inline-block;flex:10 10 auto;flex-basis:50%;text-align:center}.td.cbi-section-actions{vertical-align:bottom}.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr{display:none}.tr[data-title]::before,.tr.cbi-section-table-titles.named::before{font-size:.9rem;display:block;flex:1 1 100%;border-bottom:thin solid rgba(0,0,0,0.26);background:#e9ecef}.td[data-title],[data-page^="admin-status-realtime"] .td[id]{text-align:left}.td[data-title]::before{display:block}.cbi-button+.cbi-button{margin-left:0}.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>*{margin:2.1px 3px}.Firewall form{position:static !important;margin:0 0 2rem 0;padding:2rem;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.Firewall form input{width:100% !important;margin:0;margin-top:1rem}.Firewall .center,.Firewall .center::before{text-align:left !important}.commandbox{width:100% !important;margin-left:0 !important}.btn:not(button),.cbi-button{font-size:.8rem}}@media screen and (max-width:768px){body{font-size:.8rem}.cbi-progressbar::after{font-size:.6rem}.main-left{position:fixed;z-index:100;width:0}.main-left.active{width:13rem}.main-right{width:100%}.main-right.active{overflow-y:hidden}.darkMask.active{display:block}.showSide{padding:.1rem;position:relative;z-index:99;display:inline-block !important}.showSide::before{font-family:'argon' !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\e20e";font-size:1.7rem}header>.fill>.container>.flex1>.brand{display:inline-block}.main>.main-left>.nav>.slide>.slide-menu>li>a{font-size:.8rem}}@media screen and (max-width:600px){.mobile-hide{display:none}#maincontent>.container{margin:0 1rem 1rem 1rem}.cbi-value-title{text-align:left}[data-page="admin-system-flash"] legend{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-section-descr{padding:1rem 0 1rem 1rem}[data-page="admin-system-flash"] .cbi-value{padding:0 1rem}[data-page="admin-network-dhcp"] [data-tab-active="true"]{padding:1rem 1rem !important}.cbi-dynlist p{padding:.5rem 1rem}body{overflow-x:hidden}.node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field{width:16rem}.node-main-login footer{display:none}.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar{width:0px;height:0px}.cbi-value-field,.cbi-value-description{display:block !important;padding-left:0 !important;padding-right:0 !important}[data-page="admin-system-admin-password"] .cbi-value-field{display:table-cell !important}.modal.cbi-modal{max-width:100%;max-height:none}.modal{display:flex;align-items:center;flex-wrap:wrap;width:100%;min-width:270px;max-width:600px;min-height:32px;margin:5em auto;padding:1em;border-radius:3px !important;background:#fff;box-shadow:0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12)}.cbi-dropdown[open]>ul.dropdown{left:.2rem !important;right:0 !important;margin-bottom:1rem}.login-page .login-container footer{display:none}}@media screen and (min-width:600px){::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar,::-webkit-scrollbar-corner{background:transparent}::-webkit-scrollbar-thumb{background:#9e9e9e}::-webkit-scrollbar-thumb:hover{background:#757575}::-webkit-scrollbar-thumb:active{background:#424242}}@media screen and (max-width:480px){.mobile-hide{display:none}.login-page .login-container{margin-left:0rem !important;width:100%}.login-page .login-container .login-form .form-login .input-group::before{color:#525461}.login-page .login-container .login-form .form-login .input-group input{color:#525461;border-bottom:white 1px solid;border-bottom:var(--white) 1px solid;border-radius:0}} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/css/dark.css b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css new file mode 100755 index 000000000..0a5759093 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/css/dark.css @@ -0,0 +1 @@ +body{background:#1e1e1e;color:#cccccc}.login-page .login-container .login-form{background-color:#1e1e1e;-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark));background-color:rgba(0, 0, 0, var(--blur-opacity-dark))}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent !important;color:#adb5bd;border-bottom:#adb5bd 1px solid !important;border-radius:0 !important;border-top:none !important;border-left:none !important;border-right:none !important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.login-page .login-container .login-form .form-login .cbi-button-apply:hover,.login-page .login-container .login-form .form-login .cbi-button-apply:focus{opacity:.9}header::after{background-color:#1e1e1e !important}.main .main-left{background-color:#333333 !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#cccccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#cccccc !important}.main .main-left .nav .slide .slide-menu li a{color:#cccccc}.main .main-left .nav .slide .slide-menu li a:hover{background:none !important}.main .main-left .nav .slide .menu.active{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#cccccc !important}.main .main-left .nav .slide .menu.active a::after{background-color:#cccccc !important}.main .main-left .nav li a{color:#cccccc !important}.main .main-left .nav li a:hover{background-color:#483d8b !important;background-color:var(--dark-primary) !important;color:#cccccc !important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526 !important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333333}h3{color:#ccc;border-bottom:0;background:#333333}a:-webkit-any-link{color:-webkit-link;cursor:pointer;color:#483d8b;color:var(--dark-primary)}input:-webkit-autofill{background-color:#3c3c3c !important}.cbi-value-field .cbi-input-apply,.cbi-button-apply,.cbi-button-edit{color:#fff !important;background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e !important}.cbi-map-descr{color:#ccc}.cbi-section{background:none;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.panel-title{color:#ccc;background-color:#333333;border-bottom:0px}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#swaptotal>div>div,#swapfree>div>div,#memfree>div>div,#membuff>div>div,#conns>div>div,#memtotal>div>div{background-color:#32325d !important}#swaptotal>div>div>div>small,#swapfree>div>div>div>small,#memfree>div>div>div>small,#membuff>div>div>div>small,#conns>div>div>div>small,#memtotal>div>div>div>small{color:#ccc !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999999 !important;background-color:transparent !important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#32325d !important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:black 1px solid !important}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666 !important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc;border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}h4{background-color:#1e1e1f}.cbi-progressbar{position:relative;min-width:170px;height:20px;margin:6px 0;border:thin solid #999;background:transparent;border-radius:.2rem;overflow:hidden}.cbi-progressbar div{background-color:#32325d !important}.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{background-color:#1e1e1f}.cbi-button{color:#ccc !important;background-color:#483d8b;background-color:var(--dark-primary)}.cbi-section-node{background:none;border-radius:0 0 .375rem .375rem;padding:0rem}abbr{color:#5e72e4}div>table>tbody>tr:nth-of-type(2n),div>.table>.tbody>.tr:nth-of-type(2n){background-color:#252526}#content_syslog{box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}#syslog{color:#ccc;background-color:#1e1e1e}#iwsvg,#iwsvg2,#bwsvg{overflow:hidden;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e !important}.tabs{background-color:#252526}.tabs>li[class~="active"]>a{color:#ccc}.tabs>li[class~="active"],.tabs>li:hover{border-bottom:.18751rem solid #483d8b;border-bottom:.18751rem solid var(--dark-primary);color:#ccc;background-color:#181819}.cbi-tabmenu>li>a,.tabs>li>a{color:#ccc}.cbi-tabmenu>li>a:hover,.tabs>li>a:hover{color:#ccc}.cbi-tabmenu>li{background:#2d2d2d}.cbi-tabmenu li[class~="cbi-tab"] a{color:#ccc}.cbi-tabmenu>li:hover{color:#ccc;background:#2d2d2d}.cbi-tabmenu>li[class~="cbi-tab"]{background-color:#181819}.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#252526}.cbi-value-title{color:#ccc}select,input{color:#ccc;background-color:transparent !important;border:1px solid #252526;box-shadow:none}select:not([multiple="multiple"]):focus,input:focus{border-color:#483d8b !important;border-color:var(--dark-primary) !important;outline:0}select{background-color:#1e1e1e !important}#cbi-dropbear h2,#cbi-dropbear .cbi-map-descr,#cbi-dropbear .cbi-map-descr abbr,#cbi-rc h2,#cbi-rc .cbi-map-descr,#cbi-distfeedconf h2,#cbi-distfeedconf .cbi-map-descr,#cbi-customfeedconf h2,#cbi-customfeedconf .cbi-map-descr,#cbi-download h2,#cbi-filelist h2{color:#ccc !important}.cbi-value-field>ul>li .ifacebadge{background-color:#3c3c3c}.cbi-section-descr{color:#ccc}.cbi-input-textarea{background-color:#1e1e1e;color:#ccc}.cbi-section-remove:nth-of-type(2n),.cbi-section-node:nth-of-type(2n){background-color:#1e1e1e}.node-system-packages>.main table tr td:nth-last-child(1){color:#ccc}.cbi-section-node .cbi-value{padding:1rem 1rem .3rem 1rem}.ifacebox{background-color:none;border:1px solid #1e1e1e}.ifacebox-head{color:#666}.ifacebox-body{background-color:#333}.zonebadge strong{color:#333}.zonebadge>.ifacebadge{background-color:#3c3c3c}div.cbi-value var,td.cbi-value-field var{color:#5e72e4}#diag-rc-output>pre{color:#ccc;background-color:#1e1e1e}.node-services-vssr .block{background-color:#3c3c3c !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.node-services-vssr .block h4{color:#ccc !important}.node-services-vssr .status-bar{color:#ccc;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e}.node-services-vssr .cbi-section-table-row{color:#ccc;background-color:#3c3c3c !important;box-shadow:0 0 5px 0 rgba(0,0,0,0.35)}.node-services-vssr .cbi-section-table-row.fast{background:#483d8b !important;background:var(--dark-primary) !important;color:#fff}.node-services-vssr .ssr-button{color:#ccc}.node-services-vssr .incon:nth-child(2){border-right:#1e1e1e 1px solid}#xhr_poll_status>.label.success{color:#ccc !important;background-color:darkolivegreen !important}.notice{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.cbi-input-find,.cbi-input-save,.cbi-button-add,.cbi-button-save,.cbi-button-find,.cbi-input-reload,.cbi-button-reload{color:#fff !important;background:darkolivegreen !important;border-color:darkolivegreen !important}.cbi-button-reset,.cbi-input-remove{color:#fff !important;background-color:darkorange !important;border-color:darkorange !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit.important,.cbi-button-apply.important,.cbi-button-reload.important,.cbi-button-action.important{border:1px #483d8b solid !important;border:1px var(--dark-primary) solid !important}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:normal;color:#fff;border:thin solid darkorange !important;background-color:darkorange !important}fieldset[id^="cbi-apply-"]{background-color:#333333}#detail-bubble>div{border:1px solid #ccc;border-radius:2px;padding:5px;background:#252525}.ifacebox-head.active{background-color:#32325d !important}header .fill .status span[data-style="active"]{color:#ccc !important;background-color:darkolivegreen !important}#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{background-color:#252526;border-bottom:black 1px solid !important}.network-status-table .ifacebox-body .ifacebadge{background-color:#252526;border-bottom:0;box-shadow:none}td>.ifacebadge,.td>.ifacebadge{background-color:#483d8b;background-color:var(--dark-primary);border:0}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"]{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{background:#1e1e1e !important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{background:transparent !important}[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr{color:#ccc}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal !important;background-color:darkseagreen}[data-page="admin-system-flash"] .modal .alert-message{background-color:transparent !important}[data-page="admin-system-flash"] .modal .danger{border:thin solid darkorange !important;background-color:darkorange !important}.cbi-value input[type="password"]+.cbi-button-neutral{background-color:#483d8b !important;background-color:var(--dark-primary) !important}.btn,button,select,input,.cbi-dropdown{border:1px solid #3c3c3c !important}.cbi-dropdown .preview{color:#ccc}.cbi-section-table-row{background-color:#1e1e1e !important}.modal{background-color:#1e1e1e}.cbi-button-positive{color:#fff !important;background-color:darkolivegreen !important}[data-page="admin-system-flash"] legend{color:#ccc}.logout:before{color:#adb5bd !important}.cbi-dropdown[open]{border-color:#483d8b !important;border-color:var(--dark-primary) !important}.cbi-dropdown[open]>ul.dropdown{background:#252526 !important;color:#ccc !important;box-shadow:none;border:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown li{color:#ccc;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li[selected]{background-color:#483d8b !important;background-color:var(--dark-primary) !important;border-bottom:1px solid #3c3c3c !important}.cbi-dropdown[open]>ul.dropdown>li.focus{background:#483d8b;background:var(--dark-primary);outline:none}.ifacebadge{background-color:#333333}.cbi-dynlist>.item>span{border:1px solid #3c3c3c !important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{background:#483d8b !important;background:var(--dark-primary) !important}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{background:#483d8b;background:var(--dark-primary)}[data-page="admin-system-opkg"] h2{color:#ccc !important}@media screen and (max-width:480px){.node-status-iptables>.main div>.cbi-map>form{background-color:#1e1e1e;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/favicon.ico b/luci-theme-argon/htdocs/luci-static/argon/favicon.ico new file mode 100755 index 000000000..461133680 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/favicon.ico differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot new file mode 100755 index 000000000..efce636a8 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.eot differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg new file mode 100755 index 000000000..c555b7594 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.svg @@ -0,0 +1,1191 @@ + + + + +Created by FontForge 20090622 at Tue Jul 23 03:29:07 2019 + By deploy user +TypoGraphica ©Sharkshock Productions 2015. All Rights Reserved + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf new file mode 100755 index 000000000..e11f89a0f Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.ttf differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff new file mode 100755 index 000000000..fef38ca00 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/TypoGraphica.woff differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot new file mode 100755 index 000000000..e28f6db55 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.eot differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg new file mode 100755 index 000000000..1e12b5f6a --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.svg @@ -0,0 +1,38 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf new file mode 100755 index 000000000..3d062dcf2 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.ttf differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff new file mode 100755 index 000000000..ef1e9c2c4 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/fonts/argon.woff differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png b/luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png new file mode 100755 index 000000000..7c17009d3 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/android-icon-192x192.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png new file mode 100755 index 000000000..5308d66b7 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-144x144.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png new file mode 100755 index 000000000..f18dfa49c Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-60x60.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png new file mode 100755 index 000000000..bb3e24233 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/apple-icon-72x72.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg new file mode 100755 index 000000000..ebeca958b --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/arrow.svg @@ -0,0 +1 @@ + diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml b/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml new file mode 100755 index 000000000..c55414822 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png new file mode 100755 index 000000000..308843a09 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-16x16.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png new file mode 100755 index 000000000..bfcd09707 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-32x32.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-96x96.png b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-96x96.png new file mode 100755 index 000000000..d0fe1ed09 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/favicon-96x96.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/manifest.json b/luci-theme-argon/htdocs/luci-static/argon/icon/manifest.json new file mode 100755 index 000000000..2817bc813 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "Openwrt", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/ms-icon-144x144.png b/luci-theme-argon/htdocs/luci-static/argon/icon/ms-icon-144x144.png new file mode 100755 index 000000000..5308d66b7 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/icon/ms-icon-144x144.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg b/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg new file mode 100755 index 000000000..6ddd3b3ed --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/icon/spinner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg b/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg new file mode 100755 index 000000000..654e2fe24 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/img/argon.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg b/luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg new file mode 100755 index 000000000..26a52a535 Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/img/bg1.jpg differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/blank.png b/luci-theme-argon/htdocs/luci-static/argon/img/blank.png new file mode 100755 index 000000000..9f4100e6e Binary files /dev/null and b/luci-theme-argon/htdocs/luci-static/argon/img/blank.png differ diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg new file mode 100755 index 000000000..f01ad5c79 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/img/volume_high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg b/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg new file mode 100755 index 000000000..0598d584e --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/img/volume_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js b/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js new file mode 100755 index 000000000..b0614034a --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/jerrykuku/luci-theme-argon/issues + * + * luci-theme-material: + * Copyright 2015 Lutty Yang + * https://github.com/LuttyYang/luci-theme-material/ + * + * Agron Theme + * https://demos.creative-tim.com/argon-dashboard/index.html + * + * Login background + * https://unsplash.com/ + * Font generate by Icomoon + * + * Licensed to the public under the Apache License 2.0 + */ + +/* + * Include base and custom css + */ +@import url("pure-min.less"); +@import url("fonts.less"); + + +:root { + --primary: #5e72e4; + --dark-primary: #483d8b; + --main-color: #09c; + --header-bg: #09c; + --header-color: #fff; + --bar-bg: #5e72e4; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #d4d4d4; + --submenu-bg-hover-active: #09c; + --blue: #5e72e4; + --indigo: #5603ad; + --purple: #8965e0; + --pink: #f3a4b5; + --red: #f5365c; + --orange: #fb6340; + --yellow: #ffd600; + --green: #2dce89; + --teal: #11cdef; + --cyan: #2bffc6; + --white: #fff; + --gray: #8898aa; + --gray-dark: #32325d; + --light: #ced4da; + --lighter: #e9ecef; + --secondary: #f7fafc; + --success: #2dce89; + --info: #11cdef; + --warning: #fb6340; + --danger: #f5365c; + --light: #adb5bd; + --dark: #212529; + --default: #172b4d; + --white: #fff; + --neutral: #fff; + --darker: black; + --background-color: #f4f5f7; + --login-form-bg-color: rgba(244, 245, 247, 0.8); + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --blur-radius: 10px; + --blur-opacity: 0.5; + --blur-radius-dark: 10px; + --blur-opacity-dark: 0.5; + --font-family-sans-serif: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + --font-family-normal: Open Sans, PingFangSC-Regular, Microsoft Yahei, WenQuanYi Micro Hei, "Helvetica Neue", Helvetica, Hiragino Sans GB, sans-serif; +} + +html, +body { + margin: 0px; + padding: 0px; + height: 100%; + font-size: 16px; + font-family: "Google Sans", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans-serif", "Helvetica Neue", "Helvetica", "Hiragino Sans GB"; + font-family: var(--font-family-sans-serif); +} + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + font-size: 0.875rem; + background-color: #f4f5f7; + + background-color: var(--background-color); + color: #32325d; + color: var(--gray-dark); + -webkit-tap-highlight-color: transparent; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +::selection { + background-color: #5e72e4; + background-color: var(--primary); + color: #ffffff; + color: var(--white); +} + +a:link, +a:visited, +a:active { + color: #5e72e4; + color: var(--primary); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +li { + list-style-type: none; +} + + + +.table { + position: relative; + display: table; +} + +.tr { + display: table-row; +} + +.thead { + display: table-header-group; +} + +.tbody { + display: table-row-group; +} + +.tfoot { + display: table-footer-group; +} + +.td, +.th { + line-height: normal; + display: table-cell; + padding: .5em; + text-align: center; + vertical-align: middle; +} + +.th { + font-weight: bold; + white-space: nowrap; +} + +.tr.placeholder { + height: 4em; +} + +.tr.placeholder>.td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 0.4rem 0 !important; + text-align: center !important; + background: inherit; +} + +.td[width="33%"] { + padding: 1.1em 1.5rem; +} + +.table[width="33%"], +.th[width="33%"], +.td[width="33%"] { + width: 33%; +} + +.table[width="100%"], +.th[width="100%"], +.td[width="100%"] { + width: 100%; +} + +.col-1 { + flex: 1 1 30px !important; +} + +.col-2 { + flex: 2 2 60px !important; +} + +.col-3 { + flex: 3 3 90px !important; +} + +.col-4 { + flex: 4 4 120px !important; +} + +.col-5 { + flex: 5 5 150px !important; +} + +.col-6 { + flex: 6 6 180px !important; +} + +.col-7 { + flex: 7 7 210px !important; +} + +.col-8 { + flex: 8 8 240px !important; +} + +.col-9 { + flex: 9 9 270px !important; +} + +.col-10 { + flex: 10 10 300px !important; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; + +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: inherit; + font-weight: normal; + line-height: 1.1 !important; + color: inherit; +} + + + +select { + padding: .36rem .8rem; + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; +} + +.btn, +button, +select, +input, +.cbi-dropdown { + line-height: 1.5rem; + padding: .5rem .75rem; + margin: 0.25rem 0.1rem; + color: #8898aa; + border: 1px solid #dee2e6; + + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + transition: box-shadow .15s ease; +} + +select, +.cbi-dropdown { + width: inherit; + cursor: default; +} + +select:not([multiple="multiple"]):focus, +input:not(.cbi-button):focus, +.cbi-dropdown:focus { + border-color: #5e72e4; + border-color: var(--primary); + box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1); +} + +.cbi-dropdown, +select[multiple="multiple"] { + height: auto; +} + +pre { + overflow: auto; +} + +code { + font-size: 1rem; + font-size-adjust: .35; + padding: 1px 3px; + color: #101010; + border-radius: 2px; + background: #ddd; +} + +abbr { + cursor: help; + text-decoration: underline; + color: #5e72e4; + color: var(--primary); +} + +hr { + margin: 1rem 0; + opacity: .1; + border-color: #eee; +} + + + + +/*********************** +* +* Login Page +* +***************************/ + +.login-page { + height: 100%; + + .video { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #000; + background-color: var(--darker); + overflow: hidden; + + video { + width: 100%; + height: auto; + } + } + + .volume-control { + position: fixed; + right: 1rem; + top: 1rem; + width: 1.5rem; + height: 1.5rem; + z-index: 5000; + cursor: pointer; + background-size: contain; + background-image: url(../img/volume_high.svg); + + &.mute { + background-image: url(../img/volume_off.svg); + } + } + + .main-bg { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background-image: url(../img/blank.png); + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all 0.5s; + } + + .login-container { + height: 100%; + margin-left: 4.5rem; + position: absolute; + top: 0px; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 100%; + z-index: 2; + width: 420px; + box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 35px -5px; + margin-left: 5%; + background: transparent; + + .login-form { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 100%; + max-width: 420px; + background-color: #fff; + background-color: var(--white); + -webkit-backdrop-filter: blur(var(--blur-radius)); + backdrop-filter: blur(var(--blur-radius)); + background-color: rgba(244, 245, 247, var(--blur-opacity)); + + .brand { + display: flex; + -webkit-box-align: center; + align-items: center; + margin: 50px auto 100px 50px; + color: #525461; + color: var(--default); + + .icon { + width: 50px; + height: auto; + margin-right: 25px; + } + + .brand-text { + font-size: 1.25rem; + font-weight: 700; + font-family: "TypoGraphica"; + + } + + &:hover { + text-decoration: none; + } + } + + .form-login { + width: 100%; + padding: 20px 50px; + box-sizing: border-box; + + .errorbox { + text-align: center; + color: #fb6340; + color: var(--warning); + padding-bottom: 2rem; + } + + .input-group { + margin-bottom: 1.25rem; + position: relative; + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #525461; + color: var(--default); + font-size: 1.5rem; + position: absolute; + z-index: 100; + left: 10px; + top: 10px; + } + + .border { + position: absolute; + width: 100%; + height: 1px; + bottom: 0; + border-bottom: 1px #5e72e4 solid; + border-bottom: 1px var(--primary) solid; + transform: scaleX(0); + transition: transform 0.3s; + } + + input { + font-size: 1rem; + line-height: 1.5em; + display: block; + width: 100%; + padding: .5rem .75rem 0.5rem 3rem; + margin: 0.825rem 0; + box-sizing: border-box; + transition: all .3s cubic-bezier(.68, -.55, .265, 1.55); + color: #525461; + color: var(--default); + border: 0; + border-radius: 0; + border-bottom: 1px solid #fff; + border-bottom: 1px solid var(--white); + background-color: transparent; + background-clip: padding-box; + box-shadow: 0 3px 2px rgba(233, 236, 239, .05); + outline: none; + + &:focus+.border { + transform: scaleX(1); + } + } + + .cbi-input-password { + margin-bottom: 2rem; + position: relative; + } + } + + .user-icon::before { + content: "\e971"; + } + + .pass-icon::before { + content: "\e910"; + + } + } + + .cbi-button-apply { + width: 100% !important; + box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 50px 0px; + font-weight: 600; + font-size: 15px; + color: #fff; + color: var(--white); + text-align: center; + width: 100%; + cursor: pointer; + min-height: 50px; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + border-radius: 6px; + outline: none; + border-width: initial; + border-style: none; + border-color: initial; + border-image: initial; + padding: 10px 0px; + margin: 30px 0px 100px; + transition: all 0.3s !important; + letter-spacing: 0.8rem; + + &:hover, + :focus { + opacity: 0.9; + } + } + } + + footer { + box-sizing: border-box; + width: 100%; + text-align: center; + line-height: 1.6rem; + display: flex; + justify-content: space-evenly; + margin-top: auto; + padding: 0px 0px 30px; + z-index: 10; + color: #525461; + color: var(--default); + position: absolute; + bottom: 0; + + .ftc { + position: absolute; + bottom: 30px; + width: 100%; + } + + .luci-link { + display: block; + } + } + } +} + + +header, +.main { + width: 100%; +} + + +footer { + font-size: .8rem; + overflow: hidden; + padding: 1rem; + text-align: right; + white-space: nowrap; + color: #aaa; +} + +footer>a { + text-decoration: none; + color: #aaa; +} + +small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; +} + +.main { + position: relative; + top: 0; + bottom: 0; + overflow-y: auto; + height: 100%; +} + +.main-left { + position: fixed; + top: 0; + float: left; + overflow-x: auto; + width: 15%; + width: calc(0% + 15rem); + height: 100%; + background-color: #fff; + background-color: var(--menu-bg-color); + box-shadow: rgba(0, 0, 0, 0.75) 0px 0px 15px -5px; + overflow-x: auto; + position: fixed; + z-index: 100; + + + .sidenav-header { + padding: 1.5rem .5rem; + text-align: center; + + .brand { + font-size: 1.8rem; + color: #5e72e4; + color: var(--primary); + font-family: "TypoGraphica"; + text-decoration: none; + text-align: center; + cursor: default; + vertical-align: text-bottom; + } + } + + &::-webkit-scrollbar { + width: 5px; + height: 1px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } +} + +.main-right { + float: right; + width: 85%; + width: calc(100% - 15rem); + height: 100%; + transition: all 0.2s; +} + +.main-right>#maincontent { + position: relative; + z-index: 50; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.nowrap:not(.td) { + white-space: nowrap; +} + +[disabled="disabled"] { + pointer-events: none; +} + +header { + color: #fff; + color: var(--header-color); + padding: 0; + position: relative; + + &.bg-primary { + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + } + + &::after { + content: ""; + position: absolute; + height: 2rem; + width: 100%; + background-color: #5e72e4 !important; + background-color: var(--primary) !important; + } + + .fill { + padding: 0.8rem 0; + border-bottom: 0px solid rgba(255, 255, 255, .08) !important; + display: flex; + + .container { + height: 2rem; + padding: 0 1.25rem; + display: flex; + align-items: center; + width: 100%; + + .flex1 { + flex: 1; + + .showSide { + display: none; + color: #fff; + font-size: 1.4rem; + + &:hover { + text-decoration: none; + } + } + + .brand { + font-size: 1.5rem; + color: #fff; + font-family: "TypoGraphica"; + text-decoration: none; + padding-left: 1rem; + cursor: default; + vertical-align: text-bottom; + display: none; + } + } + + + .pull-right { + float: right; + margin-top: 0rem; + display: flex; + } + } + + .status { + span{ + display: inline-block; + font-size: 0.8rem; + font-weight: bold; + padding: 0.3rem 0.8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + text-shadow: none; + border-radius: 4px; + cursor: pointer; + transition: all 0.3s; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + margin: 0 0.25rem; + &:last-child{ + margin-right: 0; + } + } + + span[data-indicator="poll-status"] { + color: #32325d; + background-color: #fff; + } + + span[data-style="active"] { + + background-color: var(--green); + + } + + span[data-style="inactive"] { + color: #ffffff !important; + background-color: #32325d; + + } + } + } +} + + + +#xhr_poll_status { + display: flex; + margin-left: 0.5rem; + + * { + color: #fff; + } +} + +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + border: 0 !important; +} + +.danger { + background-color: #ff7d60 !important; +} + +.warning { + background-color: #f0e68c !important; +} + +.success { + background-color: #5cb85c !important; +} + +.notice { + background-color: #11cdef !important; + color: #fff; +} + +.error { + color: #f00; +} + +.alert, +.alert-message { + font-weight: bold; + margin-bottom: 1.25rem; + padding: 1rem 1.25rem; + border: 0; + border-radius: 0.375rem !important; + background-color: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + text-shadow: 1px 1px rgba(0, 0, 0, .1); + + &.error { + background-color: #ffd600; + } + + h4 { + padding: 0.25rem 0rem; + border-radius: 4px; + background-color: #ffd600; + } + + .btn { + height: auto; + } +} + +.alert-message>h4 { + font-size: 110%; + font-weight: bold; +} + +.alert-message>* { + margin: .5rem 0; +} + +.alert-message .btn { + padding: .3rem .6rem; +} + +.container .alert, +.container .alert-message { + margin-top: 0rem; +} + + +/* + * Main Menu + */ + +.main { + .main-left { + transition: all 0.2s; + + .nav { + margin-top: 0.5rem; + + >li>a:first-child { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .375rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + } + + li { + padding: 0.5rem 1rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0; + + a { + display: block; + color: #5f6368; + color: var(--menu-color); + } + + &.slide { + padding: 0; + + ul { + display: none; + overflow: hidden; + } + + &:hover { + background: none; + } + + .slide-menu { + margin: 0 0.5rem 0 2.5rem; + padding: 0rem 0.5rem; + + &.active { + display: block; + + } + + + li { + position: relative; + border-radius: 0.375rem; + margin: 0; + padding: 0.5rem 0rem; + background: none; + list-style: none; + + a { + text-decoration: none; + } + + &::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 0; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; + } + + &:hover { + background: none; + + &::after { + width: 100%; + } + } + + } + + .active { + background: none; + + color: var(--menu-color); + + a { + color: var(--menu-color); + } + + &::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background-color: #5e72e4; + background-color: var(--primary); + transition: all 0.2s; + } + + &:hover { + + background: none; + + &::after { + width: 100%; + } + } + } + } + + } + + + + .menu { + display: block; + margin: 0.1rem .5rem 0.1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .375rem; + text-decoration: none; + cursor: default; + font-size: 1rem; + transition: all 0.2s; + position: relative; + + &.active { + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + + &::after { + transform: rotate(90deg); + color: #fff !important; + } + } + + &:hover { + cursor: pointer; + color: #fff; + background: #5e72e4; + background: var(--primary); + + &::before { + color: #fff !important; + } + } + + &::before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e915"; + color: #5e72e4; + color: var(--primary); + } + + &::after { + position: absolute; + right: 0.5rem; + top: 0.8rem; + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: '\e90f'; + transition: all .15s ease; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all 0.3s; + } + } + + + .menu[data-title=Status]:before { + content: "\e906"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=System]:before { + content: "\e90a"; + color: #fb6340; + } + + .menu[data-title=Services]:before { + content: "\e909"; + color: #11cdef; + } + + .menu[data-title=NAS]:before { + content: "\e90c"; + color: #f3a4b5; + } + + .menu[data-title=VPN]:before { + content: "\e90b"; + color: #8965e0; + } + + .menu[data-title=Network]:before { + content: "\e908"; + color: #8965e0; + } + + .menu[data-title=Bandwidth_Monitor]:before { + content: "\e90d"; + color: #2dce89; + } + + .menu[data-title=Docker]:before { + content: "\e911"; + color: #6699ff; + } + + .menu[data-title=Statistics]:before { + content: "\e913"; + color: #8965e0; + } + + .menu[data-title=Control]:before { + content: "\e912"; + color: #5e72e4; + color: var(--primary); + } + + .menu[data-title=Asterisk]:before { + content: "\e914"; + color: #fb6340; + } + + a[data-title=Logout]:before { + content: "\e907"; + color: #adb5bd; + } + } + } + } +} + +.lg { + margin: 0; + padding: 0 !important; +} + +.logout { + display: block; + margin: 0.8rem .5rem 0.1rem 0.5rem; + padding: .675rem 0 .675rem 2.5rem; + border-radius: .375rem; + text-decoration: none; + font-size: 1rem; + transition: all 0.2s; + position: relative; +} + +.logout:before { + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: 0.8rem; + padding-top: 3px; + transition: all 0.3s; + content: "\e907"; + color: #32325d !important; +} + + +body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { + transition: transform .1s ease-in-out; +} + +body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { + transition: transform .2s ease-in-out; +} + +.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before { + display: none; +} + + + + +#maincontent>.container { + margin: 0 1.25rem 1rem 1.25rem; +} + +ul { + line-height: normal; +} + +li { + list-style-type: none; +} + +h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; +} + +h2 { + margin: 0 0 1rem 0; + font-size: 1.25rem; + letter-spacing: 0.1rem; + padding: 1rem 1.25rem; + color: #32325d; + border-radius: .375rem; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, .03); + font-weight: bold; + +} + +h3 { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); + border-radius: .375rem; + background: #fff; + font-weight: bold; +} + +h4 { + margin: 0; + padding: 0.75rem 1.25rem; + font-size: 0.7rem; + font-weight: 600; + color: #525f7f; + background-color: #e9ecef; + background-color: var(--lighter); + font-weight: bold; + + em { + padding: 0 0.5rem; + } + +} + +h5 { + font-size: 1rem; + margin: 2rem 0 0 0; + padding-bottom: 10px; +} + +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network>.cbi-section-node, +#cbi-wireless>.cbi-section-node, +#cbi-wireless>#wifi_assoclist_table, +[data-tab-title], +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent>.container { + font-family: inherit; + font-weight: normal; + font-style: normal; + line-height: normal; + min-width: inherit; + margin: 1.25rem 0; + padding: 0rem; + border: 0; + + border-radius: 0.375rem; + background-color: #fff; + box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .15) +} + +.cbi-modal .cbi-section, +.cbi-section .cbi-section { + padding: 0; + box-shadow: none; +} + +.cbi-modal .cbi-tabmenu { + margin-left: 0; +} + +.cbi-map-descr { + font-size: small; + line-height: 1.5; + padding: 0 1.25rem; +} + +.cbi-section-descr:not(:empty) { + + font-size: small; + line-height: 1.5; + padding: 1rem 1.25rem 0 1.25rem; +} + +.cbi-map-descr+fieldset { + margin-top: 1rem; +} + +.cbi-map-descr>abbr { + cursor: help; + text-decoration: underline; +} + +.cbi-section>legend { + display: none !important; +} + +fieldset>fieldset, +.cbi-section>.cbi-section { + margin: 0; + padding: 0; + border: 0; + box-shadow: none; +} + +.cbi-section>h3:first-child, +.panel-title { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + margin: 0; + margin-bottom: 0; + padding: 0.8755rem 1.25rem; + color: #32325d; + color: var(--gray-dark); + +} + +.cbi-section>h3:first-child, +.cbi-section>h4:first-child, +.cbi-section>p:first-child, +[data-tab-title]>h3:first-child, +[data-tab-title]>h4:first-child, +[data-tab-title]>p:first-child { + padding: 1rem 1.25rem; +} + +.cbi-section p { + padding: 1rem; +} + +.cbi-tblsection { + overflow-x: scroll; +} + +table { + border-spacing: 0; + border-collapse: collapse; +} + +table, +.table { + overflow-y: hidden; + width: 100%; + font-size: 90%; +} + +.table .table-titles th { + background-color: #e9ecef; + background-color: var(--lighter); +} + +table>tbody>tr>td, +table>tbody>tr>th, +table>tfoot>tr>td, +table>tfoot>tr>th, +table>thead>tr>td, +table>thead>tr>th, +.table>.tbody>.tr>.td, +.table>.tbody>.tr>.th, +.table>.tfoot>.tr>.td, +.table>.tfoot>.tr>.th, +.table>.thead>.tr>.td, +.table>.thead>.tr>.th, +.table>.tr>.td.cbi-value-field, +.table>.tr>.th.cbi-section-table-cell { + padding: .5rem; +} + +.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { + padding: .6rem; +} + +.cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; +} + +tr>td, +tr>th, +.tr>.td, +.tr>.th, +.cbi-section-table-row::before, +#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { + border-top: thin solid #ddd; + padding: 1.1em 1.25rem; +} + +#cbi-wireless .td, +#cbi-network .tr:first-child>.td, +.table[width="100%"]>.tr:first-child>.td, +[data-page="admin-network-diagnostics"] .tr>.td, +.tr.table-titles>.th, +.tr.cbi-section-table-titles>.th { + border-top: 0 !important; + background-color: #f6f9fc; + padding: 1.1em 1.25rem; + line-height: 1.3rem; +} + +.table[width="100%"]>.tr:first-child>.td { + margin: auto 0; +} + +.cbi-section-table-row { + margin-bottom: 1rem; + text-align: center !important; + background: #f4f4f4; +} + +.cbi-section-table-row:last-child { + margin-bottom: 0; +} + +.cbi-section-table-row>.cbi-value-field .cbi-dropdown, +.cbi-section-table-row>.cbi-value-field .cbi-input-select, +.cbi-section-table-row>.cbi-value-field .cbi-input-text, +.cbi-section-table-row>.cbi-value-field .cbi-input-password { + width: 100%; +} + +.cbi-section-table-row>.cbi-value-field .cbi-input-text, +.cbi-section-table-row>.cbi-value-field .cbi-input-password { + min-width: 80px; +} + +.cbi-section-table-row>.cbi-value-field [data-dynlist]>input, +.cbi-section-table-row>.cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); +} + +.cbi-section-table-row .td { + text-align: center !important; +} + +.control-group { + display: inline-flex; + width: 100%; + flex-wrap: wrap; + gap: 2px; +} + +div>table>tbody>tr:nth-of-type(2n), +div>.table>.tr:nth-of-type(2n) { + background-color: #f9f9f9; +} + +/* fix multiple table */ +table table, +.table .table, +.cbi-value-field table, +.cbi-value-field .table, +td>table>tbody>tr>td, +.td>.table>.tbody>.tr>.td, +.cbi-value-field>table>tbody>tr>td, +.cbi-value-field>.table>.tbody>.tr>.td { + border: 0; +} + +/* button style */ +.btn, +.cbi-button, +.item::after { + font-size: .8rem; + display: inline-block; + width: auto !important; + padding: 0.45rem .8rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: rgba(0, 0, 0, .87); + border: 0; + border-radius: .2rem; + background-color: #f0f0f0; + background-image: none; + -webkit-appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; +} + +.cbi-button-up, +.cbi-button-down { + font-size: 1.2rem; + display: inline-block; + min-width: 0; + padding: .2rem 1rem; + font-size: 0; + color: transparent !important; + background: url(../icon/arrow.svg) no-repeat center; + background-size: 12px 20px; +} + +.cbi-button-up { + transform: scaleY(-1); +} + +.cbi-button:not(select) { + -webkit-appearance: none !important; +} + + +.btn:hover, +.btn:focus, +.btn:active, +.cbi-button:hover, +.cbi-button:focus, +.cbi-button:active, +.item:hover::after, +.item:focus::after, +.item:active::after, +.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, +.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, +.cbi-page-actions .cbi-button-apply+.cbi-button-save:active { + text-decoration: none; + outline: 0; +} + +.btn:hover, +.btn:focus, +.cbi-button:hover, +.cbi-button:focus, +.item:hover::after, +.item:focus::after { + box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 2px rgba(0, 0, 0, .2); +} + +.btn:active, +.cbi-button:active, +.item:active::after { + box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23); +} + +.cbi-button-up:hover, +.cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 -2px 2px rgba(0, 0, 0, .2); +} + +.cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0, 0, 0, .19), 0 -6px 6px rgba(0, 0, 0, .23); +} + +.btn:disabled, +.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: .5; + box-shadow: none; +} + +/* gray */ +.alert-message [class="btn"], +.modal div[class="btn"], +.cbi-button-find, +.cbi-button-link, +.cbi-button-up, +.cbi-button-down, +.cbi-button-neutral, +.cbi-button[name="zero"], +.cbi-button[name="restart"], +.cbi-button[onclick="hide_empty(this)"] { + font-weight: bold; + color: #fff; + border: thin solid #8898aa; + background-color: #8898aa; +} + +/* dark blue */ +.btn.primary, +.cbi-page-actions .cbi-button-save, +.cbi-page-actions .cbi-button-apply+.cbi-button-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-positive, +.cbi-button-link, +.cbi-button[value="Enable"], +.cbi-button[value="Scan"], +.cbi-button[value^="Back"], +.cbi-button-neutral[onclick="handleConfig(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + background-color: #5e72e4; + background-color: var(--primary); + ; +} + +/* light blue */ +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit, +.cbi-button-apply, +.cbi-button-reload, +.cbi-button-action, +.cbi-button[value="Submit"], +.cbi-button[value="Upload"], +.cbi-button[value$="Apply"], +.cbi-button[onclick="addKey(event)"] { + font-weight: normal; + color: #fff !important; + border: thin solid #5e72e4; + border: thin solid var(--primary); + + background-color: #5e72e4; + background-color: var(--primary); +} + +/* red */ +.btn.danger, +.cbi-section-remove>.cbi-button, +.cbi-button-remove, +.cbi-button-reset, +.cbi-button-negative, +.cbi-button[value="Stop"], +.cbi-button[value="Kill"], +.cbi-button[onclick="reboot(this)"], +.cbi-button-neutral[value="Restart"] { + font-weight: normal; + color: #fff; + border: thin solid #f5365c; + border: thin solid var(--red); + background-color: #f5365c; + background-color: var(--red); +} + +/* yellow */ +.btn[value="Dismiss"], +.cbi-button[value="Terminate"], +.cbi-button[value="Reset"], +.cbi-button[value="Disabled"], +.cbi-button[onclick^="iface_reconnect"], +.cbi-button[onclick="handleReset(event)"], +.cbi-button-neutral[value="Disable"] { + font-weight: normal; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; +} + +/* green */ +.cbi-button-success, +.cbi-button-download, +.cbi-button[name="backup"], +.cbi-button[value="Download"], +.cbi-button[value="Save mtdblock"] { + font-weight: normal; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; +} + +.cbi-page-actions .cbi-button-link:first-child { + float: left; +} + +.a-to-btn { + text-decoration: none; +} + +.cbi-value-field .cbi-button-add { + font-weight: bold; + margin: 4px 0 4px 3px; + padding: 1px 6px; + display: flex; + align-items: center; +} + +.tabs { + margin: 0 0 1rem 0; + padding: 0 1rem; + background-color: #FFFFFF; + border-radius: 0.375rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, .03); + white-space: nowrap; + overflow-x: auto; + + &::-webkit-scrollbar { + width: 1px; + height: 5px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } + + li[class~="active"], + li:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; + border-radius: 0; + + a { + color: #5e72e4; + color: var(--primary); + } + } + + li { + font-size: 0.875rem; + display: inline-block; + padding: 0.875rem 0rem; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0; + transition: all 0.2s; + + a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; + } + + &:hover { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + } + } +} + + + + +.cbi-tabmenu { + color: white; + padding: 0.5rem 1rem 0 1rem; + white-space: nowrap; + overflow-x: auto; + + &::-webkit-scrollbar { + width: 1px; + height: 5px; + } + + &::-webkit-scrollbar-thumb { + background-color: #f6f9fc + } + + &::-webkit-scrollbar-track { + background-color: #fff; + } + + li { + background: #dce3e9; + display: inline-block; + font-size: 0.875rem; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + padding: 0.5rem 0rem; + border-bottom: 0.18751rem solid rgba(0, 0, 0, 0); + margin: 0 0.2rem; + + a { + text-decoration: none; + color: #404040; + padding: 0.5rem 0.8rem; + } + + &:hover { + cursor: pointer; + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; + + a { + color: #525f7f; + } + } + } + + li[class~="cbi-tab"] { + border-bottom: 0.18751rem solid #5e72e4; + border-bottom: 0.18751rem solid var(--primary); + color: #5e72e4; + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; + + a { + color: #5e72e4; + color: var(--primary); + } + } +} + +.cbi-tab-descr { + padding: 0.5rem 1.5rem; +} + +.cbi-section-node { + padding: 1rem 0; +} + +.cbi-section .cbi-section-remove:nth-of-type(2n), +.container>.cbi-section .cbi-section-node:nth-of-type(2n) { + background-color: #f9f9f9; +} + +[data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem 0rem !important; + + p { + margin-left: 1rem; + margin-bottom: 1rem; + } +} + + + +[data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity .25s ease-in; + margin: inherit !important; +} + + +.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3), +.cbi-section[id] .cbi-section-node:nth-of-type(4n+4) { + background-color: #f9f9f9; +} + +.cbi-section-node-tabbed { + margin-top: 0; + padding: 0; + border: 0 solid #d4d4d4; + border-radius: 0.375rem; +} + +.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { + background-color: #f9f9f9; +} + +.cbi-value-field, +.cbi-value-description { + line-height: 1.25; + display: table-cell; + + abbr { + color: #32325d; + color: var(--gray-dark); + } +} + +.cbi-value-description { + font-size: small; + padding: .5rem; + opacity: .5; +} + +.cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + padding-top: .25rem; + padding-right: 2rem; + text-align: right; + word-wrap: break-word; +} + +.cbi-value { + display: inline-block; + width: 100%; + padding: .35rem 1rem .2rem 1rem; + line-height: 2.4rem; +} + +.cbi-value ul { + line-height: 1.25; +} + +.cbi-value-field .cbi-dropdown, +.cbi-value-field .cbi-input-select, +.cbi-value input[type="text"], +.cbi-value input[type="password"] { + min-width: 18rem; +} + +.cbi-value input[type="password"] { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + margin-right: 0; +} + +.cbi-value input[type="password"]+.cbi-button-neutral { + height: 42px; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: 0; + border: 0; +} + +#cbi-firewall-zone .cbi-input-select, +#cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; +} + +#cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; +} + +.cbi-input-invalid { + color: #f5365c; + border-bottom-color: #f5365c; +} + +.cbi-section-error { + font-weight: bold; + line-height: 1.42857143; + margin: 18px; + padding: 6px; + border: thin solid #f5365c; + border-radius: 3px; + background-color: #fce6e6; +} + +.cbi-section-error ul { + margin: 0 0 0 20px; +} + +.cbi-section-error ul li { + font-weight: bold; + color: #f5365c; +} + +.td[data-title]::before { + font-weight: bold; + display: none; + padding: .25rem 0; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; +} + +.tr.placeholder .td[data-title]::before { + display: none; +} + +.tr[data-title]::before, +.tr.cbi-section-table-titles.named::before { + font-weight: bold; + display: table-cell; + align-self: center; + flex: 1 1 5%; + padding: .25rem; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; +} + +.cbi-rowstyle-1 { + background-color: #f9f9f9; +} + +.cbi-rowstyle-2 { + background-color: #eee; +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down, +body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: #fff !important; +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto !important; +} + +.td.cbi-section-actions { + text-align: right !important; + vertical-align: middle; +} + +.td.cbi-section-actions>* { + display: inline-flex; +} + +.td.cbi-section-actions>*>*, +.td.cbi-section-actions>*>form>* { + margin: 0 5px; + display: flex; + align-items: center; +} + +.td.cbi-section-actions>*>form { + display: inline-flex; + margin: 0; +} + +.cbi-checkbox { + margin: 0 0.25rem; +} + +/* lists */ +.cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; +} + +.cbi-dynlist>.item { + position: relative; + max-width: 25rem; + pointer-events: none; + color: #8898aa; + outline: 0; +} + +.cbi-dynlist[name="sshkeys"]>.item { + max-width: none; +} + +.cbi-dynlist>.item::after { + position: absolute; + width: 2.2rem !important; + height: calc(100% - 0.5rem - 2px); + right: 0; + bottom: 0; + content: "\00D7"; + pointer-events: auto; + background-color: var(--red); + font-weight: normal; + font-size: 1.2rem; + display: flex; + align-items: center; + justify-content: center; + line-height: 1.5rem; + padding: 0; + margin: 0.25rem 0.1rem 0.25rem 0; + color: #fff; + border: 1px solid #f5365c; + border-radius: 0.25rem; + outline: 0; + background-image: none; + box-shadow: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.cbi-dynlist>.item>span { + white-space: normal; + word-break: break-word; + line-height: 1.5rem; + padding: 0.5rem 0.5rem; + margin: 0.25rem 0.1rem; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + outline: 0; + background-image: none; + box-shadow: none; + display: block; + transition: box-shadow 0.15s ease; + box-sizing: border-box; + min-width: 15rem; +} + +.cbi-dynlist>.add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; +} + +.cbi-dynlist>.add-item input { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: 0; + border-right: none; +} + +.cbi-dynlist>.add-item .cbi-button-add { + font-weight: normal; + font-size: 1.2rem; + display: flex; + align-items: center; + line-height: 1.5rem; + padding: 0.5rem 0.75rem; + margin: 0.25rem 0.1rem 0.25rem 0; + color: #fff; + border: 1px solid #5e72e4; + border: 1px solid var(--primary); + border-radius: 0.25rem; + outline: 0; + background-image: none; + box-shadow: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.cbi-dynlist>.add-item:not([ondrop])>input { + overflow: hidden; + width: 100%; + min-width: 15rem; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cbi-dynlist>.add-item[ondrop]>input { + min-width: 13rem; +} + +.cbi-dynlist, +.cbi-dropdown { + position: relative; + display: inline-flex; + padding: 0.2rem 0.2rem; +} + +.cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; +} + +.cbi-dropdown>ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + margin: 0 !important; + padding: 0; + list-style: none; + outline: 0; +} + + +.cbi-dropdown>ul.preview { + display: none; + +} + +.cbi-button-apply>ul.preview { + display: none; + + li { + color: #fff; + } + +} + +.cbi-button-apply>ul:first-child { + li { + color: #fff; + } + +} + +.cbi-dropdown>.open { + flex-basis: 15px; +} + +.cbi-dropdown>.open, +.cbi-dropdown>.more { + font-size: 1rem; + font-weight: 900; + line-height: 2; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + padding: 0 .25em; + cursor: default; + text-align: center; + outline: 0; +} + +.cbi-dropdown>.more, +.cbi-dropdown>ul>li[placeholder] { + font-weight: bold; + display: none; + color: #777; + text-shadow: 1px 1px 0 #fff; +} + +.cbi-dropdown>ul>li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + padding: .25em; + white-space: nowrap; + text-overflow: ellipsis; + +} + +.cbi-dropdown>ul>li .hide-open { + display: initial; +} + +.cbi-dropdown>ul>li .hide-close { + display: none; +} + +.cbi-dropdown>ul>li[display]:not([display="0"]) { + border-left: thin solid #ccc; +} + +.cbi-dropdown[empty]>ul { + max-width: 1px; +} + +.cbi-dropdown>ul>li>form { + display: none; + margin: 0; + padding: 0; + pointer-events: none; +} + +.cbi-dropdown>ul>li img { + margin-right: .25em; + vertical-align: middle; +} + +.cbi-dropdown>ul>li>form>input[type="checkbox"] { + height: auto; + margin: 0; +} + +.cbi-dropdown>ul>li input[type="text"] { + height: 20px; +} + +.cbi-dropdown[open]>ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px !important; + border: 0 solid #918e8c; + background: #ffffff; + box-shadow: 0 0 4px #918e8c; + border-bottom-left-radius: 0.35rem; + border-bottom-right-radius: 0.35rem; + color: var(--main-menu-color); + margin-left: -0.2rem !important; + + li { + color: #000; + } +} + + +.cbi-dropdown>ul>li[display], +.cbi-dropdown[open]>ul.preview, +.cbi-dropdown[open]>ul.dropdown>li, +.cbi-dropdown[multiple]>ul>li>label, +.cbi-dropdown[multiple][open]>ul.dropdown>li, +.cbi-dropdown[multiple][more]>.more, +.cbi-dropdown[multiple][empty]>.more { + display: flex; + align-items: center; + flex-grow: 1; + +} + +.cbi-dropdown[empty]>ul>li, +.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], +.cbi-dropdown[multiple][open]>ul.dropdown>li>form { + display: block; +} + +.cbi-dropdown[open]>ul.dropdown>li .hide-open { + display: none; +} + +.cbi-dropdown[open]>ul.dropdown>li .hide-close { + display: initial; +} + +.cbi-dropdown[open]>ul.dropdown>li { + border-bottom: thin solid #ccc; + padding: 0.5rem 0.8rem; +} + +.cbi-dropdown[open]>ul.dropdown>li label { + margin-left: 0.5rem; +} + +.cbi-dropdown[open]>ul.dropdown>li[selected] { + background: #dce1fe; +} + +.cbi-dropdown[open]>ul.dropdown>li.focus { + background: #dce1fe; + outline: none; +} + +.cbi-dropdown[open]>ul.dropdown>li:last-child { + margin-bottom: 0; + border-bottom: 0; +} + +.cbi-dropdown[open]>ul.dropdown>li[unselectable] { + opacity: .7; +} + +.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child { + width: 100%; +} + +.cbi-dropdown[disabled] { + pointer-events: none; + opacity: .6; +} + +.cbi-dropdown .zonebadge { + width: 100%; +} + +.cbi-dropdown[open] .zonebadge { + width: auto; +} + +/* progressbar */ +.cbi-progressbar { + position: relative; + min-width: 11rem; + height: 1.5rem; + margin: 0 0; + border: thin solid #999; + background: #eee; + border-radius: 4px; + overflow: hidden; +} + +.cbi-progressbar>div { + width: 0; + height: 100%; + transition: width .25s ease-in; + background: #5bc0de; + background: var(--bar-bg); +} + +.cbi-progressbar::after { + font-family: monospace; + font-size: 1em; + font-weight: bold; + font-size-adjust: .38; + line-height: 1.5rem; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + content: attr(title); + text-align: center; + white-space: pre; + text-overflow: ellipsis; +} + +#modal_overlay { + position: fixed; + z-index: 900; + top: 0; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity .125s ease-in; + opacity: 0; + background: rgba(0, 0, 0, .7); + -webkit-overflow-scrolling: touch; +} + +.modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1em; + border-radius: 3px !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +.modal>* { + line-height: normal; + flex-basis: 100%; + margin-bottom: .5em; + max-width: 100%; +} + +.modal>pre, +.modal>textarea { + font-size: 1rem; + font-size-adjust: .35; + overflow: auto; + margin-bottom: .5em; + padding: 8.5px; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +.modal>h4 { + margin: .5em 0; +} + +.modal ul { + margin-left: 2.2em; +} + +.modal li { + list-style-type: square; + color: #808080; +} + +.modal p { + + word-break: break-word; +} + +.modal .label { + font-size: .6rem; + font-weight: normal; + padding: .1rem .3rem; + padding-bottom: 0; + cursor: default; + border-radius: 0; +} + +.modal .label.warning { + background-color: #f0ad4e !important; +} + +.modal .btn { + padding: 0.45rem 0.8rem; +} + +.modal.cbi-modal { + max-width: 90%; + max-height: none; +} + +body.modal-overlay-active { + overflow: hidden; + height: 100vh; +} + +body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; +} + + + +.spinning { + position: relative; + padding-left: 32px !important; +} + +.spinning::before { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + width: 32px; + content: ""; + background: url(/luci-static/resources/icons/loading.gif) no-repeat center; + background-size: 16px; +} + +/* luci */ +.hidden { + display: none; +} + +.left, +.left::before { + text-align: left !important; +} + +.right, +.right::before { + text-align: right !important; +} + +.center, +.center::before { + text-align: center !important; +} + +.top { + align-self: flex-start !important; + vertical-align: top !important; +} + +.bottom { + align-self: flex-end !important; + vertical-align: bottom !important; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + padding-top: 1rem; + text-align: right; + justify-content: flex-end; +} + +.cbi-page-actions>form[method="post"] { + display: inline-block; +} + +.th[data-type="button"], +.td[data-type="button"], +.th[data-type="fvalue"], +.td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; +} + +.ifacebadge { + display: inline-flex; + gap: .2rem; + padding: .5rem .8rem; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); + border-radius: 4px; +} + +td>.ifacebadge, +.td>.ifacebadge { + font-size: .8rem; + background-color: #f0f0f0; +} + +.ifacebadge>em, +.ifacebadge>img { + display: inline-block; + align-self: flex-start; +} + +.ifacebadge>img+img { + margin: 0 .2rem 0 0; +} + +.network-status-table { + display: flex; + flex-wrap: wrap; +} + +.network-status-table .ifacebox { + flex-grow: 1; + border-radius: 4px; + overflow: hidden; + margin: 0 1.25rem 1rem 1.25rem; +} + +.network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; + gap: 0.5em; +} + +.network-status-table .ifacebox-body>span { + flex: 10 10 auto; + height: 100%; +} + +.network-status-table .ifacebox-body>div { + display: flex; + flex-wrap: wrap; + gap: .5rem; +} + +.network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + padding: .5em; + background-color: #fff; + + >span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} + +/* textarea */ +.cbi-input-textarea { + font-family: monospace; + width: 100%; + font-size: 0.875rem; + min-height: 14rem; + padding: .8rem; + color: #000; +} + +#syslog { + font-size: small; + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + padding: 1rem; + resize: none; + color: #242424; + border: 0; + border-radius: 0.375rem; + background-color: #ffffff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +#syslog:focus { + outline: 0; +} + +/* config changes */ +.uci-change-list { + font-family: monospace; +} + +.uci-change-list ins, +.uci-change-legend-label ins { + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; +} + +.uci-change-list del, +.uci-change-legend-label del { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #f00; + background-color: #fcc; +} + +.uci-change-list var, +.uci-change-legend-label var { + font-style: normal; + display: block; + padding: 2px; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; +} + +.uci-change-list var ins, +.uci-change-list var del { + font-style: normal; + padding: 0; + white-space: pre; + border: 0; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + float: left; + width: 150px; +} + +.uci-change-legend-label>ins, +.uci-change-legend-label>del, +.uci-change-legend-label>var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; +} + +.uci-change-legend-label var ins, +.uci-change-legend-label var del { + line-height: .4; + border: 0; +} + +.uci-change-list var, +.uci-change-list del, +.uci-change-list ins { + padding: .5rem; +} + +/* other fix */ +#iwsvg, +#iwsvg2, +#bwsvg { + border: thin solid #d4d4d4 !important; +} + +#iwsvg, +[data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0 !important; +} + +.ifacebox { + line-height: 1.25; + display: inline-flex; + overflow: hidden; + flex-direction: column; + border-radius: 4px; + min-width: 100px; + border-bottom: thin solid #ccc; + background-color: #f9f9f9; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .2); +} + +.ifacebox-head { + padding: .25em; + background: #eee; +} + +.ifacebox-head.active { + background: #5e72e4; + background: var(--primary); + + * { + color: #fff; + color: var(--white); + } + +} + +.ifacebox-body { + padding: 0.875rem 1rem; + line-height: 1.6em; +} + +.cbi-image-button { + margin-left: .5rem; +} + +.zonebadge { + display: inline-block; + padding: .2rem .5rem; + border-radius: 4px; +} + +.zonebadge .ifacebadge { + margin: .1rem .2rem; + padding: .2rem .3rem; + border: thin solid #6c6c6c; +} + +.zonebadge>input[type="text"] { + min-width: 10rem; + margin-top: .3rem; + padding: .16rem 1rem; +} + +.zonebadge>em, +.zonebadge>strong { + display: inline-block; + margin: 0 .2rem; +} + +.cbi-value-field .cbi-input-checkbox, +.cbi-value-field .cbi-input-radio { + margin-top: .1rem; +} + +.cbi-value-field>ul>li { + display: flex; +} + +.cbi-value-field>ul>li>label { + margin-top: .5rem; +} + +.cbi-value-field>ul>li .ifacebadge { + margin-top: -.5rem; + margin-left: .4rem; + background-color: #eee; +} + +.cbi-section-table-row>.cbi-value-field .cbi-dropdown { + min-width: 3rem; +} + +.cbi-section-create { + display: inline-flex; + align-items: center; + margin: 0.25rem 1.25rem; +} + +.cbi-section-create>* { + margin: .5rem 0; +} + +.cbi-section-remove { + padding: .5rem; +} + +div.cbi-value var, +td.cbi-value-field var, +.td.cbi-value-field var { + font-style: italic; + color: #0069d6; +} + +.cbi-optionals { + padding: 1rem 1rem 0 1rem; + border-top: thin solid #ccc; +} + +.cbi-dropdown-container { + position: relative; +} + +.cbi-tooltip-container, +span[data-tooltip], +span[data-tooltip] .label { + cursor: help !important; +} + +.cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + padding: 2px 5px; + transition: opacity .25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 3px; + background: #fff; + box-shadow: 0 0 2px #444; +} + +.cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity .25s ease-in; + opacity: 1; +} + +.zonebadge .cbi-tooltip { + margin: -1.5rem 0 0 -.5rem; + padding: .25rem; + background: inherit; +} + +.zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg, rgba(204, 204, 204, .5), rgba(204, 204, 204, .5) 5px, rgba(255, 255, 255, .5) 5px, rgba(255, 255, 255, .5) 10px); +} + +.zone-forwards { + display: flex; + min-width: 10rem; +} + +.zone-forwards>* { + flex: 1 1 45%; +} + +.zone-forwards>span { + flex-basis: 10%; + padding: 0 .25rem; + text-align: center; +} + +.zone-forwards .zone-src, +.zone-forwards .zone-dest { + display: flex; + flex-direction: column; +} + +.label { + font-size: .8rem; + font-weight: bold; + padding: .3rem .8rem; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: #fff !important; + border-radius: 3px; + background-color: #bfbfbf; + text-shadow: none; +} + +label>input[type="checkbox"], +label>input[type="radio"] { + position: relative; + top: .4rem; + right: .2rem; + margin: 0; + vertical-align: bottom; +} + +label[data-index][data-depends] { + padding-right: 2em; +} + +.showSide { + display: none; +} + +.darkMask { + position: fixed; + z-index: 99; + display: none; + width: 100%; + height: 100%; + content: ""; + top: 0; + background-color: rgba(0, 0, 0, .56); + transition: all 0.2s; + + &.active { + display: block; + } +} + +/* diagnostics */ +#diag-rc-output>pre, +#command-rc-output>pre, +[data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: .35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + padding: 8.5px; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); +} + +[data-page="admin-network-diagnostics"] .table { + box-shadow: none; +} + +input[name="ping"], +input[name="traceroute"], +input[name="nslookup"] { + width: 80%; +} + + + +/* fix status */ +.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), +.node-status-processes>.main .table .tr .td:nth-child(3) { + white-space: normal; +} + +/* fix system reboot */ +[data-page="admin-system-reboot"] p { + padding-left: 1.5rem; +} + +[data-page="admin-system-reboot"] .cbi-button { + background: #fb6340 !important; +} + +[data-page="admin-system-reboot"] p>span { + position: relative; + top: .1rem; + left: 1rem; +} + +[data-page="admin-vpn-passwall"] h4 { + background: transparent; +} + +/* samba */ +#cbi-samba [data-tab="template"] .cbi-value-field { + display: block; +} + +#cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: .6rem; +} + +/* admin-system-admin-password */ +[data-page="admin-system-admin"] .cbi-map h2, +[data-page="admin-system-admin-password"] .cbi-map h2, +[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, +[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} + + +/* software */ +[data-page="admin-system-opkg"] h2 { + margin-left: 0; + color: #32325d; + color: var(--gray-dark); +} + +.controls { + margin: .5em 1rem 1em 1rem !important; +} + +.controls>*>.btn:not([aria-label$="page"]) { + flex-grow: initial !important; + margin-top: .25rem; +} + +.controls>#pager>.btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: bold; +} + +.controls>*>label { + margin-bottom: .2rem; +} + +[data-page="admin-system-opkg"] div.btn { + line-height: 3; + display: inline; + padding: .3rem .6rem; +} + +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent>.container { + margin-top: 2rem; + padding-top: .1rem; +} + +[data-page="admin-system-opkg"] #maincontent>.container { + margin: 0 1.25rem 1rem 1.25rem; + margin-bottom: 1rem; +} + +.td.version, +.td.size { + white-space: normal !important; + word-break: break-word; +} + +.cbi-tabmenu+.cbi-section { + margin-top: 0; +} + +/* admin-system-crontab*/ +[data-page="admin-system-crontab"] #view p { + margin-bottom: 1rem; +} + +/*admin-system-flash*/ + +[data-page="admin-system-flash"] { + .cbi-value { + padding: 0; + } + + .cbi-section { + .cbi-section { + margin-top: 0; + } + } + + .cbi-map-tabbed { + border-radius: 0.375rem; + } + + legend { + display: block !important; + font-size: 1.2rem; + width: 100%; + display: block; + margin-bottom: 0; + padding: 1rem 0 1rem 1.5rem; + border-bottom: 1px solid rgba(0, 0, 0, .05); + line-height: 1.5; + margin-bottom: 0rem; + letter-spacing: 0.1rem; + color: #32325d; + font-weight: bold; + } + + .cbi-section-descr { + font-weight: 600; + padding: 1rem 0 1rem 1.5rem; + color: #525f7f; + } + + .modal { + + + label>input[type="checkbox"] { + top: -0.35rem; + } + + .btn { + white-space: normal !important; + } + } +} + +/* wireless overview */ +#cbi-wireless>#wifi_assoclist_table>.tr { + box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd !important; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.table-titles { + box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; +} + +#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { + width: 23rem; +} + +[data-page="admin-network-dhcp"] .cbi-value { + padding: 0; + +} + +[data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem 0 !important; +} + +/* firewall */ +#iptables { + margin: 0; +} + +.Firewall form { + margin: 2rem 2rem 0 0; + padding: 0; + box-shadow: none; +} + +#cbi-firewall-redirect table *, +#cbi-network-switch_vlan table *, +#cbi-firewall-zone table * { + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"], +#cbi-network-switch_vlan table input[type="text"], +#cbi-firewall-zone table input[type="text"] { + width: 5rem; +} + +#cbi-firewall-redirect table select, +#cbi-network-switch_vlan table select, +#cbi-firewall-zone table select { + min-width: 3.5rem; +} + +#cbi-network-switch_vlan .th, +#cbi-network-switch_vlan .td { + flex-basis: 12%; +} + +#cbi-firewall-zone .table, +#cbi-network-switch_vlan .table { + display: block; +} + +#cbi-firewall-zone .td, +#cbi-network-switch_vlan .td { + width: 100%; +} + +[data-page="admin-network-firewall-custom"] #view p, +[data-page="admin-status-routes"] #view p { + padding: 0 1.5rem; + margin-bottom: 1rem; + + textarea { + padding: 1rem; + border-radius: 0.375rem; + } +} + +/* applyreboot fix */ +#applyreboot-container { + margin: 2rem; +} + +#applyreboot-section { + line-height: 300%; + margin: 2rem; +} + +/* openvpn bug fix */ +.OpenVPN a { + line-height: initial !important; +} + +/* custom commands */ +.commandbox { + width: 24% !important; + margin: 10px 0 0 10px !important; + padding: .5rem 1rem; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05); +} + +.commandbox h3 { + line-height: normal !important; + overflow: hidden; + margin: 6px 0 !important; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox div { + left: auto !important; +} + +.commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + padding: 2px 3px; + white-space: nowrap; + text-overflow: ellipsis; +} + +.commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; +} + +.commandbox p:first-of-type { + margin-top: -6px; +} + +.commandbox p:nth-of-type(2) { + margin-top: 2px; +} + +[data-page^="admin-system-commands"] .panel-title, +[data-page^="command-cfg"] .mobile-hide, +[data-page^="command-cfg"] .showSide { + display: none; +} + +#command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + margin: 0; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; +} + +@keyframes anim-fade-in { + 100% { + opacity: 1; + } +} + +/* other fix */ +input[type="checkbox"] { + appearance: none !important; + -webkit-appearance: none !important; + border: 1px solid #dee2e6; + + width: 16px !important; + height: 16px !important; + padding: 0; + cursor: pointer; + transition: all 0.2s; + margin: 1rem 0 0 0; +} + +input[type="checkbox"]:checked { + border: 1px solid #5e72e4; + border: 1px solid var(--primary); + background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; + background-color: #5e72e4; + background-color: var(--primary); + background-size: 70%; + background-repeat: no-repeat; + background-position: center; +} + +.fb-container .cbi-button { + height: auto !important; +} + +#cbi-usb_printer-printer em { + display: block; + padding: 1rem; + text-align: center; +} + +pre.command-output { + padding: 1.5rem; +} + +[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { + padding: 1.5rem !important; +} + +[data-page="admin-nlbw-backup"] form { + padding-left: 1.5rem; +} + +[data-page="admin-status-iptables"] .right { + margin-bottom: 0 !important; +} + +/* IE hacks */ +@media all and (-ms-high-contrast: none) { + .main>.main-left>.nav>.slide>.menu::before { + top: 30.25%; + } + + .main>.main-left>.nav>li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } +} + +@media screen and (max-width: 1600px) { + header>.fill>.container>#logo { + margin: 0 2.5rem 0 .5rem; + } + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + .btn:not(button), + .cbi-button { + font-size: .8rem; + } + + .label { + padding: .2rem .6rem; + } + + + .cbi-value-title { + width: 15rem; + padding-right: .6rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 18rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-admin-status>.main fieldset li>a { + padding: .3rem .6rem; + } +} + +@media screen and (max-width: 1366px) { + + + header>.fill>.container { + + cursor: default; + } + + + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + + .tabs>li>a, + .cbi-tabmenu>li>a { + padding: .2rem .8rem; + } + + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + + table { + font-size: .7rem !important; + width: 100% !important; + } + + .table .cbi-input-text { + width: 100%; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"], + .cbi-value input[type="password"] { + min-width: 16rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 4rem; + } + + .main>.main-left>.nav>li, + .main>.main-left>.nav>li>a, + .main .main-left .nav>li>a:first-child, + .main>.main-left>.nav>.slide>.menu, + .main>.main-left>.nav>li>[data-title="Logout"] { + font-size: .9rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: .7rem; + } + + #modal_overlay { + top: 0rem; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), + [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), + [data-page="admin-network-hosts"] .table, + [data-page="admin-network-routes"] .table { + overflow-y: visible; + } + + .commandbox { + width: 32% !important; + } + + .btn:not(button), + .cbi-button { + font-size: 0.8rem; + + } +} + +@media screen and (max-width: 1152px) { + header>.fill>.container>#logo { + display: none; + } + + header>.fill>.container>.brand { + position: relative; + } + + html, + .main { + overflow-y: visible; + } + + .main>.loading>span { + top: 25%; + } + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + + + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + + .node-main-login>.main .cbi-value-title { + text-align: left; + } + + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + + .cbi-value-field .cbi-dropdown, + .cbi-value-field .cbi-input-select, + .cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + } + + /*.cbi-value input[type="password"],*/ + .cbi-value input[name^="pw"], + .cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem !important; + min-width: 13rem; + } + + #diag-rc-output>pre, + #command-rc-output>pre, + [data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + + .table { + display: block; + } + + .Interfaces .table { + overflow-x: hidden; + } + + #packages.table { + display: grid; + } + + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .Overview .table[width="100%"]>.tr { + flex-wrap: nowrap; + } + + .tr.placeholder { + border-bottom: thin solid #ddd; + } + + .tr.placeholder>.td, + #cbi-firewall .tr>.td, + #cbi-network .tr:nth-child(2)>.td, + .cbi-section #wifi_assoclist_table .tr>.td { + border-top: 0; + } + + .th, + .td { + display: inline-block; + align-self: flex-start; + flex: 2 2 10%; + text-overflow: ellipsis; + word-wrap: break-word; + } + + .td select, + .td input[type="text"] { + width: 100%; + word-wrap: normal; + } + + .td [data-dynlist]>input, + .td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + .td[data-type="button"], + .td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + + .th.cbi-value-field, + .td.cbi-value-field, + .th.cbi-section-table-cell, + .td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + } + + .td.cbi-value-field, + .cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + + .td.cbi-section-actions { + vertical-align: bottom; + } + + .tr.table-titles, + .tr.cbi-section-table-titles, + .tr.cbi-section-table-descr { + display: none; + } + + .tr[data-title]::before, + .tr.cbi-section-table-titles.named::before { + font-size: .9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0, 0, 0, .26); + background: #e9ecef; + } + + .td[data-title], + [data-page^="admin-status-realtime"] .td[id] { + text-align: left; + } + + .td[data-title]::before { + display: block; + } + + .cbi-button+.cbi-button { + margin-left: 0; + } + + .td.cbi-section-actions>*>*, + .td.cbi-section-actions>*>form>* { + margin: 2.1px 3px; + } + + .Firewall form { + position: static !important; + margin: 0 0 2rem 0; + padding: 2rem; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); + } + + .Firewall form input { + width: 100% !important; + margin: 0; + margin-top: 1rem; + } + + .Firewall .center, + .Firewall .center::before { + text-align: left !important; + } + + .commandbox { + width: 100% !important; + margin-left: 0 !important; + } + + .btn:not(button), + .cbi-button { + font-size: 0.8rem; + } +} + + + + +@media screen and (max-width: 768px) { + body { + font-size: .8rem; + } + + .cbi-progressbar::after { + font-size: .6rem; + } + + + + .main-left { + position: fixed; + z-index: 100; + width: 0; + + &.active { + width: 13rem; + } + } + + .main-right { + width: 100%; + + &.active { + overflow-y: hidden; + } + } + + .darkMask.active { + display: block; + } + + .showSide { + padding: 0.1rem; + position: relative; + z-index: 99; + display: inline-block !important; + + &::before { + font-family: 'argon' !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\e20e"; + font-size: 1.7rem; + } + } + + + header>.fill>.container>.flex1>.brand { + display: inline-block; + } + + + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: 0.8rem; + } + + + +} + +@media screen and (max-width: 600px) { + .mobile-hide { + display: none; + } + + #maincontent>.container { + margin: 0 1rem 1rem 1rem; + } + + .cbi-value-title { + text-align: left; + } + + [data-page="admin-system-flash"] legend { + padding: 1rem 0 1rem 1rem; + + } + + [data-page="admin-system-flash"] .cbi-section-descr { + padding: 1rem 0 1rem 1rem; + + } + + [data-page="admin-system-flash"] .cbi-value { + padding: 0 1rem; + } + + [data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem 1rem !important; + } + + .cbi-dynlist p { + padding: 0.5rem 1rem; + } + + body { + overflow-x: hidden; + } + + .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { + width: 16rem; + } + + .node-main-login footer { + display: none; + } + + .tabs, + .cbi-tabmenu { + &::-webkit-scrollbar { + width: 0px; + height: 0px; + } + } + + .cbi-value-field, + .cbi-value-description { + display: block !important; + padding-left: 0 !important; + padding-right: 0 !important; + } + + [data-page="admin-system-admin-password"] .cbi-value-field { + display: table-cell !important; + } + + .modal.cbi-modal { + max-width: 100%; + max-height: none; + } + + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 100%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + margin: 5em auto; + padding: 1em; + border-radius: 3px !important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); + } + + .cbi-dropdown[open]>ul.dropdown { + left: 0.2rem !important; + right: 0 !important; + margin-bottom: 1rem; + } + + .login-page .login-container footer { + display: none; + } +} + + + +@media screen and (min-width: 600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar, + ::-webkit-scrollbar-corner { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background: #9e9e9e; + } + + ::-webkit-scrollbar-thumb:hover { + background: #757575; + } + + ::-webkit-scrollbar-thumb:active { + background: #424242; + } + + + + +} + + + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; + } + + .login-page .login-container { + margin-left: 0rem !important; + width: 100%; + + .login-form { + .form-login { + .input-group { + &::before { + color: #525461; + } + + input { + color: #525461; + border-bottom: white 1px solid; + border-bottom: var(--white) 1px solid; + border-radius: 0; + } + + } + } + } + + } + + +} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/dark.less b/luci-theme-argon/htdocs/luci-static/argon/less/dark.less new file mode 100755 index 000000000..1e0568ad6 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/less/dark.less @@ -0,0 +1,830 @@ +// compress: true , sourceMap: false +/** + * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template + * + * luci-theme-argon + * Copyright 2020 Jerryk + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/jerrykuku/luci-theme-argon/issues + * + * luci-theme-bootstrap: + * Copyright 2008 Steven Barth + * Copyright 2008 Jo-Philipp Wich + * Copyright 2012 David Menting + * + * MUI: + * https://github.com/muicss/mui + * + * luci-theme-material: + * https://github.com/LuttyYang/luci-theme-material/ + * + * Agron Theme + * https://demos.creative-tim.com/argon-dashboard/index.html + * + * Login background + * https://unsplash.com/ + * + * Licensed to the public under the Apache License 2.0 + */ + +body { + background: #1e1e1e; + color: #cccccc; +} + +.login-page .login-container { + + .login-form { + background-color: #1e1e1e; + -webkit-backdrop-filter: blur(var(--blur-radius-dark)); + backdrop-filter: blur(var(--blur-radius-dark)); + background-color: rgba(0, 0, 0, var(--blur-opacity-dark)); + + .brand { + color: #adb5bd; + } + + .form-login { + .input-group { + &::before { + color: #adb5bd; + } + + input { + background-color: transparent !important; + color: #adb5bd; + border-bottom: #adb5bd 1px solid !important; + border-radius: 0 !important; + border-top: none !important; + border-left: none !important; + border-right: none !important; + box-shadow: none; + } + + } + + .cbi-button-apply { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + + &:hover, + &:focus { + opacity: 0.9; + } + } + } + } + +} + +header::after { + background-color: #1e1e1e !important; +} + + +.main { + .main-left { + + background-color: #333333 !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .15); + + .sidenav-header .brand { + color: #ccc; + } + + .nav { + .slide { + .slide-menu { + .active { + a { + color: #cccccc; + + &::after { + background-color: #cccccc !important; + } + } + } + + li { + a { + color: #cccccc; + } + + a:hover { + background: none !important; + } + } + } + + .menu.active { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + color: #cccccc !important; + + a::after { + background-color: #cccccc !important; + } + } + } + + li { + a { + color: #cccccc !important; + } + + a:hover { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + color: #cccccc !important; + } + } + } + + + &::-webkit-scrollbar-thumb { + background-color: #252526 !important; + } + + &::-webkit-scrollbar-track { + background-color: #333; + } + } + + .main-right { + background-color: #1e1e1e; + } +} + +h2 { + color: #ccc; + background: #333333; +} + +h3 { + color: #ccc; + border-bottom: 0; + background: #333333; +} + +a:-webkit-any-link { + color: -webkit-link; + cursor: pointer; + color: #483d8b; + color: var(--dark-primary); +} + + +input:-webkit-autofill { + background-color: #3c3c3c !important; +} + +.cbi-value-field .cbi-input-apply, +.cbi-button-apply, +.cbi-button-edit { + color: #fff !important; + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; +} + + +.cbi-section em { + color: #ccc; +} + +header.bg-primary { + background-color: #1e1e1e !important; +} + +.cbi-map-descr { + color: #ccc; +} + +.cbi-section { + background: none; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) +} + +.panel-title { + color: #ccc; + background-color: #333333; + border-bottom: 0px; +} + +div>table>tbody>tr:nth-of-type(2n), +div>.table>.tr:nth-of-type(2n) { + background-color: #252526; +} + +table>tbody>tr>td, +table>tfoot>tr>td, +table>thead>tr>td { + color: #ccc; +} + +fieldset>table>tbody>tr:nth-of-type(2n) { + background-color: #252526; +} + +table>tbody>tr>td, +table>tfoot>tr>td, +table>thead>tr>td { + border-top: 1px solid #252526; +} + +#swaptotal>div>div, +#swapfree>div>div, +#memfree>div>div, +#membuff>div>div, +#conns>div>div, +#memtotal>div>div { + background-color: #32325d !important; +} + +#swaptotal>div>div>div>small, +#swapfree>div>div>div>small, +#memfree>div>div>div>small, +#membuff>div>div>div>small, +#conns>div>div>div>small, +#memtotal>div>div>div>small { + + color: #ccc !important; +} + +.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last { + line-height: 1.8em; + + div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] { + border: 1px solid #999999 !important; + background-color: transparent !important; + + div { + background-color: #32325d !important; + } + } + +} + +table>tbody>tr>th, +table>tfoot>tr>th, +table>thead>tr>th { + + background-color: #252526; + border-bottom: black 1px solid !important; +} + +tr>td, +tr>th, +.tr>.td, +.tr>.th, +.cbi-section-table-row::before, +#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { + border-top: 0; +} + +.cbi-rowstyle-2 { + background-color: #1e1e1e; +} + +.cbi-rowstyle-1 { + background-color: #252526; +} + +.cbi-rowstyle-2 .cbi-button-up, +.cbi-rowstyle-2 .cbi-button-down, +body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: rgb(102, 102, 102) !important; +} + +.cbi-section>h3:first-child, +.panel-title, +h3 { + color: #ccc; + border-bottom: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +h4 { + background-color: #1e1e1f; +} + +.cbi-progressbar { + position: relative; + min-width: 170px; + height: 20px; + margin: 6px 0; + border: thin solid #999; + background: transparent; + border-radius: 0.2rem; + overflow: hidden; + + div { + background-color: #32325d !important; + } +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + background-color: #1e1e1f; +} + +.cbi-button { + color: #ccc !important; + background-color: #483d8b; + background-color: var(--dark-primary); +} + +.cbi-section-node { + background: none; + border-radius: 0 0 .375rem .375rem; + padding: 0rem; +} + +abbr { + color: #5e72e4; +} + +div>table>tbody>tr:nth-of-type(2n), +div>.table>.tbody>.tr:nth-of-type(2n) { + background-color: #252526; +} + +#content_syslog { + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35) +} + +#syslog { + color: #ccc; + background-color: #1e1e1e; +} + +#iwsvg, +#iwsvg2, +#bwsvg { + overflow: hidden; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + background-color: #1e1e1e !important; +} + +.tabs { + background-color: #252526; +} + +.tabs>li[class~="active"]>a { + color: #ccc; +} + +.tabs>li[class~="active"], +.tabs>li:hover { + border-bottom: 0.18751rem solid #483d8b; + border-bottom: 0.18751rem solid var(--dark-primary); + color: #ccc; + background-color: #181819; +} + +.cbi-tabmenu>li>a, +.tabs>li>a { + color: #ccc; + + &:hover { + color: #ccc; + } +} + +.cbi-tabmenu>li { + background: #2d2d2d; +} + +.cbi-tabmenu li[class~="cbi-tab"] a { + color: #ccc; +} + +.cbi-tabmenu>li:hover { + color: #ccc; + background: #2d2d2d; +} + +.cbi-tabmenu>li[class~="cbi-tab"] { + background-color: #181819; +} + +.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { + background-color: #252526; +} + +.cbi-value-title { + color: #ccc; +} + +select, +input { + color: #ccc; + background-color: transparent !important; + border: 1px solid #252526; + box-shadow: none; +} + +select:not([multiple="multiple"]):focus, +input:focus { + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; + outline: 0; + +} + +select { + background-color: #1e1e1e !important; +} + +#cbi-dropbear h2, +#cbi-dropbear .cbi-map-descr, +#cbi-dropbear .cbi-map-descr abbr, +#cbi-rc h2, +#cbi-rc .cbi-map-descr, +#cbi-distfeedconf h2, +#cbi-distfeedconf .cbi-map-descr, +#cbi-customfeedconf h2, +#cbi-customfeedconf .cbi-map-descr, +#cbi-download h2, +#cbi-filelist h2 { + color: #ccc !important; +} + +.cbi-value-field>ul>li .ifacebadge { + background-color: #3c3c3c; +} + +.cbi-section-descr { + color: #ccc; +} + +.cbi-input-textarea { + background-color: #1e1e1e; + color: #ccc; +} + + + +.cbi-section-remove:nth-of-type(2n), +.cbi-section-node:nth-of-type(2n) { + background-color: #1e1e1e; +} + +.node-system-packages>.main table tr td:nth-last-child(1) { + color: #ccc; + +} + +.cbi-section-node .cbi-value { + padding: 1rem 1rem 0.3rem 1rem; +} + +.ifacebox { + background-color: none; + border: 1px solid #1e1e1e; +} + +.ifacebox-head { + color: #666; +} + +.ifacebox-body { + background-color: #333; +} + +.zonebadge strong { + color: #333; +} + +.zonebadge>.ifacebadge { + background-color: #3c3c3c; +} + +div.cbi-value var, +td.cbi-value-field var { + color: #5e72e4; +} + +#diag-rc-output>pre { + color: #ccc; + background-color: #1e1e1e; +} + +.node-services-vssr .block { + background-color: #3c3c3c !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); +} + +.node-services-vssr .block h4 { + color: #ccc !important; +} + +.node-services-vssr .status-bar { + color: #ccc; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + background-color: #1e1e1e; +} + +.node-services-vssr .cbi-section-table-row { + color: #ccc; + background-color: #3c3c3c !important; + box-shadow: 0 0 5px 0 rgba(0, 0, 0, .35) +} + +.node-services-vssr .cbi-section-table-row.fast { + background: #483d8b !important; + background: var(--dark-primary) !important; + color: #fff; +} + +.node-services-vssr .ssr-button { + color: #ccc; + +} + +.node-services-vssr .incon:nth-child(2) { + border-right: #1e1e1e 1px solid; +} + +#xhr_poll_status>.label.success { + color: #ccc !important; + + background-color: darkolivegreen !important; +} + +.notice { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; +} + +.cbi-input-find, +.cbi-input-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-find, +.cbi-input-reload, +.cbi-button-reload { + color: #fff !important; + background: darkolivegreen !important; + border-color: darkolivegreen !important; +} + +.cbi-button-reset, +.cbi-input-remove { + color: #fff !important; + background-color: darkorange !important; + border-color: darkorange !important; +} + +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit.important, +.cbi-button-apply.important, +.cbi-button-reload.important, +.cbi-button-action.important { + border: 1px #483d8b solid !important; + border: 1px var(--dark-primary) solid !important; +} + +.btn[value="Dismiss"], +.cbi-button[value="Terminate"], +.cbi-button[value="Reset"], +.cbi-button[value="Disabled"], +.cbi-button[onclick^="iface_reconnect"], +.cbi-button[onclick="handleReset(event)"], +.cbi-button-neutral[value="Disable"] { + font-weight: normal; + color: #fff; + border: thin solid darkorange !important; + background-color: darkorange !important; +} + +fieldset[id^="cbi-apply-"] { + background-color: #333333; +} + +#detail-bubble>div { + border: 1px solid #ccc; + border-radius: 2px; + padding: 5px; + background: #252525; +} + +.ifacebox-head.active { + background-color: #32325d !important; +} + +header .fill .status span[data-style="active"] { + color: #ccc !important; + background-color: darkolivegreen !important; +} + +#cbi-wireless .td, +#cbi-network .tr:first-child>.td, +.table[width="100%"]>.tr:first-child>.td, +[data-page="admin-network-diagnostics"] .tr>.td, +.tr.table-titles>.th, +.tr.cbi-section-table-titles>.th { + background-color: #252526; + border-bottom: black 1px solid !important; + +} + +.network-status-table .ifacebox-body .ifacebadge { + background-color: #252526; + border-bottom: 0; + box-shadow: none; +} + +td>.ifacebadge, +.td>.ifacebadge { + + background-color: #483d8b; + background-color: var(--dark-primary); + border: 0; +} + +.btn.danger, +.cbi-section-remove>.cbi-button, +.cbi-button-remove, +.cbi-button-reset, +.cbi-button-negative, +.cbi-button[value="Stop"], +.cbi-button[value="Kill"], +.cbi-button[onclick="reboot(this)"], +.cbi-button-neutral[value="Restart"] { + border: thin solid darkorange !important; + background-color: darkorange !important; +} + +.cbi-section, +.cbi-section-error, +#iptables, +.Firewall form, +#cbi-network>.cbi-section-node, +#cbi-wireless>.cbi-section-node, +#cbi-wireless>#wifi_assoclist_table, +[data-tab-title], +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), +[data-page="admin-system-opkg"] #maincontent>.container { + background: #1e1e1e !important; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, 0.35); +} + +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + background: transparent !important; +} + +[data-page="admin-system-admin"] .cbi-map h2, +[data-page="admin-system-admin-password"] .cbi-map h2, +[data-page="admin-system-admin"] .cbi-map .cbi-map-descr, +[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr { + color: #ccc; +} + +[data-page="admin-system-flash"] { + .modal { + label>input[type="checkbox"] { + top: -0.35rem; + } + + .btn { + white-space: normal !important; + background-color: darkseagreen; + } + + .alert-message { + background-color: transparent !important; + } + + .danger { + border: thin solid darkorange !important; + background-color: darkorange !important; + } + } +} + +.cbi-value input[type="password"]+.cbi-button-neutral { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; +} + +.btn, +button, +select, +input, +.cbi-dropdown { + border: 1px solid #3c3c3c !important; +} + + +.cbi-dropdown .preview { + color: #ccc; +} + +.cbi-section-table-row { + background-color: #1e1e1e !important; +} + +.modal { + background-color: #1e1e1e; +} + +.cbi-button-positive { + color: #fff !important; + background-color: darkolivegreen !important; +} + +[data-page="admin-system-flash"] legend { + color: #ccc; +} + +.logout:before { + color: #adb5bd !important; +} + +.cbi-dropdown[open] { + border-color: #483d8b !important; + border-color: var(--dark-primary) !important; +} + +.cbi-dropdown[open]>ul.dropdown { + background: #252526 !important; + color: #ccc !important; + box-shadow: none; + border: 1px solid #3c3c3c !important; + + +} + +.cbi-dropdown[open]>ul.dropdown li { + color: #ccc; + border-bottom: 1px solid #3c3c3c !important; +} + +.cbi-dropdown[open]>ul.dropdown>li[selected] { + background-color: #483d8b !important; + background-color: var(--dark-primary) !important; + border-bottom: 1px solid #3c3c3c !important; +} + +.cbi-dropdown[open]>ul.dropdown>li.focus { + background: #483d8b; + background: var(--dark-primary); + outline: none; +} + +.ifacebadge { + background-color: #333333; +} + +.cbi-dynlist>.item>span { + border: 1px solid #3c3c3c !important; +} + +.cbi-page-actions .cbi-button-apply, +.cbi-section-actions .cbi-button-edit, +.cbi-button-edit, +.cbi-button-apply, +.cbi-button-reload, +.cbi-button-action, +.cbi-button[value="Submit"], +.cbi-button[value="Upload"], +.cbi-button[value$="Apply"], +.cbi-button[onclick="addKey(event)"] { + background: #483d8b !important; + background: var(--dark-primary) !important; +} + +.btn.primary, +.cbi-page-actions .cbi-button-save, +.cbi-page-actions .cbi-button-apply+.cbi-button-save, +.cbi-button-add, +.cbi-button-save, +.cbi-button-positive, +.cbi-button-link, +.cbi-button[value="Enable"], +.cbi-button[value="Scan"], +.cbi-button[value^="Back"], +.cbi-button-neutral[onclick="handleConfig(event)"] { + background: #483d8b; + background: var(--dark-primary); +} + +[data-page="admin-system-opkg"] h2 { + color: #ccc !important; +} + + + + +@media screen and (max-width: 480px) { + .node-status-iptables>.main div>.cbi-map>form { + background-color: #1e1e1e; + box-shadow: 0 0 0.5rem 0 rgba(0, 0, 0, .35); + } + + +} diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/fonts.less b/luci-theme-argon/htdocs/luci-static/argon/less/fonts.less new file mode 100755 index 000000000..71dd0fed7 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/less/fonts.less @@ -0,0 +1,190 @@ +// out: false +/** + * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template + * + * luci-theme-argon + * Copyright 2020 Jerryk + * + * Have a bug? Please create an issue here on GitHub! + * https://github.com/jerrykuku/luci-theme-argon/issues + * + * luci-theme-bootstrap: + * Copyright 2008 Steven Barth + * Copyright 2008 Jo-Philipp Wich + * Copyright 2012 David Menting + * + * MUI: + * https://github.com/muicss/mui + * + * luci-theme-material: + * https://github.com/LuttyYang/luci-theme-material/ + * + * Agron Theme + * https://demos.creative-tim.com/argon-dashboard/index.html + * + * Login background + * https://unsplash.com/ + * + * Licensed to the public under the Apache License 2.0 + */ + + + @font-face { + font-family: 'Google Sans'; + src: url('data:application/font-woff2;charset=utf-8;base64,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') format('woff2'), + url('data:application/font-woff;charset=utf-8;base64,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') format('woff'); + font-weight: normal; + font-style: normal; +} + +/* Logo Font */ +@font-face { + font-family: 'TypoGraphica'; + src: url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'), + url('../fonts/TypoGraphica.woff') format('woff'), + url('../fonts/TypoGraphica.ttf') format('truetype'), + url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg'); + font-weight: normal; + font-style: normal; +} + +/* ICON Font */ + +@font-face { + font-family: 'argon'; + src: url('../fonts/argon.eot?u6kthm'); + src: url('../fonts/argon.eot?u6kthm#iefix') format('embedded-opentype'), + url('../fonts/argon.ttf?u6kthm') format('truetype'), + url('../fonts/argon.woff?u6kthm') format('woff'), + url('../fonts/argon.svg?u6kthm#argon') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="icon-"], +[class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'argon' !important; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-expand_more:before { + content: "\e20b"; +} + +.icon-menu:before { + content: "\e20e"; +} + +.icon-favorite:before { + content: "\e291"; +} + +.icon-spinner:before { + content: "\e603"; +} + +.icon-delete:before { + content: "\e900"; +} + +.icon-edit:before { + content: "\e901"; +} + +.icon-use:before { + content: "\e902"; +} + +.icon-loading:before { + content: "\e903"; +} + +.icon-switch:before { + content: "\e904"; +} + +.icon-error:before { + content: "\e905"; +} + +.icon-dashboard:before { + content: "\e906"; +} + +.icon-logout:before { + content: "\e907"; +} + +.icon-Network:before { + content: "\e908"; +} + +.icon-services:before { + content: "\e909"; +} + +.icon-system:before { + content: "\e90a"; +} + +.icon-vpn:before { + content: "\e90b"; +} + +.icon-storage:before { + content: "\e90c"; +} + +.icon-statistics:before { + content: "\e90d"; +} + +.icon-hello-world:before { + content: "\e90e"; +} + +.icon-angle-right:before { + content: "\e90f"; +} + +.icon-password:before { + content: "\e910"; +} + +.icon-user:before { + content: "\e971"; +} + +.icon-question:before { + content: "\f059"; +} + +.icon-docker:before { + content: "\e911"; +} + +.icon-control:before { + content: "\e912"; +} + +.icon-statistics1:before { + content: "\e913"; +} + +.icon-asterisk:before { + content: "\e914"; +} + +.icon-app:before { + content: "\e915"; +} \ No newline at end of file diff --git a/luci-theme-argon/htdocs/luci-static/argon/less/pure-min.less b/luci-theme-argon/htdocs/luci-static/argon/less/pure-min.less new file mode 100755 index 000000000..040c34a1f --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/argon/less/pure-min.less @@ -0,0 +1,12 @@ +// out: false +/*! +Pure v2.0.3 +Copyright 2013 Yahoo! +Licensed under the BSD License. +https://github.com/pure-css/pure/blob/master/LICENSE.md +*/ +/*! +normalize.css v | MIT License | git.io/normalize +Copyright (c) Nicolas Gallagher and Jonathan Neal +*/ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129fea;outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} diff --git a/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js b/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js new file mode 100755 index 000000000..cc8678f17 --- /dev/null +++ b/luci-theme-argon/htdocs/luci-static/resources/menu-argon.js @@ -0,0 +1,158 @@ +'use strict'; +'require baseclass'; +'require ui'; + +return baseclass.extend({ + __init__: function () { + ui.menu.load().then(L.bind(this.render, this)); + }, + + render: function (tree) { + var node = tree, + url = '', + children = ui.menu.getChildren(tree); + + for (var i = 0; i < children.length; i++) { + var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0); + + if (isActive) + this.renderMainMenu(children[i], children[i].name); + } + + if (L.env.dispatchpath.length >= 3) { + for (var i = 0; i < 3 && node; i++) { + node = node.children[L.env.dispatchpath[i]]; + url = url + (url ? '/' : '') + L.env.dispatchpath[i]; + } + + if (node) + this.renderTabMenu(node, url); + } + + document.querySelector('a.showSide') + .addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle')); + document.querySelector('.darkMask') + .addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle')); + }, + + handleMenuExpand: function (ev) { + var a = ev.target, slide = a.parentNode, slide_menu = a.nextElementSibling; + var collapse = false; + + document.querySelectorAll('.main .main-left .nav > li >ul.active').forEach(function (ul) { + $(ul).stop(true).slideUp("fast", function () { + ul.classList.remove('active'); + ul.previousElementSibling.classList.remove('active'); + }); + if (!collapse && ul === slide_menu) { + collapse = true; + } + + }); + + if (!slide_menu) + return; + + + if (!collapse) { + $(slide).find(".slide-menu").slideDown("fast",function(){ + slide_menu.classList.add('active'); + a.classList.add('active'); + }); + a.blur(); + } + ev.preventDefault(); + ev.stopPropagation(); + }, + + renderMainMenu: function (tree, url, level) { + var l = (level || 0) + 1, + ul = E('ul', { 'class': level ? 'slide-menu' : 'nav' }), + children = ui.menu.getChildren(tree); + + if (children.length == 0 || l > 2) + return E([]); + + for (var i = 0; i < children.length; i++) { + var isActive = ((L.env.dispatchpath[l] == children[i].name) && (L.env.dispatchpath[l - 1] == tree.name)), + submenu = this.renderMainMenu(children[i], url + '/' + children[i].name, l), + hasChildren = submenu.children.length, + slideClass = hasChildren ? 'slide' : null, + menuClass = hasChildren ? 'menu' : null; + if (isActive) { + ul.classList.add('active'); + slideClass += " active"; + menuClass += " active"; + } + + ul.appendChild(E('li', { 'class': slideClass }, [ + E('a', { + 'href': L.url(url, children[i].name), + 'click': (l == 1) ? ui.createHandlerFn(this, 'handleMenuExpand') : null, + 'class': menuClass, + 'data-title': hasChildren ? children[i].title.replace(" ", "_") : children[i].title.replace(" ", "_"), + }, [_(children[i].title)]), + submenu + ])); + } + + if (l == 1) { + document.querySelector('#mainmenu').appendChild(ul); + document.querySelector('#mainmenu').style.display = ''; + + } + return ul; + }, + + renderTabMenu: function (tree, url, level) { + var container = document.querySelector('#tabmenu'), + l = (level || 0) + 1, + ul = E('ul', { 'class': 'tabs' }), + children = ui.menu.getChildren(tree), + activeNode = null; + + if (children.length == 0) + return E([]); + + for (var i = 0; i < children.length; i++) { + var isActive = (L.env.dispatchpath[l + 2] == children[i].name), + activeClass = isActive ? ' active' : '', + className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass); + + ul.appendChild(E('li', { 'class': className }, [ + E('a', { 'href': L.url(url, children[i].name) }, [_(children[i].title)]) + ])); + + if (isActive) + activeNode = children[i]; + } + + container.appendChild(ul); + container.style.display = ''; + + if (activeNode) + container.appendChild(this.renderTabMenu(activeNode, url + '/' + activeNode.name, l)); + + return ul; + }, + + handleSidebarToggle: function (ev) { + var showside = document.querySelector('a.showSide'), + sidebar = document.querySelector('#mainmenu'), + darkmask = document.querySelector('.darkMask'), + scrollbar = document.querySelector('.main-right'); + + if (showside.classList.contains('active')) { + showside.classList.remove('active'); + sidebar.classList.remove('active'); + scrollbar.classList.remove('active'); + darkmask.classList.remove('active'); + } + else { + showside.classList.add('active'); + sidebar.classList.add('active'); + scrollbar.classList.add('active'); + darkmask.classList.add('active'); + } + } +}); diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer.htm b/luci-theme-argon/luasrc/view/themes/argon/footer.htm new file mode 100755 index 000000000..085f6e76f --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/footer.htm @@ -0,0 +1,46 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> +
+ +
+ + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm new file mode 100755 index 000000000..8098df211 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/footer_login.htm @@ -0,0 +1,44 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> + + + + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/header.htm b/luci-theme-argon/luasrc/view/themes/argon/header.htm new file mode 100755 index 000000000..17717ff65 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/header.htm @@ -0,0 +1,180 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(os.time()) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end + + -- Brand name + local brand_name = boardinfo.hostname or "?" +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + + + +"> + +
+ +
+
+
+
+ +
+
+
+
+
+
+
+ <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%> +
+

<%:No password set!%>

+

<%:There is no password set on this router. Please configure a root password to protect the web interface.%> +

+ <% if disp.lookup("admin/system/admin") then %> + + <% end %> +
+ <%- end -%> + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm new file mode 100755 index 000000000..568e0cecb --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/header_login.htm @@ -0,0 +1,119 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm new file mode 100755 index 000000000..398314779 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/out_footer_login.htm @@ -0,0 +1,27 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2019 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local is_rollback_pending, rollback_time_remaining, rollback_session, rollback_token = luci.model.uci:rollback_pending() + + if is_rollback_pending or trigger_apply or trigger_revert then +%> + +<% + end + + include("themes/" .. theme .. "/footer_login") +%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm b/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm new file mode 100755 index 000000000..35e73ec46 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/out_header_login.htm @@ -0,0 +1,14 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2019 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local ver = require "luci.version" + + if not luci.dispatcher.context.template_header_sent then + include("themes/" .. theme .. "/header_login") + luci.dispatcher.context.template_header_sent = true + end +%> diff --git a/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm new file mode 100755 index 000000000..5b46f2fa3 --- /dev/null +++ b/luci-theme-argon/luasrc/view/themes/argon/sysauth.htm @@ -0,0 +1,186 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI and Argon Template + + luci-theme-argon + Copyright 2020 Jerryk + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008-2016 Jo-Philipp Wich + Copyright 2012 David Menting + + MUI: + https://github.com/muicss/mui + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<%+themes/argon/out_header_login%> +<% + local util = require "luci.util" + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local json = require "luci.jsonc" + local sys = require "luci.sys" + local uci = require 'luci.model.uci'.cursor() + + -- Fetch Local Background Media + + local function glob(...) + local iter, code, msg = fs.glob(...) + if iter then + return nutil.consume(iter) + else + return nil, code, msg + end + end + + + local imageTypes = " jpg png gif " + local videoTypes = " mp4 webm " + local allTypes = imageTypes .. videoTypes + local function fetchMedia(path,themeDir) + local backgroundTable = {} + local backgroundCount = 0 + for i, f in ipairs(glob(path)) do + attr = fs.stat(f) + if attr then + local ext = fs.basename(f):match(".+%.(%w+)$") + if ext ~= nil then + ext = ext:lower() + end + if ext ~= nil and string.match(allTypes, " "..ext.." ") ~= nil then + local bg = {} + bg.type = ext + bg.url = themeDir .. fs.basename(f) + table.insert(backgroundTable,bg) + backgroundCount = backgroundCount + 1 + end + end + end + return backgroundTable,backgroundCount + end + local function selectBackground(themeDir) + local bgUrl = media .. "/img/bg1.jpg" + local backgroundType = "Image" + local mimeType = "" + + if fs.access("/etc/config/argon") then + if uci:get_first('argon', 'global', 'bing_background') == "1" then + local bing = sys.exec("/usr/libexec/argon/bing_wallpaper") + if (bing and bing ~= '') then + return bing, "Image", "" + end + end + end + + local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*",themeDir) + if ( backgroundCount > 0 ) then + local currentBg = backgroundTable[math.random(1,backgroundCount)] + bgUrl = currentBg.url + if (string.match(videoTypes, " "..currentBg.type.." ") ~= nil) then + backgroundType = "Video" + mimeType = "video/" .. currentBg.type + end + end + + return bgUrl,backgroundType,mimeType + end + + local boardinfo = util.ubus("system", "board") + local themeDir = media .. "/background/" + local bgUrl,backgroundType,mimeType = selectBackground(themeDir) +%> + +