diff --git a/applications/luci-app-arpbind/Makefile b/applications/luci-app-arpbind/Makefile new file mode 100644 index 000000000000..d8a42d90f995 --- /dev/null +++ b/applications/luci-app-arpbind/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2015 GuoGuo +# Copyright (C) 2025 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for ARP binding +LUCI_DEPENDS:=+ip + +define Package/luci-app-arpbind/conffiles +/etc/config/arpbind +endef + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js b/applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js new file mode 100644 index 000000000000..d9c26237103f --- /dev/null +++ b/applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2015 GuoGuo + * Copyright (C) 2025 ImmortalWrt.org + */ + +'use strict'; +'require form'; +'require network'; +'require view'; + +'require tools.widgets as widgets'; + +return view.extend({ + load: function() { + return Promise.all([ + network.getHostHints() + ]); + }, + + render: function (data) { + let m, s, o; + let hosts = data[0]?.hosts; + let ipaddrs = {}; + + m = new form.Map('arpbind', _('IP/MAC Binding'), + _('ARP is used to convert a network address (e.g. an IPv4 address) to a physical address such as a MAC address.
Here you can add some static ARP binding rules.')); + + s = m.section(form.TableSection, 'arpbind', _('Rules')); + s.addremove = true; + s.anonymous = true; + s.sortable = true; + s.rowcolors = true; + + o = s.option(form.Flag, 'enabled', _('Disable')); + o.enabled = '0'; + o.disabled = '1'; + o.default = o.disabled; + + o = s.option(form.Value, 'ipaddr', _('IP Address')); + o.datatype = 'ipaddr'; + Object.keys(hosts).forEach(function(mac) { + let addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4); + + for (let i = 0; i < addrs.length; i++) + ipaddrs[addrs[i]] = hosts[mac].name || mac; + }); + L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) { + o.value(ipv4, '%s (%s)'.format(ipv4, ipaddrs[ipv4])); + }); + o.rmempty = false; + + o = s.option(form.Value, 'macaddr', _('MAC Address')); + o.datatype = 'macaddr'; + Object.keys(hosts).forEach(function(mac) { + let hint = hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0]; + o.value(mac, hint ? '%s (%s)'.format(mac, hint) : mac); + }); + o.rmempty = false; + + o = s.option(widgets.DeviceSelect, 'ifname', _('Interface')); + o.multiple = false; + o.noaliases = true; + o.nocreate = true; + o.rmempty = false; + + return m.render(); + } +}); diff --git a/applications/luci-app-arpbind/po/templates/arpbind.pot b/applications/luci-app-arpbind/po/templates/arpbind.pot new file mode 100644 index 000000000000..edf0fd1b6de6 --- /dev/null +++ b/applications/luci-app-arpbind/po/templates/arpbind.pot @@ -0,0 +1,38 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:27 +msgid "" +"ARP is used to convert a network address (e.g. an IPv4 address) to a " +"physical address such as a MAC address.
Here you can add some static " +"ARP binding rules." +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:35 +msgid "Disable" +msgstr "" + +#: applications/luci-app-arpbind/root/usr/share/rpcd/acl.d/luci-app-arpbind.json:3 +msgid "Grant UCI access for luci-app-arpbind" +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:40 +msgid "IP Address" +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:26 +#: applications/luci-app-arpbind/root/usr/share/luci/menu.d/luci-app-arpbind.json:3 +msgid "IP/MAC Binding" +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:61 +msgid "Interface" +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:53 +msgid "MAC Address" +msgstr "" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:29 +msgid "Rules" +msgstr "" diff --git a/applications/luci-app-arpbind/po/zh_Hans/arpbind.po b/applications/luci-app-arpbind/po/zh_Hans/arpbind.po new file mode 100644 index 000000000000..53342594b618 --- /dev/null +++ b/applications/luci-app-arpbind/po/zh_Hans/arpbind.po @@ -0,0 +1,53 @@ +msgid "" +msgstr "" +"Project-Id-Version: Luci ARP Bind\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-06-23 20:16+0800\n" +"PO-Revision-Date: 2015-06-23 20:17+0800\n" +"Last-Translator: 981213 \n" +"Language-Team: PandoraBox Team\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.8.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:27 +msgid "" +"ARP is used to convert a network address (e.g. an IPv4 address) to a " +"physical address such as a MAC address.
Here you can add some static " +"ARP binding rules." +msgstr "" +"ARP协议是用于实现网络地址到物理地址转换的协议。
在这里,你可以设置静态" +"ARP绑定规则。" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:35 +msgid "Disable" +msgstr "禁用" + +#: applications/luci-app-arpbind/root/usr/share/rpcd/acl.d/luci-app-arpbind.json:3 +msgid "Grant UCI access for luci-app-arpbind" +msgstr "授予 luci-app-arpbind 访问 UCI 配置的权限" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:40 +msgid "IP Address" +msgstr "IP 地址" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:26 +#: applications/luci-app-arpbind/root/usr/share/luci/menu.d/luci-app-arpbind.json:3 +msgid "IP/MAC Binding" +msgstr "IP/MAC绑定" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:61 +msgid "Interface" +msgstr "接口" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:53 +msgid "MAC Address" +msgstr "MAC 地址" + +#: applications/luci-app-arpbind/htdocs/luci-static/resources/view/arpbind.js:29 +msgid "Rules" +msgstr "规则" diff --git a/applications/luci-app-arpbind/root/etc/config/arpbind b/applications/luci-app-arpbind/root/etc/config/arpbind new file mode 100644 index 000000000000..a98acd8f0689 --- /dev/null +++ b/applications/luci-app-arpbind/root/etc/config/arpbind @@ -0,0 +1,7 @@ + +config arpbind + option enabled '0' + option ipaddr '' + option macaddr '' + option ifname '' + diff --git a/applications/luci-app-arpbind/root/etc/hotplug.d/iface/50-arpbind b/applications/luci-app-arpbind/root/etc/hotplug.d/iface/50-arpbind new file mode 100644 index 000000000000..36dfc74a3c6f --- /dev/null +++ b/applications/luci-app-arpbind/root/etc/hotplug.d/iface/50-arpbind @@ -0,0 +1,4 @@ +#!/bin/sh + +[ "$ACTION" = "ifup" ] && /etc/init.d/arpbind start +exit 0 diff --git a/applications/luci-app-arpbind/root/etc/init.d/arpbind b/applications/luci-app-arpbind/root/etc/init.d/arpbind new file mode 100644 index 000000000000..df19064c9c82 --- /dev/null +++ b/applications/luci-app-arpbind/root/etc/init.d/arpbind @@ -0,0 +1,48 @@ +#!/bin/sh /etc/rc.common +# OpenWrt 静态ARP绑定 启动脚本 +# Copyright (C) 2015 GuoGuo + +START=80 +STOP=20 + +USE_PROCD=1 + +setup_arp() { + local cfg="$1" + local enabled ipaddr macaddr ifname + + config_get_bool enabled "$cfg" "enabled" "1" + [ "$enabled" -eq "1" ] || return 1 + + config_get ipaddr "$cfg" "ipaddr" + config_get macaddr "$cfg" "macaddr" + config_get ifname "$cfg" "ifname" + + if [ -z "$ipaddr" ] || [ -z "$macaddr" ] || [ -z "$ifname" ]; then + return 1 + fi + + ip neigh add "$ipaddr" lladdr "$macaddr" nud permanent dev "$ifname" || \ + ip neigh change "$ipaddr" lladdr "$macaddr" nud permanent dev "$ifname" +} + +start_service() { + config_load "arpbind" + config_foreach setup_arp "arpbind" +} + +stop_service() { + ls "/sys/class/net" | while IFS= read -r ifname; do + ip link set arp off dev "$ifname" + ip link set arp on dev "$ifname" + done +} + +reload_service() { + stop + start +} + +service_triggers() { + procd_add_reload_trigger "arpbind" +} diff --git a/applications/luci-app-arpbind/root/etc/uci-defaults/luci-arpbind b/applications/luci-app-arpbind/root/etc/uci-defaults/luci-arpbind new file mode 100644 index 000000000000..a342e8a7cd7a --- /dev/null +++ b/applications/luci-app-arpbind/root/etc/uci-defaults/luci-arpbind @@ -0,0 +1,8 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@arpbind[-1] + commit ucitrack +EOF + +exit 0 diff --git a/applications/luci-app-arpbind/root/usr/share/luci/menu.d/luci-app-arpbind.json b/applications/luci-app-arpbind/root/usr/share/luci/menu.d/luci-app-arpbind.json new file mode 100644 index 000000000000..d0470be312ca --- /dev/null +++ b/applications/luci-app-arpbind/root/usr/share/luci/menu.d/luci-app-arpbind.json @@ -0,0 +1,14 @@ +{ + "admin/network/arpbind": { + "title": "IP/MAC Binding", + "order": 45, + "action": { + "type": "view", + "path": "arpbind" + }, + "depends": { + "acl": [ "luci-app-arpbind" ], + "uci": { "arpbind": true } + } + } +} diff --git a/applications/luci-app-arpbind/root/usr/share/rpcd/acl.d/luci-app-arpbind.json b/applications/luci-app-arpbind/root/usr/share/rpcd/acl.d/luci-app-arpbind.json new file mode 100644 index 000000000000..e3f5ff248617 --- /dev/null +++ b/applications/luci-app-arpbind/root/usr/share/rpcd/acl.d/luci-app-arpbind.json @@ -0,0 +1,11 @@ +{ + "luci-app-arpbind": { + "description": "Grant UCI access for luci-app-arpbind", + "read": { + "uci": [ "arpbind" ] + }, + "write": { + "uci": [ "arpbind" ] + } + } +} diff --git a/applications/luci-app-diskman/Makefile b/applications/luci-app-diskman/Makefile new file mode 100644 index 000000000000..d64a5e8e7f5d --- /dev/null +++ b/applications/luci-app-diskman/Makefile @@ -0,0 +1,52 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-diskman +PKG_VERSION:=0.2.13 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=lisaac +PKG_LICENSE:=AGPL-3.0 + +LUCI_TITLE:=Disk Manager interface for LuCI +LUCI_DEPENDS:= \ + +luci-compat +blkid +e2fsprogs +parted +smartmontools +dosfstools \ + +kmod-fs-msdos +kmod-fs-ntfs3 +kmod-fs-exfat +exfat-mkfs \ + +exfat-fsck +kmod-nls-cp932 +kmod-nls-cp936 +kmod-nls-cp950 \ + +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 + +define Package/luci-app-diskman/config +config PACKAGE_$(PKG_NAME)_INCLUDE_btrfs_progs + depends on PACKAGE_$(PKG_NAME) + bool "Include btrfs-progs" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_lsblk + depends on PACKAGE_$(PKG_NAME) + bool "Include lsblk" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_mdadm + depends on PACKAGE_$(PKG_NAME) + 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_linears + depends on PACKAGE_$(PKG_NAME)_INCLUDE_mdadm + bool "Include kmod-md-linear" + default n +endef + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-diskman/luasrc/controller/diskman.lua b/applications/luci-app-diskman/luasrc/controller/diskman.lua new file mode 100644 index 000000000000..98b2e646857a --- /dev/null +++ b/applications/luci-app-diskman/luasrc/controller/diskman.lua @@ -0,0 +1,151 @@ +--[[ +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 attr = { } + local dm = require "luci.model.diskman" + local cmd = io.popen(dm.command.smartctl .. " -H -A -i /dev/%s" % dev) + if cmd then + local content = cmd:read("*all") + local ln + cmd:close() + if content:match("NVMe Version:")then + for ln in string.gmatch(content,'[^\r\n]+') do + if ln:match("^(.-):%s+(.+)") then + local key, value = ln:match("^(.-):%s+(.+)") + attr[#attr+1]= { + key = key, + value = value + } + end + end + else + for ln in string.gmatch(content,'[^\r\n]+') do + if 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 + end + luci.http.prepare_content("application/json") + luci.http.write_json(attr) +end \ No newline at end of file diff --git a/applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua b/applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua new file mode 100644 index 000000000000..0060078536f0 --- /dev/null +++ b/applications/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/applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua b/applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua new file mode 100644 index 000000000000..3382afff8dec --- /dev/null +++ b/applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua @@ -0,0 +1,360 @@ +--[[ +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_status", translate("Health") .. "
" .. translate("Status")) +-- d:option(DummyValue, "status", translate("Status")) + +-- local btn_eject = d:option(Button, "_eject") +-- btn_eject.template = "diskman/cbi/disabled_button" +-- btn_eject.inputstyle = "remove" +-- btn_eject.inputtitle = translate("Eject") +-- btn_eject.forcewrite = true +-- btn_eject.write = function(self, section, value) +-- local dev = section +-- local disk_info = dm.get_disk_info(dev, true) +-- if disk_info.p_table:match("Raid") then +-- m.errmessage = translate("Unsupported raid reject!") +-- return +-- end +-- 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 + +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 = dm.find_free_md_device() + 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("grep -m1 'Personalities :' /proc/mdstat") + if valid_raid:match("%[linear%]") then + r_level:value("linear", "Linear") + end + if valid_raid:match("%[raid5%]") then + r_level:value("5", "Raid 5") + end + if valid_raid:match("%[raid6%]") then + 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/applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua b/applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua new file mode 100644 index 000000000000..348a617a6c64 --- /dev/null +++ b/applications/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 \ No newline at end of file diff --git a/applications/luci-app-diskman/luasrc/model/diskman.lua b/applications/luci-app-diskman/luasrc/model/diskman.lua new file mode 100644 index 000000000000..ec3d60cd287d --- /dev/null +++ b/applications/luci-app-diskman/luasrc/model/diskman.lua @@ -0,0 +1,743 @@ +--[[ +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 + if val ~= "-" then + smart_info.temp = (val:match("(%d+)") or "?") .. "°C" + end + 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") or device:match("vd") 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/" .. partition_temp["name"] .. " -no fstype") or ""):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.logic_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 or result + 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+$") + or dev:match("^vd[a-z]$") + 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.fat", option = "-F 32" }, + exfat = { cmd = "mkfs.exfat", option = "" }, + hfsplus = { cmd = "mkhfs", option = "-f" }, + ntfs = { cmd = "mkfs.ntfs", 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.find_free_md_device = function() + for num=0,127 do + local md = io.open("/dev/md"..tostring(num), "r") + if md == nil then + return "/dev/md"..tostring(num) + else + io.close(md) + end + end + return nil +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 + rname = d.find_free_md_device() + if rname == nil then return "ERR: Cannot find free md device" end + 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/applications/luci-app-diskman/luasrc/view/diskman/cbi/disabled_button.htm b/applications/luci-app-diskman/luasrc/view/diskman/cbi/disabled_button.htm new file mode 100644 index 000000000000..1ad4eca3be42 --- /dev/null +++ b/applications/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/applications/luci-app-diskman/luasrc/view/diskman/cbi/format_button.htm b/applications/luci-app-diskman/luasrc/view/diskman/cbi/format_button.htm new file mode 100644 index 000000000000..18e306e27f70 --- /dev/null +++ b/applications/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/applications/luci-app-diskman/luasrc/view/diskman/cbi/inlinebutton.htm b/applications/luci-app-diskman/luasrc/view/diskman/cbi/inlinebutton.htm new file mode 100644 index 000000000000..b1b193257197 --- /dev/null +++ b/applications/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/applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm b/applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm new file mode 100644 index 000000000000..69aa65e003cc --- /dev/null +++ b/applications/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/applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm b/applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm new file mode 100644 index 000000000000..72a21f50ecbe --- /dev/null +++ b/applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm @@ -0,0 +1,87 @@ +<% 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 + + if self.message then + %>
<%=self.message%>
<% + end + + if self.errmessage then + %>
<%=self.errmessage%>
<% + end + + self:render_children() + + %>
<% + + 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/applications/luci-app-diskman/luasrc/view/diskman/disk_info.htm b/applications/luci-app-diskman/luasrc/view/diskman/disk_info.htm new file mode 100644 index 000000000000..10ba3e7c28cb --- /dev/null +++ b/applications/luci-app-diskman/luasrc/view/diskman/disk_info.htm @@ -0,0 +1,110 @@ + diff --git a/applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm b/applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm new file mode 100644 index 000000000000..100541fe9d21 --- /dev/null +++ b/applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm @@ -0,0 +1,138 @@ + + \ No newline at end of file diff --git a/applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm b/applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm new file mode 100644 index 000000000000..ffb4f7d9114d --- /dev/null +++ b/applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm @@ -0,0 +1,78 @@ + + + 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/applications/luci-app-diskman/po/pl/diskman.po b/applications/luci-app-diskman/po/pl/diskman.po new file mode 100644 index 000000000000..e9627d453509 --- /dev/null +++ b/applications/luci-app-diskman/po/pl/diskman.po @@ -0,0 +1,514 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2023-04-21 02:03+0000\n" +"Last-Translator: lisaac \n" +"Language-Team: Polski (Polish) \n" +"Language: pl\n" +"MIME-Version: 1.0\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.1-dev\n" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:5 +msgid "-- Please choose --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:6 +msgid "-- custom --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:95 +msgid "Active" +msgstr "Aktywny" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:61 +msgid "Attrbute" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:58 +msgid "Back to Overview" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:104 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:27 +msgid "Btrfs Info" +msgstr "Informacja o Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:314 +msgid "Btrfs Label" +msgstr "Etykieta Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:327 +msgid "Btrfs Member" +msgstr "Członek Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:318 +msgid "Btrfs Raid Level" +msgstr "Poziom Raid Btrfs" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:62 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Cancel" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:72 +msgid "Collecting data..." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:129 +msgid "Create" +msgstr "Utwórz" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:344 +msgid "Create Btrfs" +msgstr "Utwórz Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:295 +msgid "Create Raid" +msgstr "Utwórz RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:241 +msgid "Creation" +msgstr "Kreator" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:30 +msgid "Data" +msgstr "Data" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector" +msgstr "" +"Sektory wyrównywane są do wielokrotności 2048, sektor końcowy można podać " +"jako rozmiar w postaci +size{b,k,m,g,t}" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:114 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:118 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:127 +msgid "Delete" +msgstr "Usuń" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:184 +msgid "Destination Path (optional)" +msgstr "Ścieżka docelowa (opcjonalnie)" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:120 +msgid "Device" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:28 +msgid "Device Info" +msgstr "Informacja o urządzeniu" + +#: applications/luci-app-diskman/luasrc/controller/diskman.lua:24 +msgid "Disk Man" +msgstr "Menadżer dysków" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "DiskMan" +msgstr "Menadżer dysków" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:34 +msgid "Disks" +msgstr "Dyski" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:52 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:91 +msgid "Eject" +msgstr "Wysuń" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:136 +msgid "End Sector" +msgstr "Sektor końcowy" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:139 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:184 +msgid "File System" +msgstr "System plików" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:62 +msgid "Flag" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:199 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format" +msgstr "Formatuj" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format partation:" +msgstr "Format partycji:" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:106 +msgid "Formatting.." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:160 +msgid "Free Space" +msgstr "Wolna przestrzeń" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:59 +msgid "Health" +msgstr "Kondycja" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:53 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:60 +msgid "ID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:320 +msgid "Invalid End Sector!" +msgstr "Nieprawidłowy sektor końcowy!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:301 +msgid "Invalid Start Sector!" +msgstr "Nieprawidłowy sektor początkowy!" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:57 +msgid "KEY" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:36 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:106 +msgid "Label" +msgstr "Etykieta" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:51 +msgid "Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +msgid "Manage Btrfs" +msgstr "Zarządzaj Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "Manage Disks over LuCI." +msgstr "Zarządzaj dyskami przez LuCI." + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:29 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:94 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:107 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:52 +msgid "Members" +msgstr "Członkowie" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:31 +msgid "Metadata" +msgstr "Metadata" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:38 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:32 +msgid "Model" +msgstr "Model urządzenia" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:210 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:214 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:224 +msgid "Mount" +msgstr "Montuj" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:155 +msgid "Mount Options" +msgstr "Opcje montowania" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:119 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:184 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:162 +msgid "Mount Point" +msgstr "Punkt montowania" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Multiple Devices Btrfs Creation" +msgstr "Kreator urządzeń Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:124 +msgid "Name" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:279 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:285 +msgid "New" +msgstr "Nowa" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:166 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:192 +msgid "New Snapshot" +msgstr "Nowy obraz" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:43 +msgid "No Attrbute to display." +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:17 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:19 +msgid "One or more required fields have no value!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:56 +msgid "Otime" +msgstr "Otime" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Disk over LuCI." +msgstr "Zarządzaj partycjami przez LuCI." + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Management" +msgstr "Menadżer partycji" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:43 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:92 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:36 +msgid "Partition Table" +msgstr "Tablica partycji" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:352 +msgid "Partition not exists!" +msgstr "Partycja nie istnieje!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Partitions Info" +msgstr "Informacja o partycjach" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:58 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:37 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:31 +msgid "Path" +msgstr "Ścieżka" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:206 +msgid "Please input Source Path of snapshot, Source Path must start with '/'" +msgstr "" +"Proszę podać ścieżkę źródłową dla obrazu, ścieżka musi zaczynać się od '/'" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:133 +msgid "Please input Subvolume Path, Subvolume must start with '/'" +msgstr "" +"Proszę podać ścieżkę dla sub-wolumenu, sub-wolumen musi zaczynać się od '/'" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:103 +msgid "Please select file system!" +msgstr "Proszę wybrać system plików!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID Creation" +msgstr "Kreator RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:87 +msgid "RAID Devices" +msgstr "Urządzenia RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:90 +msgid "RAID mode" +msgstr "Tryb RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:255 +msgid "Raid Level" +msgstr "Poziom RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:278 +msgid "Raid Member" +msgstr "Członek RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:250 +msgid "Raid Name" +msgstr "Nazwa RAID" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:68 +msgid "Raw" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "Readonly" +msgstr "Tylko do odczytu" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:276 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:348 +msgid "Remove" +msgstr "Wysuń" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:20 +msgid "Rescan Disks" +msgstr "Skanuj dyski" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:76 +msgid "Reset" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:56 +msgid "Rotation Rate" +msgstr "Obroty" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:53 +msgid "S.M.A.R.T Attrbutes" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:44 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:55 +msgid "SATA Version" +msgstr "Wersja SATA" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:35 +msgid "Sector Size" +msgstr "Rozmiar sektora" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:39 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:33 +msgid "Serial Number" +msgstr "Numer seryjny" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:75 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:82 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:86 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:93 +msgid "Set Default" +msgstr "Ustaw domyślnie" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:32 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:40 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:91 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:155 +msgid "Size" +msgstr "Rozmiar" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:67 +msgid "Skip" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:57 +msgid "Snapshots" +msgstr "Obrazy" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "Source Path" +msgstr "Ścieżka źródłowa" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:125 +msgid "Start Sector" +msgstr "Sektor początkowy" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:93 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:58 +msgid "Status" +msgstr "Status" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:52 +msgid "SubVolumes" +msgstr "Sub-wolumeny" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:71 +msgid "Submit" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:41 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:54 +msgid "Temp" +msgstr "Temperatura" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "The path where you want to store the snapshot" +msgstr "Ścieżka w której chcesz przechowywać obraz" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "The source path for create the snapshot" +msgstr "Ścieżka źródłowa do utworzenia obrazu" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:65 +msgid "Thresh" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:54 +msgid "Top Level" +msgstr "Top Level" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:157 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:66 +msgid "Type" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:28 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:55 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:105 +msgid "UUID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:217 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:228 +msgid "Umount" +msgstr "Odmontuj" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:58 +msgid "Unsupported raid reject!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:42 +msgid "Update" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:67 +msgid "Updated" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:35 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:161 +msgid "Usage" +msgstr "Wykorzystane" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:33 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:159 +msgid "Used" +msgstr "Zajęte" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:58 +msgid "VALUE" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:63 +msgid "Value" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:74 +msgid "" +"Warnning !! \\nTHIS WILL OVERWRITE EXISTING PARTITIONS!! \\nModify the " +"partition table?" +msgstr "" +"Ostrzeżenie !! \n" +"ISTNIEJĄCE PARTYCJE ZOSTANĄ NADPISANE!! \n" +"Zmodyfikować tablicę partycji?" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:64 +msgid "Worst" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:63 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:99 +msgid "is in use! please unmount it first!" +msgstr "aktualnie jest w użyciu, proszę najpierw odmontować!" + +#~ msgid "Partition NOT found!" +#~ msgstr "Nie znaleziono partycji!" + +#~ msgid "Filesystem NOT support!" +#~ msgstr "System plików nie jest obsługiwany!" diff --git a/applications/luci-app-diskman/po/templates/diskman.pot b/applications/luci-app-diskman/po/templates/diskman.pot new file mode 100644 index 000000000000..4a503591b7b1 --- /dev/null +++ b/applications/luci-app-diskman/po/templates/diskman.pot @@ -0,0 +1,490 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:5 +msgid "-- Please choose --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:6 +msgid "-- custom --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:95 +msgid "Active" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:61 +msgid "Attrbute" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:58 +msgid "Back to Overview" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:104 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:27 +msgid "Btrfs Info" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:314 +msgid "Btrfs Label" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:327 +msgid "Btrfs Member" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:318 +msgid "Btrfs Raid Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:62 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Cancel" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:72 +msgid "Collecting data..." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:129 +msgid "Create" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:344 +msgid "Create Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:295 +msgid "Create Raid" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:241 +msgid "Creation" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:30 +msgid "Data" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Default 2048 sector alignment, support +size{b,k,m,g,t} in End Sector" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:114 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:118 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:127 +msgid "Delete" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:184 +msgid "Destination Path (optional)" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:120 +msgid "Device" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:28 +msgid "Device Info" +msgstr "" + +#: applications/luci-app-diskman/luasrc/controller/diskman.lua:24 +msgid "Disk Man" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "DiskMan" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:34 +msgid "Disks" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:52 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:91 +msgid "Eject" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:136 +msgid "End Sector" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:139 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:184 +msgid "File System" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:62 +msgid "Flag" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:199 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format partation:" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:106 +msgid "Formatting.." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:160 +msgid "Free Space" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:59 +msgid "Health" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:53 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:60 +msgid "ID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:320 +msgid "Invalid End Sector!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:301 +msgid "Invalid Start Sector!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:57 +msgid "KEY" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:36 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:106 +msgid "Label" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:51 +msgid "Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +msgid "Manage Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "Manage Disks over LuCI." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:29 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:94 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:107 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:52 +msgid "Members" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:31 +msgid "Metadata" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:38 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:32 +msgid "Model" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:210 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:214 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:224 +msgid "Mount" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:155 +msgid "Mount Options" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:119 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:184 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:162 +msgid "Mount Point" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Multiple Devices Btrfs Creation" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:124 +msgid "Name" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:279 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:285 +msgid "New" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:166 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:192 +msgid "New Snapshot" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:43 +msgid "No Attrbute to display." +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:17 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:19 +msgid "One or more required fields have no value!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:56 +msgid "Otime" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Disk over LuCI." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Management" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:43 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:92 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:36 +msgid "Partition Table" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:352 +msgid "Partition not exists!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Partitions Info" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:58 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:37 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:31 +msgid "Path" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:206 +msgid "Please input Source Path of snapshot, Source Path must start with '/'" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:133 +msgid "Please input Subvolume Path, Subvolume must start with '/'" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:103 +msgid "Please select file system!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID Creation" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:87 +msgid "RAID Devices" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:90 +msgid "RAID mode" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:255 +msgid "Raid Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:278 +msgid "Raid Member" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:250 +msgid "Raid Name" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:68 +msgid "Raw" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "Readonly" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:276 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:348 +msgid "Remove" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:20 +msgid "Rescan Disks" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:76 +msgid "Reset" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:56 +msgid "Rotation Rate" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:53 +msgid "S.M.A.R.T Attrbutes" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:44 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:55 +msgid "SATA Version" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:35 +msgid "Sector Size" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:39 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:33 +msgid "Serial Number" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:75 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:82 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:86 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:93 +msgid "Set Default" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:32 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:40 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:91 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:155 +msgid "Size" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:67 +msgid "Skip" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:57 +msgid "Snapshots" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "Source Path" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:125 +msgid "Start Sector" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:93 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:58 +msgid "Status" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:52 +msgid "SubVolumes" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:71 +msgid "Submit" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:41 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:54 +msgid "Temp" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "The path where you want to store the snapshot" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "The source path for create the snapshot" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:65 +msgid "Thresh" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:54 +msgid "Top Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:157 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:66 +msgid "Type" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:28 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:55 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:105 +msgid "UUID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:217 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:228 +msgid "Umount" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:58 +msgid "Unsupported raid reject!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:42 +msgid "Update" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:67 +msgid "Updated" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:35 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:161 +msgid "Usage" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:33 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:159 +msgid "Used" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:58 +msgid "VALUE" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:63 +msgid "Value" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:74 +msgid "" +"Warnning !! \\nTHIS WILL OVERWRITE EXISTING PARTITIONS!! \\nModify the " +"partition table?" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:64 +msgid "Worst" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:63 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:99 +msgid "is in use! please unmount it first!" +msgstr "" diff --git a/applications/luci-app-diskman/po/zh_Hans/diskman.po b/applications/luci-app-diskman/po/zh_Hans/diskman.po new file mode 100644 index 000000000000..c8558f1a69ed --- /dev/null +++ b/applications/luci-app-diskman/po/zh_Hans/diskman.po @@ -0,0 +1,511 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2023-04-21 02:03+0000\n" +"Last-Translator: muink \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\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.1-dev\n" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:5 +msgid "-- Please choose --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:6 +msgid "-- custom --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:95 +msgid "Active" +msgstr "活动" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:61 +msgid "Attrbute" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:58 +msgid "Back to Overview" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:104 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:27 +msgid "Btrfs Info" +msgstr "Btrfs 信息" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:314 +msgid "Btrfs Label" +msgstr "Btrfs 卷标" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:327 +msgid "Btrfs Member" +msgstr "Btrfs 阵列成员" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:318 +msgid "Btrfs Raid Level" +msgstr "Btrfs Raid 级别" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:62 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Cancel" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:72 +msgid "Collecting data..." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:129 +msgid "Create" +msgstr "创建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:344 +msgid "Create Btrfs" +msgstr "创建 Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:295 +msgid "Create Raid" +msgstr "创建 RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:241 +msgid "Creation" +msgstr "创建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:30 +msgid "Data" +msgstr "数据" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +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" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:114 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:118 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:127 +msgid "Delete" +msgstr "删除" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:184 +msgid "Destination Path (optional)" +msgstr "目标目录(可选)" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:120 +msgid "Device" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:28 +msgid "Device Info" +msgstr "设备信息" + +#: applications/luci-app-diskman/luasrc/controller/diskman.lua:24 +msgid "Disk Man" +msgstr "磁盘管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "DiskMan" +msgstr "DiskMan 磁盘管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:34 +msgid "Disks" +msgstr "磁盘" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:52 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:91 +msgid "Eject" +msgstr "弹出" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:136 +msgid "End Sector" +msgstr "中止扇区" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:139 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:184 +msgid "File System" +msgstr "文件系统" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:62 +msgid "Flag" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:199 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format" +msgstr "格式化" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format partation:" +msgstr "格式化分区:" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:106 +msgid "Formatting.." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:160 +msgid "Free Space" +msgstr "空闲空间" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:59 +msgid "Health" +msgstr "健康" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:53 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:60 +msgid "ID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:320 +msgid "Invalid End Sector!" +msgstr "无效的终止扇区!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:301 +msgid "Invalid Start Sector!" +msgstr "无效的起始扇区!" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:57 +msgid "KEY" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:36 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:106 +msgid "Label" +msgstr "卷标" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:51 +msgid "Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +msgid "Manage Btrfs" +msgstr "Btrfs 管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "Manage Disks over LuCI." +msgstr "通过 LuCI 管理磁盘" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:29 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:94 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:107 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:52 +msgid "Members" +msgstr "成员" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:31 +msgid "Metadata" +msgstr "元数据" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:38 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:32 +msgid "Model" +msgstr "型号" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:210 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:214 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:224 +msgid "Mount" +msgstr "挂载" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:155 +msgid "Mount Options" +msgstr "挂载选项" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:119 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:184 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:162 +msgid "Mount Point" +msgstr "挂载点" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Multiple Devices Btrfs Creation" +msgstr "Btrfs 阵列创建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:124 +msgid "Name" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:279 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:285 +msgid "New" +msgstr "新建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:166 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:192 +msgid "New Snapshot" +msgstr "新建快照" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:43 +msgid "No Attrbute to display." +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:17 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:19 +msgid "One or more required fields have no value!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:56 +msgid "Otime" +msgstr "创建时间" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Disk over LuCI." +msgstr "通过LuCI分区磁盘。" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Management" +msgstr "分区管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:43 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:92 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:36 +msgid "Partition Table" +msgstr "分区表" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:352 +msgid "Partition not exists!" +msgstr "分区不存在!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Partitions Info" +msgstr "分区信息" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:58 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:37 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:31 +msgid "Path" +msgstr "路径" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:206 +msgid "Please input Source Path of snapshot, Source Path must start with '/'" +msgstr "请输入快照源路径,源路径必须以'/'开头" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:133 +msgid "Please input Subvolume Path, Subvolume must start with '/'" +msgstr "请输入子卷路径,子卷路径必须以'/'开头" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:103 +msgid "Please select file system!" +msgstr "请选择文件系统!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID Creation" +msgstr "RAID 创建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:87 +msgid "RAID Devices" +msgstr "RAID 设备" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:90 +msgid "RAID mode" +msgstr "RAID 模式" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:255 +msgid "Raid Level" +msgstr "RAID 级别" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:278 +msgid "Raid Member" +msgstr "磁盘阵列成员" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:250 +msgid "Raid Name" +msgstr "RAID 名称" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:68 +msgid "Raw" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "Readonly" +msgstr "只读" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:276 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:348 +msgid "Remove" +msgstr "移除" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:20 +msgid "Rescan Disks" +msgstr "重新扫描磁盘" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:76 +msgid "Reset" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:56 +msgid "Rotation Rate" +msgstr "转速" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:53 +msgid "S.M.A.R.T Attrbutes" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:44 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:55 +msgid "SATA Version" +msgstr "SATA 版本" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:35 +msgid "Sector Size" +msgstr "扇区/物理扇区大小" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:39 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:33 +msgid "Serial Number" +msgstr "序列号" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:75 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:82 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:86 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:93 +msgid "Set Default" +msgstr "默认子卷" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:32 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:40 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:91 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:155 +msgid "Size" +msgstr "容量" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:67 +msgid "Skip" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:57 +msgid "Snapshots" +msgstr "快照" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "Source Path" +msgstr "源目录" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:125 +msgid "Start Sector" +msgstr "起始扇区" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:93 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:58 +msgid "Status" +msgstr "状态" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:52 +msgid "SubVolumes" +msgstr "子卷" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:71 +msgid "Submit" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:41 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:54 +msgid "Temp" +msgstr "温度" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "The path where you want to store the snapshot" +msgstr "存放快照数据目录" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "The source path for create the snapshot" +msgstr "创建快照的源数据目录" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:65 +msgid "Thresh" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:54 +msgid "Top Level" +msgstr "父ID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:157 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:66 +msgid "Type" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:28 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:55 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:105 +msgid "UUID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:217 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:228 +msgid "Umount" +msgstr "卸载" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:58 +msgid "Unsupported raid reject!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:42 +msgid "Update" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:67 +msgid "Updated" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:35 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:161 +msgid "Usage" +msgstr "用量" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:33 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:159 +msgid "Used" +msgstr "已使用" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:58 +msgid "VALUE" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:63 +msgid "Value" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:74 +msgid "" +"Warnning !! \\nTHIS WILL OVERWRITE EXISTING PARTITIONS!! \\nModify the " +"partition table?" +msgstr "" +"警告!!\n" +"此操作会覆盖现有分区\n" +"确定修改分区表?" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:64 +msgid "Worst" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:63 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:99 +msgid "is in use! please unmount it first!" +msgstr "正在被使用!请先卸载!" + +#~ msgid "Partition NOT found!" +#~ msgstr "分区未找到!" + +#~ msgid "Filesystem NOT support!" +#~ msgstr "文件系统不支持!" diff --git a/applications/luci-app-diskman/po/zh_Hant/diskman.po b/applications/luci-app-diskman/po/zh_Hant/diskman.po new file mode 100644 index 000000000000..e145e397cbb2 --- /dev/null +++ b/applications/luci-app-diskman/po/zh_Hant/diskman.po @@ -0,0 +1,512 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2023-04-21 02:03+0000\n" +"Last-Translator: muink \n" +"Language-Team: Chinese (Traditional) \n" +"Language: zh_Hant\n" +"MIME-Version: 1.0\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.1-dev\n" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:5 +msgid "-- Please choose --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:6 +msgid "-- custom --" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:95 +msgid "Active" +msgstr "活躍" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:61 +msgid "Attrbute" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:58 +msgid "Back to Overview" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:104 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Btrfs" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:27 +msgid "Btrfs Info" +msgstr "Btrfs 信息" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:314 +msgid "Btrfs Label" +msgstr "Btrfs 卷標" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:327 +msgid "Btrfs Member" +msgstr "Btrfs 陣列成員" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:318 +msgid "Btrfs Raid Level" +msgstr "Btrfs Raid 等級" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:62 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Cancel" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:72 +msgid "Collecting data..." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:129 +msgid "Create" +msgstr "創建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:344 +msgid "Create Btrfs" +msgstr "創建 Btrfs" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:295 +msgid "Create Raid" +msgstr "創建 RAID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:241 +msgid "Creation" +msgstr "創建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:30 +msgid "Data" +msgstr "數據" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +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" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:114 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:118 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:127 +msgid "Delete" +msgstr "刪除" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:184 +msgid "Destination Path (optional)" +msgstr "目標目錄(可選)" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:120 +msgid "Device" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:28 +msgid "Device Info" +msgstr "裝置信息" + +#: applications/luci-app-diskman/luasrc/controller/diskman.lua:24 +msgid "Disk Man" +msgstr "硬碟管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "DiskMan" +msgstr "DiskMan 硬碟管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:34 +msgid "Disks" +msgstr "硬碟" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:52 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:91 +msgid "Eject" +msgstr "彈出" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:136 +msgid "End Sector" +msgstr "結束磁區" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:139 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:184 +msgid "File System" +msgstr "文件系統" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:62 +msgid "Flag" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:199 +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format" +msgstr "格式化" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:132 +msgid "Format partation:" +msgstr "格式化分割區:" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:106 +msgid "Formatting.." +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:160 +msgid "Free Space" +msgstr "空閒空間" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:59 +msgid "Health" +msgstr "健康" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:53 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:60 +msgid "ID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:320 +msgid "Invalid End Sector!" +msgstr "無效的結束磁區!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:301 +msgid "Invalid Start Sector!" +msgstr "無效的起始磁區!" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:57 +msgid "KEY" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:36 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:106 +msgid "Label" +msgstr "卷標" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:51 +msgid "Level" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:19 +msgid "Manage Btrfs" +msgstr "Btrfs 管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:11 +msgid "Manage Disks over LuCI." +msgstr "通过 LuCI 管理硬碟" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:29 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:94 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:107 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:52 +msgid "Members" +msgstr "成員" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:31 +msgid "Metadata" +msgstr "元數據" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:38 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:32 +msgid "Model" +msgstr "型號" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:210 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:214 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:224 +msgid "Mount" +msgstr "掛載" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:155 +msgid "Mount Options" +msgstr "掛載選項" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:119 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:184 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:162 +msgid "Mount Point" +msgstr "掛載點" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:244 +msgid "Multiple Devices Btrfs Creation" +msgstr "Btrfs 陣列創建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:124 +msgid "Name" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:279 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:285 +msgid "New" +msgstr "新建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:166 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:192 +msgid "New Snapshot" +msgstr "新建快照" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:43 +msgid "No Attrbute to display." +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:17 +msgid "One or more fields contain invalid values!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xnullsection.htm:19 +msgid "One or more required fields have no value!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:56 +msgid "Otime" +msgstr "創建時間" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Disk over LuCI." +msgstr "通過 LuCI 分割硬碟。" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:17 +msgid "Partition Management" +msgstr "分割區管理" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:43 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:92 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:36 +msgid "Partition Table" +msgstr "分割區表" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:352 +msgid "Partition not exists!" +msgstr "分割區不存在!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:121 +msgid "Partitions Info" +msgstr "分割區信息" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:58 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:37 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:31 +msgid "Path" +msgstr "路徑" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:206 +msgid "Please input Source Path of snapshot, Source Path must start with '/'" +msgstr "請輸入快照源路径,源路径必須以'/'開頭" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:133 +msgid "Please input Subvolume Path, Subvolume must start with '/'" +msgstr "請輸入子卷路径,子卷路径必須以'/'開頭" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:103 +msgid "Please select file system!" +msgstr "請選擇文件系統!" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:243 +msgid "RAID Creation" +msgstr "RAID 創建" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:87 +msgid "RAID Devices" +msgstr "RAID 裝置" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:90 +msgid "RAID mode" +msgstr "RAID 模式" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:255 +msgid "Raid Level" +msgstr "RAID 等級" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:278 +msgid "Raid Member" +msgstr "硬碟陣列成員" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:250 +msgid "Raid Name" +msgstr "RAID 名稱" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:68 +msgid "Raw" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "Readonly" +msgstr "只讀" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:89 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:276 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:348 +msgid "Remove" +msgstr "移除" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:20 +msgid "Rescan Disks" +msgstr "重新掃描硬碟" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:76 +msgid "Reset" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:56 +msgid "Rotation Rate" +msgstr "轉速" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:53 +msgid "S.M.A.R.T Attrbutes" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:44 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:55 +msgid "SATA Version" +msgstr "SATA 版本" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:35 +msgid "Sector Size" +msgstr "磁區/物理磁區大小" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:39 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:33 +msgid "Serial Number" +msgstr "序列號" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:75 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:82 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:86 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:93 +msgid "Set Default" +msgstr "默認子卷" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:32 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:40 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:91 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:34 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:155 +msgid "Size" +msgstr "容量" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:67 +msgid "Skip" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:57 +msgid "Snapshots" +msgstr "快照" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "Source Path" +msgstr "源目錄" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:125 +msgid "Start Sector" +msgstr "起始磁區" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:46 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:93 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:58 +msgid "Status" +msgstr "狀態" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:52 +msgid "SubVolumes" +msgstr "子卷" + +#: applications/luci-app-diskman/luasrc/view/diskman/cbi/xsimpleform.htm:71 +msgid "Submit" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:41 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:54 +msgid "Temp" +msgstr "溫度" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:175 +msgid "The path where you want to store the snapshot" +msgstr "存放快照的數據目錄" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:168 +msgid "The source path for create the snapshot" +msgstr "創建快照的源數據目錄" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:65 +msgid "Thresh" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:54 +msgid "Top Level" +msgstr "父 ID" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:157 +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:66 +msgid "Type" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:28 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:55 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:105 +msgid "UUID" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:217 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:228 +msgid "Umount" +msgstr "卸載" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:58 +msgid "Unsupported raid reject!" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:42 +msgid "Update" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:67 +msgid "Updated" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:35 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:110 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:161 +msgid "Usage" +msgstr "用量" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/btrfs.lua:33 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:159 +msgid "Used" +msgstr "已使用" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:58 +msgid "VALUE" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:63 +msgid "Value" +msgstr "" + +#: applications/luci-app-diskman/luasrc/view/diskman/partition_info.htm:74 +msgid "" +"Warnning !! \\nTHIS WILL OVERWRITE EXISTING PARTITIONS!! \\nModify the " +"partition table?" +msgstr "" +"警告!!\n" +"此操作会覆蓋現有分割區\n" +"確定修改分割區表?" + +#: applications/luci-app-diskman/luasrc/view/diskman/smart_detail.htm:64 +msgid "Worst" +msgstr "" + +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/disks.lua:63 +#: applications/luci-app-diskman/luasrc/model/cbi/diskman/partition.lua:99 +msgid "is in use! please unmount it first!" +msgstr "正在被使用!請先卸載!" + +#~ msgid "Partition NOT found!" +#~ msgstr "分割區未找到!" + +#~ msgid "Filesystem NOT support!" +#~ msgstr "文件系統不支持!" diff --git a/applications/luci-app-docker/Makefile b/applications/luci-app-docker/Makefile new file mode 100644 index 000000000000..1133ae4808d7 --- /dev/null +++ b/applications/luci-app-docker/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Luci for Docker-CE +LUCI_DEPENDS:=+docker +dockerd +e2fsprogs +fdisk +LUCI_PKGARCH:=all +PKG_VERSION:=1 +PKG_RELEASE:=12 + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-docker/luasrc/controller/docker.lua b/applications/luci-app-docker/luasrc/controller/docker.lua new file mode 100644 index 000000000000..01a5b6cd170e --- /dev/null +++ b/applications/luci-app-docker/luasrc/controller/docker.lua @@ -0,0 +1,20 @@ +module("luci.controller.docker", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/docker") then + return + end + + local page = entry({"admin", "services", "docker"}, cbi("docker"), _("Docker CE Container"), 199) + page.dependent = true + page.acl_depends = { "luci-app-docker" } + + entry({"admin", "services", "docker", "status"}, call("act_status")).leaf = true +end + +function act_status() + local e = {} + e.running = luci.sys.call("pgrep /usr/bin/dockerd >/dev/null") == 0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/applications/luci-app-docker/luasrc/model/cbi/docker.lua b/applications/luci-app-docker/luasrc/model/cbi/docker.lua new file mode 100644 index 000000000000..7896a32cf9f0 --- /dev/null +++ b/applications/luci-app-docker/luasrc/model/cbi/docker.lua @@ -0,0 +1,23 @@ +local running = (luci.sys.call("pidof portainer >/dev/null") == 0) +local button = "" + +if running then + button = "      


" +end + +m = Map("docker", "Docker CE", translate("Docker is a set of platform-as-a-service (PaaS) products that use OS-level virtualization to deliver software in packages called containers.") .. button) + +m:section(SimpleSection).template = "docker/docker_status" + +s = m:section(TypedSection, "docker") +s.anonymous = true + +wan_mode = s:option(Flag, "wan_mode", translate("Enable WAN access Dokcer")) +wan_mode.description = translate("Enable WAN access docker mapped ports") +wan_mode.default = 0 +wan_mode.rmempty = false + +o = s:option(DummyValue, "readme", translate(" ")) +o.description = translate(""..translate("Download DockerReadme.pdf").."") + +return m diff --git a/applications/luci-app-docker/luasrc/view/docker/docker_status.htm b/applications/luci-app-docker/luasrc/view/docker/docker_status.htm new file mode 100644 index 000000000000..f3cf6b7610f5 --- /dev/null +++ b/applications/luci-app-docker/luasrc/view/docker/docker_status.htm @@ -0,0 +1,22 @@ + + +
+

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

+
diff --git a/applications/luci-app-docker/po/zh_Hans/docker.po b/applications/luci-app-docker/po/zh_Hans/docker.po new file mode 100644 index 000000000000..85363c44baf2 --- /dev/null +++ b/applications/luci-app-docker/po/zh_Hans/docker.po @@ -0,0 +1,39 @@ +msgid "" +msgstr "" +"Project-Id-Version: Luci ARP Bind\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-06-23 20:16+0800\n" +"PO-Revision-Date: 2015-06-23 20:17+0800\n" +"Last-Translator: coolsnowwolf \n" +"Language-Team: PandoraBox Team\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.8.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +msgid "Docker CE Container" +msgstr "Docker CE 容器" + +msgid "Open Portainer Docker Admin" +msgstr "打开 Portainer Docker 管理页面" + +msgid "Docker is a set of platform-as-a-service (PaaS) products that use OS-level virtualization to deliver software in packages called containers." +msgstr "Docker是一组平台即服务(platform-as-a-service,PaaS)产品,它使用操作系统级容器虚拟化来交付软件包。" + +msgid "Enable WAN access Dokcer" +msgstr "允许 WAN 访问 Dokcer" + +msgid "Enable WAN access docker mapped ports" +msgstr "允许 WAN 访问 Dokcer 映射后的端口(易受攻击!)。

推荐禁用该选项后,用系统防火墙选择性映射 172.17.0.X:XX 端口到 WAN" + +msgid "Docker Readme First" +msgstr "Docker 初始化无脑配置教程" + +msgid "Download DockerReadme.pdf" +msgstr "下载 Docker 初始化无脑配置教程" + +msgid "Please download DockerReadme.pdf to read when first-running" +msgstr "初次在OpenWrt中运行Docker必读(只需执行一次流程)" diff --git a/applications/luci-app-docker/root/etc/config/docker b/applications/luci-app-docker/root/etc/config/docker new file mode 100644 index 000000000000..b73c0a3e38c9 --- /dev/null +++ b/applications/luci-app-docker/root/etc/config/docker @@ -0,0 +1,4 @@ + +config docker + option wan_mode '0' + diff --git a/applications/luci-app-docker/root/etc/docker-init b/applications/luci-app-docker/root/etc/docker-init new file mode 100644 index 000000000000..74421b05e65f --- /dev/null +++ b/applications/luci-app-docker/root/etc/docker-init @@ -0,0 +1,19 @@ +#!/bin/sh +dtype=`fdisk -l /dev/sda | grep 'Disklabel type' | awk '{print $3}'` +partid="0" + +if [ "$dtype" = "gpt" ] +then + partid=`echo "n +w +" | fdisk /dev/sda | grep 'Created a new partition' | awk '{print $5}'` + +elif [ "$dtype" = "dos" ] +then + partid=`echo "n +p +w +" | fdisk /dev/sda | grep 'Created a new partition' | awk '{print $5}'` +fi + +echo "y" | mkfs.ext4 /dev/sda$partid diff --git a/applications/luci-app-docker/root/etc/docker-web b/applications/luci-app-docker/root/etc/docker-web new file mode 100644 index 000000000000..849eb6d2a6eb --- /dev/null +++ b/applications/luci-app-docker/root/etc/docker-web @@ -0,0 +1,3 @@ +#!/bin/sh + +docker run -d --restart=always --name="portainer" -p 9999:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer diff --git a/applications/luci-app-docker/root/etc/docker/daemon.json b/applications/luci-app-docker/root/etc/docker/daemon.json new file mode 100644 index 000000000000..b8a99a4ce9ba --- /dev/null +++ b/applications/luci-app-docker/root/etc/docker/daemon.json @@ -0,0 +1,4 @@ +{ +"data-root": "/opt/", +"log-level": "warn" +} diff --git a/applications/luci-app-docker/root/etc/init.d/docker b/applications/luci-app-docker/root/etc/init.d/docker new file mode 100644 index 000000000000..fbe7f9d09394 --- /dev/null +++ b/applications/luci-app-docker/root/etc/init.d/docker @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +START=25 + +start_service() { + local nofile=$(cat /proc/sys/fs/nr_open) + local wanmode=$(uci get docker.@docker[0].wan_mode) + + if [ $wanmode = "1" ] ;then + dockerwan=" " + else + dockerwan="--iptables=false" + fi + + procd_open_instance + procd_set_param stderr 1 + procd_set_param command /usr/bin/dockerd $dockerwan + procd_set_param limits nofile="${nofile} ${nofile}" + procd_close_instance +} diff --git a/applications/luci-app-docker/root/usr/share/rpcd/acl.d/luci-app-docker.json b/applications/luci-app-docker/root/usr/share/rpcd/acl.d/luci-app-docker.json new file mode 100644 index 000000000000..05f90bcefc7c --- /dev/null +++ b/applications/luci-app-docker/root/usr/share/rpcd/acl.d/luci-app-docker.json @@ -0,0 +1,11 @@ +{ + "luci-app-docker": { + "description": "Grant UCI access for luci-app-docker", + "read": { + "uci": [ "dockerd" ] + }, + "write": { + "uci": [ "dockerd" ] + } + } +} diff --git a/applications/luci-app-docker/root/usr/share/ucitrack/luci-app-docker.json b/applications/luci-app-docker/root/usr/share/ucitrack/luci-app-docker.json new file mode 100644 index 000000000000..83283c1c4f0f --- /dev/null +++ b/applications/luci-app-docker/root/usr/share/ucitrack/luci-app-docker.json @@ -0,0 +1,4 @@ +{ + "config": "docker", + "init": [ "docker" ] +} diff --git a/applications/luci-app-docker/root/www/DockerReadme.pdf b/applications/luci-app-docker/root/www/DockerReadme.pdf new file mode 100644 index 000000000000..8a9a94b83296 Binary files /dev/null and b/applications/luci-app-docker/root/www/DockerReadme.pdf differ diff --git a/applications/luci-app-hd-idle/po/ca/hd-idle.po b/applications/luci-app-hd-idle/po/ca/hd-idle.po index aa184bdb897e..cf5610455eea 100644 --- a/applications/luci-app-hd-idle/po/ca/hd-idle.po +++ b/applications/luci-app-hd-idle/po/ca/hd-idle.po @@ -3,9 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-14 10:33+0200\n" -"PO-Revision-Date: 2026-03-08 17:31+0000\n" -"Last-Translator: Christopher Picón " -"\n" +"PO-Revision-Date: 2025-12-02 19:01+0000\n" +"Last-Translator: Alfonso Montero López \n" "Language-Team: Catalan \n" "Language: ca\n" @@ -13,11 +12,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.15-dev\n" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:43 msgid "Add new hdd setting..." -msgstr "Afegeix nova configuració d' hdd..." +msgstr "" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:61 msgid "Bus" @@ -29,7 +28,7 @@ msgstr "Disc" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:46 msgid "Disk Settings" -msgstr "Configuració del disc" +msgstr "" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:49 msgid "Enable" @@ -42,15 +41,15 @@ msgstr "" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:37 #: applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json:3 msgid "HDD Idle" -msgstr "Inactivitat d'HDD" +msgstr "HDD Idle" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:37 msgid "" "HDD Idle is a utility program for spinning-down disks after a period of idle " "time." msgstr "" -"HDD Idle és una utilitat per aturar el gir dels discs després d'un període " -"d'inactivitat." +"HDD Idle és un programa per ralentitzar els discos després d'un període de " +"temps inactiu." #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:75 #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:87 diff --git a/applications/luci-app-hd-idle/po/de/hd-idle.po b/applications/luci-app-hd-idle/po/de/hd-idle.po index 948ea8b88253..88eec57bb416 100644 --- a/applications/luci-app-hd-idle/po/de/hd-idle.po +++ b/applications/luci-app-hd-idle/po/de/hd-idle.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-14 10:33+0200\n" -"PO-Revision-Date: 2026-03-23 18:10+0000\n" -"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" +"PO-Revision-Date: 2024-01-06 10:10+0000\n" +"Last-Translator: ssantos \n" "Language-Team: German \n" "Language: de\n" @@ -12,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.4-dev\n" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:43 msgid "Add new hdd setting..." @@ -41,7 +41,7 @@ msgstr "UCI-Zugriff für luci-app-hd-idle erlauben" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:37 #: applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json:3 msgid "HDD Idle" -msgstr "HDD Leerlauf" +msgstr "HDD Idle" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:37 msgid "" diff --git a/applications/luci-app-hd-idle/po/zh_Hant/hd-idle.po b/applications/luci-app-hd-idle/po/zh_Hant/hd-idle.po index 97954eaf18a9..8e7d1f51f86f 100644 --- a/applications/luci-app-hd-idle/po/zh_Hant/hd-idle.po +++ b/applications/luci-app-hd-idle/po/zh_Hant/hd-idle.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2026-03-09 19:10+0000\n" +"PO-Revision-Date: 2026-02-11 13:57+0000\n" "Last-Translator: EESF-2 \n" "Language-Team: Chinese (Traditional Han script) \n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:43 msgid "Add new hdd setting..." @@ -22,11 +22,11 @@ msgstr "匯流排" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:53 msgid "Disk" -msgstr "硬碟" +msgstr "磁碟" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:46 msgid "Disk Settings" -msgstr "硬碟設定" +msgstr "磁碟設定" #: applications/luci-app-hd-idle/htdocs/luci-static/resources/view/hd_idle.js:49 msgid "Enable" diff --git a/applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json b/applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json index 9868364ef24b..e8294f656b47 100644 --- a/applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json +++ b/applications/luci-app-hd-idle/root/usr/share/luci/menu.d/luci-app-hd-idle.json @@ -1,5 +1,5 @@ { - "admin/services/hd_idle": { + "admin/nas/hd_idle": { "title": "HDD Idle", "order": 60, "action": { diff --git a/applications/luci-app-ksmbd/po/bg/ksmbd.po b/applications/luci-app-ksmbd/po/bg/ksmbd.po index dabe1da87636..fa3aa18c4ca8 100644 --- a/applications/luci-app-ksmbd/po/bg/ksmbd.po +++ b/applications/luci-app-ksmbd/po/bg/ksmbd.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-15 08:27+0000\n" -"Last-Translator: Daniel Konstantinov \n" +"PO-Revision-Date: 2026-03-05 17:52+0000\n" +"Last-Translator: Nikolay Tsanov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -16,15 +16,13 @@ msgstr "Разрешаване на гости" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:57 msgid "Allow legacy (insecure) protocols/authentication." -msgstr "Разреши стари (несигурни) протоколи/автентикация." +msgstr "" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:58 msgid "" "Allow legacy smb(v1)/Lanman connections, needed for older devices without " "smb(v2.1/3) support." msgstr "" -"Разреши стари smb(v1)/Lanman връзки, необходими за по-стари устройства без " -"поддръжка на smb(v2.1/3)." #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:97 msgid "Allowed users" diff --git a/applications/luci-app-ksmbd/po/ca/ksmbd.po b/applications/luci-app-ksmbd/po/ca/ksmbd.po index 52e705bd6cce..d1c4cf1d7983 100644 --- a/applications/luci-app-ksmbd/po/ca/ksmbd.po +++ b/applications/luci-app-ksmbd/po/ca/ksmbd.po @@ -1,19 +1,18 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:32+0000\n" -"Last-Translator: Christopher Picón " -"\n" +"PO-Revision-Date: 2022-07-25 17:15+0000\n" +"Last-Translator: dtalens \n" "Language-Team: Catalan \n" "Language: ca\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 5.17-dev\n" +"X-Generator: Weblate 4.14-dev\n" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:100 msgid "Allow guests" -msgstr "Permet convidats" +msgstr "" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:57 msgid "Allow legacy (insecure) protocols/authentication." diff --git a/applications/luci-app-ksmbd/po/hu/ksmbd.po b/applications/luci-app-ksmbd/po/hu/ksmbd.po index fca1a1137cb5..0834ec582841 100644 --- a/applications/luci-app-ksmbd/po/hu/ksmbd.po +++ b/applications/luci-app-ksmbd/po/hu/ksmbd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:30+0000\n" +"PO-Revision-Date: 2025-05-08 13:02+0000\n" "Last-Translator: hmzs \n" "Language-Team: Hungarian \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:100 msgid "Allow guests" diff --git a/applications/luci-app-ksmbd/po/ro/ksmbd.po b/applications/luci-app-ksmbd/po/ro/ksmbd.po index ab7f108acd69..fc463978877f 100644 --- a/applications/luci-app-ksmbd/po/ro/ksmbd.po +++ b/applications/luci-app-ksmbd/po/ro/ksmbd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-18 02:23+0000\n" +"PO-Revision-Date: 2025-08-23 10:16+0000\n" "Last-Translator: CRISTIAN ANDREI \n" "Language-Team: Romanian \n" @@ -9,7 +9,7 @@ msgstr "" "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 5.17-dev\n" +"X-Generator: Weblate 5.13\n" #: applications/luci-app-ksmbd/htdocs/luci-static/resources/view/ksmbd.js:100 msgid "Allow guests" diff --git a/applications/luci-app-ksmbd/root/usr/share/luci/menu.d/luci-app-ksmbd.json b/applications/luci-app-ksmbd/root/usr/share/luci/menu.d/luci-app-ksmbd.json index 17677a5de771..2327ce006fba 100644 --- a/applications/luci-app-ksmbd/root/usr/share/luci/menu.d/luci-app-ksmbd.json +++ b/applications/luci-app-ksmbd/root/usr/share/luci/menu.d/luci-app-ksmbd.json @@ -1,5 +1,5 @@ { - "admin/services/ksmbd": { + "admin/nas/ksmbd": { "title": "Network Shares", "action": { "type": "view", diff --git a/applications/luci-app-nlbwmon/po/bg/nlbwmon.po b/applications/luci-app-nlbwmon/po/bg/nlbwmon.po index 1737cb0f256d..347b2b091f0a 100644 --- a/applications/luci-app-nlbwmon/po/bg/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/bg/nlbwmon.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-15 08:27+0000\n" -"Last-Translator: Daniel Konstantinov \n" +"PO-Revision-Date: 2026-03-05 17:52+0000\n" +"Last-Translator: Nikolay Tsanov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -16,11 +16,11 @@ msgstr "%d IPv4 хоста" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:570 msgid "%d IPv6-only hosts" -msgstr "%d хоста само с IPv6" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:577 msgid "%d dual-stack hosts" -msgstr "%d хоста с двоен стек" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:114 msgid "%s and %s" diff --git a/applications/luci-app-nlbwmon/po/ca/nlbwmon.po b/applications/luci-app-nlbwmon/po/ca/nlbwmon.po index 3ffabf3c9cae..0968881e0189 100644 --- a/applications/luci-app-nlbwmon/po/ca/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/ca/nlbwmon.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:33+0000\n" +"PO-Revision-Date: 2025-12-03 13:52+0000\n" "Last-Translator: Christopher Picón " "\n" "Language-Team: Catalan \n" +"PO-Revision-Date: 2026-02-18 15:44+0000\n" +"Last-Translator: Werner Schleifer \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 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" @@ -368,8 +368,8 @@ msgid "" "Interval at which the temporary in-memory database is committed to the " "persistent database directory." msgstr "" -"Intervall, in dem die temporäre In-Memory-Datenbank in das Verzeichnis der " -"persistenten Datenbank übertragen wird." +"Zeitintervall, nach dem die in-Memory-Datenbank periodisch auf auf dem " +"Festspeicher persistiert wird." #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:166 msgid "" @@ -591,10 +591,10 @@ msgid "" "mainly useful for memory constrained systems which might not be able to " "satisfy memory allocation after longer uptime periods." msgstr "" -"Legt fest, ob die maximal mögliche Datenbankgröße im Arbeitsspeicher vorab " -"reserviert werden soll. Dies ist vor allem für Systeme mit begrenztem " -"Arbeitsspeicher sinnvoll, die nach längeren Betriebszeiten möglicherweise " -"nicht mehr in der Lage sind, Speicheranforderungen zu erfüllen." +"Gibt an, ob die maximal mögliche Datenbankgröße im Speicher vorab zugewiesen " +"werden soll. Dies ist hauptsächlich für Systeme mit eingeschränktem Speicher " +"nützlich, die die Speicherzuweisung nach längeren Betriebszeiten " +"möglicherweise nicht erfüllen können." #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:130 msgid "no traffic" diff --git a/applications/luci-app-nlbwmon/po/hu/nlbwmon.po b/applications/luci-app-nlbwmon/po/hu/nlbwmon.po index a36963a79bf5..e342ba1fa7bb 100644 --- a/applications/luci-app-nlbwmon/po/hu/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/hu/nlbwmon.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:31+0000\n" +"PO-Revision-Date: 2025-05-08 13:02+0000\n" "Last-Translator: hmzs \n" "Language-Team: Hungarian \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" diff --git a/applications/luci-app-nlbwmon/po/ko/nlbwmon.po b/applications/luci-app-nlbwmon/po/ko/nlbwmon.po index c7076438a745..0bdc46bb92e8 100644 --- a/applications/luci-app-nlbwmon/po/ko/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/ko/nlbwmon.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-27 13:46+0000\n" +"PO-Revision-Date: 2026-02-07 16:11+0000\n" "Last-Translator: Hyeonjeong Lee \n" "Language-Team: Korean \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" @@ -176,7 +176,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:861 #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:907 msgid "Connections" -msgstr "연결" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:843 msgid "Connections / Host" diff --git a/applications/luci-app-nlbwmon/po/pt_BR/nlbwmon.po b/applications/luci-app-nlbwmon/po/pt_BR/nlbwmon.po index c1b227a4605b..25bf24baf46e 100644 --- a/applications/luci-app-nlbwmon/po/pt_BR/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/pt_BR/nlbwmon.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-09 19:11+0000\n" -"Last-Translator: Volenski \n" +"PO-Revision-Date: 2026-01-20 07:02+0000\n" +"Last-Translator: Nicolas Aigner \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 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" @@ -185,7 +185,7 @@ msgstr "Comprimir o banco de dados" #: applications/luci-app-nlbwmon/root/usr/share/luci/menu.d/luci-app-nlbwmon.json:25 msgid "Configuration" -msgstr "Configuração" +msgstr "Configurações" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:628 msgid "Conn." diff --git a/applications/luci-app-nlbwmon/po/sv/nlbwmon.po b/applications/luci-app-nlbwmon/po/sv/nlbwmon.po index b3b3c3513ad3..802c310a39b2 100644 --- a/applications/luci-app-nlbwmon/po/sv/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/sv/nlbwmon.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-22 17:11+0000\n" +"PO-Revision-Date: 2025-03-05 20:26+0000\n" "Last-Translator: Kristoffer Grundström \n" "Language-Team: Swedish \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.10.3-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" @@ -434,7 +434,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:165 msgid "Refresh interval" -msgstr "Uppdateringsintervall" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:106 msgid "Require a valid date in the form \"YYYY-MM-DD\"" @@ -458,7 +458,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:334 msgid "Source IP" -msgstr "IP-adress för källa" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:96 msgid "Start date" @@ -470,7 +470,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:155 msgid "Stored periods" -msgstr "Lagrade perioder" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/config.js:53 msgid "" @@ -494,7 +494,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:835 msgid "Traffic Distribution" -msgstr "Distribuering av trafik" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:92 msgid "Unable to fetch traffic statistic data: %s" @@ -502,11 +502,11 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:631 msgid "Up. (Bytes)" -msgstr "Upp. (Bytes)" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:632 msgid "Up. (Pkts.)" -msgstr "Upp. (Pkt.)" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:615 msgctxt "Traffic counter" @@ -517,13 +517,13 @@ msgstr "Ladda upp" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:910 #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:957 msgid "Upload (Bytes)" -msgstr "Uppladdning (Bytes)" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:865 #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:911 #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:958 msgid "Upload (Packets)" -msgstr "Uppladdning (Paket)" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:890 msgid "Upload / Application" @@ -553,7 +553,7 @@ msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:130 msgid "no traffic" -msgstr "ingen trafik" +msgstr "" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:335 #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:388 diff --git a/applications/luci-app-nlbwmon/po/zh_Hant/nlbwmon.po b/applications/luci-app-nlbwmon/po/zh_Hant/nlbwmon.po index d520c195bb32..2d6b8e631191 100644 --- a/applications/luci-app-nlbwmon/po/zh_Hant/nlbwmon.po +++ b/applications/luci-app-nlbwmon/po/zh_Hant/nlbwmon.po @@ -3,7 +3,7 @@ # msgid "" msgstr "" -"PO-Revision-Date: 2026-03-11 18:10+0000\n" +"PO-Revision-Date: 2026-02-12 22:14+0000\n" "Last-Translator: EESF-2 \n" "Language-Team: Chinese (Traditional Han script) \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/display.js:563 msgid "%d IPv4-only hosts" @@ -488,8 +488,8 @@ msgid "" "The Netlink Bandwidth Monitor (nlbwmon) is a lightweight, efficient traffic " "accounting program keeping track of bandwidth usage per host and protocol." msgstr "" -"Netlink 頻寬監視器 (nlbwmon) 是一個輕型、有效流量統計程式,它可以追蹤每個主機" -"和協定的頻寬使用詳情。" +"Netlink 頻寬監視器 (nlbwmon) 是一個輕型、有效的流量統計程式,它可以追蹤每個主" +"機和協定的頻寬使用詳情。" #: applications/luci-app-nlbwmon/htdocs/luci-static/resources/view/nlbw/backup.js:21 msgid "The following database files have been restored:" diff --git a/applications/luci-app-nlbwmon/root/usr/share/luci/menu.d/luci-app-nlbwmon.json b/applications/luci-app-nlbwmon/root/usr/share/luci/menu.d/luci-app-nlbwmon.json index b744a6a6de4f..349fa9fdc911 100644 --- a/applications/luci-app-nlbwmon/root/usr/share/luci/menu.d/luci-app-nlbwmon.json +++ b/applications/luci-app-nlbwmon/root/usr/share/luci/menu.d/luci-app-nlbwmon.json @@ -1,10 +1,10 @@ { - "admin/services/nlbw": { + "admin/control/nlbw": { "title": "Bandwidth Monitor", "order": 80, "action": { "type": "alias", - "path": "admin/services/nlbw/display" + "path": "admin/control/nlbw/display" }, "depends": { "acl": [ "luci-app-nlbwmon" ], @@ -12,7 +12,7 @@ } }, - "admin/services/nlbw/display": { + "admin/control/nlbw/display": { "title": "Display", "order": 10, "action": { @@ -21,7 +21,7 @@ } }, - "admin/services/nlbw/config": { + "admin/control/nlbw/config": { "title": "Configuration", "order": 20, "action": { @@ -30,7 +30,7 @@ } }, - "admin/services/nlbw/backup": { + "admin/control/nlbw/backup": { "title": "Backup", "order": 30, "action": { diff --git a/applications/luci-app-ttyd/po/bg/ttyd.po b/applications/luci-app-ttyd/po/bg/ttyd.po index 2419237f9166..86365af09acf 100644 --- a/applications/luci-app-ttyd/po/bg/ttyd.po +++ b/applications/luci-app-ttyd/po/bg/ttyd.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-15 08:27+0000\n" -"Last-Translator: Daniel Konstantinov \n" +"PO-Revision-Date: 2026-03-05 17:53+0000\n" +"Last-Translator: Nikolay Tsanov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -20,7 +20,7 @@ msgstr "Добавяне на инстанция" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:49 msgid "Allow URL args" -msgstr "Разреши URL параметри" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:49 msgid "" diff --git a/applications/luci-app-ttyd/po/ca/ttyd.po b/applications/luci-app-ttyd/po/ca/ttyd.po index 284f962d338e..5ed01e9acfac 100644 --- a/applications/luci-app-ttyd/po/ca/ttyd.po +++ b/applications/luci-app-ttyd/po/ca/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:31+0000\n" +"PO-Revision-Date: 2025-12-05 05:01+0000\n" "Last-Translator: Christopher Picón " "\n" "Language-Team: Catalan \n" +"PO-Revision-Date: 2026-03-03 12:56+0000\n" +"Last-Translator: aladar42 \n" "Language-Team: Czech \n" "Language: cs\n" @@ -112,7 +112,7 @@ msgstr "Index" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:86 msgid "Info" -msgstr "Info" +msgstr "Pro informaci" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:27 msgid "Interface" @@ -240,7 +240,7 @@ msgstr "Popis umístění soketu unixové domény (např. /var/run/ttyd.sock)" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:20 msgid "UNIX socket" -msgstr "UNIX soket" +msgstr "Unixový soket" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:32 msgid "UNIX socket path" diff --git a/applications/luci-app-ttyd/po/de/ttyd.po b/applications/luci-app-ttyd/po/de/ttyd.po index ac25729c45d8..59cd2b546d87 100644 --- a/applications/luci-app-ttyd/po/de/ttyd.po +++ b/applications/luci-app-ttyd/po/de/ttyd.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-23 18:10+0000\n" -"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" +"PO-Revision-Date: 2026-02-15 08:21+0000\n" +"Last-Translator: PhillyMay \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 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Accept only one client and exit on disconnection" diff --git a/applications/luci-app-ttyd/po/es/ttyd.po b/applications/luci-app-ttyd/po/es/ttyd.po index ee17788a01d4..3e9930a3fcfc 100644 --- a/applications/luci-app-ttyd/po/es/ttyd.po +++ b/applications/luci-app-ttyd/po/es/ttyd.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2019-10-17 14:50-0300\n" -"PO-Revision-Date: 2026-03-28 19:26+0000\n" -"Last-Translator: Francisco Serrador \n" +"PO-Revision-Date: 2026-03-06 06:52+0000\n" +"Last-Translator: Franco Castillo \n" "Language-Team: Spanish \n" "Language: es\n" diff --git a/applications/luci-app-ttyd/po/ga/ttyd.po b/applications/luci-app-ttyd/po/ga/ttyd.po index 4cf9ddfd224c..b76e17a91d96 100644 --- a/applications/luci-app-ttyd/po/ga/ttyd.po +++ b/applications/luci-app-ttyd/po/ga/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-09 19:10+0000\n" +"PO-Revision-Date: 2026-03-02 04:27+0000\n" "Last-Translator: Aindriú Mac Giolla Eoin \n" "Language-Team: Irish \n" @@ -9,7 +9,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :" "(n>6 && n<11) ? 3 : 4;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Accept only one client and exit on disconnection" @@ -113,7 +113,7 @@ msgstr "Innéacs" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:86 msgid "Info" -msgstr "Eolas" +msgstr "Faisnéis" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:27 msgid "Interface" diff --git a/applications/luci-app-ttyd/po/ko/ttyd.po b/applications/luci-app-ttyd/po/ko/ttyd.po index 8ca4e8e4393e..ccc6bcaad739 100644 --- a/applications/luci-app-ttyd/po/ko/ttyd.po +++ b/applications/luci-app-ttyd/po/ko/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-08 17:32+0000\n" +"PO-Revision-Date: 2026-03-02 04:29+0000\n" "Last-Translator: Hyeonjeong Lee \n" "Language-Team: Korean \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Accept only one client and exit on disconnection" @@ -20,7 +20,7 @@ msgstr "인스턴스 추가" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:49 msgid "Allow URL args" -msgstr "URL 인자 허용" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:49 msgid "" @@ -38,7 +38,7 @@ msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:53 msgid "Client option" -msgstr "클라이언트 옵션" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:89 msgid "Command" @@ -50,11 +50,11 @@ msgstr "설정" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:37 msgid "Credential" -msgstr "인증 정보" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:37 msgid "Credential for Basic Authentication" -msgstr "기본 인증에 사용할 로그인 정보입니다" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:67 msgid "Custom index.html path" @@ -94,7 +94,7 @@ msgstr "luci-app-ttyd의 UCI 접근 권한 부여" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:43 msgid "Group ID" -msgstr "그룹 ID" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:43 msgid "Group id to run with" @@ -176,11 +176,11 @@ msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:79 msgid "SSL ca" -msgstr "SSL CA" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:73 msgid "SSL cert" -msgstr "SSL 인증서" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:73 msgid "SSL certificate file path" @@ -188,7 +188,7 @@ msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:76 msgid "SSL key" -msgstr "SSL 키" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:76 msgid "SSL key file path" @@ -213,11 +213,11 @@ msgstr "" #: applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json:3 #: applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json:14 msgid "Terminal" -msgstr "터미널" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:56 msgid "Terminal type" -msgstr "터미널 유형" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:56 msgid "Terminal type to report (default: xterm-256color)" @@ -229,11 +229,11 @@ msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:20 msgid "UNIX socket" -msgstr "UNIX 소켓" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:32 msgid "UNIX socket path" -msgstr "UNIX 소켓 경로" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:91 msgid "URL override" @@ -241,7 +241,7 @@ msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:40 msgid "User ID" -msgstr "사용자 ID" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:40 msgid "User id to run with" @@ -253,4 +253,4 @@ msgstr "경고(Warning)" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:12 msgid "ttyd Instance" -msgstr "ttyd 인스턴스" +msgstr "" diff --git a/applications/luci-app-ttyd/po/pt_BR/ttyd.po b/applications/luci-app-ttyd/po/pt_BR/ttyd.po index 1e32c88e5424..869be2b09b4d 100644 --- a/applications/luci-app-ttyd/po/pt_BR/ttyd.po +++ b/applications/luci-app-ttyd/po/pt_BR/ttyd.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-09 19:11+0000\n" -"Last-Translator: Volenski \n" +"PO-Revision-Date: 2026-01-20 07:02+0000\n" +"Last-Translator: Nicolas Aigner \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 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Accept only one client and exit on disconnection" @@ -48,7 +48,7 @@ msgstr "Comando" #: applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json:23 msgid "Config" -msgstr "Config" +msgstr "Configuração" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:37 msgid "Credential" diff --git a/applications/luci-app-ttyd/po/sv/ttyd.po b/applications/luci-app-ttyd/po/sv/ttyd.po index aa20e7bd49ed..3224f0ee20ff 100644 --- a/applications/luci-app-ttyd/po/sv/ttyd.po +++ b/applications/luci-app-ttyd/po/sv/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-22 17:09+0000\n" +"PO-Revision-Date: 2026-03-02 22:45+0000\n" "Last-Translator: Kristoffer Grundström \n" "Language-Team: Swedish \n" @@ -52,7 +52,7 @@ msgstr "Konfiguration" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:37 msgid "Credential" -msgstr "Referens" +msgstr "" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:37 msgid "Credential for Basic Authentication" diff --git a/applications/luci-app-ttyd/po/zh_Hans/ttyd.po b/applications/luci-app-ttyd/po/zh_Hans/ttyd.po index aec85d06094c..bb3f7b8d4bf5 100644 --- a/applications/luci-app-ttyd/po/zh_Hans/ttyd.po +++ b/applications/luci-app-ttyd/po/zh_Hans/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-09 19:11+0000\n" +"PO-Revision-Date: 2026-03-06 07:15+0000\n" "Last-Translator: nKsyn \n" "Language-Team: Chinese (Simplified Han script) \n" @@ -139,7 +139,7 @@ msgstr "注意,通过反向代理的页面不会像LuCI那样受到密码保 #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:85 msgid "Notice" -msgstr "通知 (Notice)" +msgstr "通知" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Once" diff --git a/applications/luci-app-ttyd/po/zh_Hant/ttyd.po b/applications/luci-app-ttyd/po/zh_Hant/ttyd.po index 0a16c87e5a7a..d2b2c0060609 100644 --- a/applications/luci-app-ttyd/po/zh_Hant/ttyd.po +++ b/applications/luci-app-ttyd/po/zh_Hant/ttyd.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-03-27 06:10+0000\n" +"PO-Revision-Date: 2026-02-20 00:34+0000\n" "Last-Translator: EESF-2 \n" "Language-Team: Chinese (Traditional Han script) \n" @@ -8,7 +8,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:65 msgid "Accept only one client and exit on disconnection" @@ -63,7 +63,7 @@ msgstr "自訂 index.html 路徑" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:82 msgid "Debug" -msgstr "除錯" +msgstr "偵錯" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:51 msgid "Do not allow clients to write to the TTY" @@ -201,7 +201,7 @@ msgstr "將選項發送到用戶端" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:82 msgid "Set log level (default: 7)" -msgstr "設定紀錄等級 (預設值: 7)" +msgstr "設定日誌等級 (預設值: 7)" #: applications/luci-app-ttyd/htdocs/luci-static/resources/view/ttyd/config.js:46 msgid "Signal" diff --git a/applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json b/applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json index 023117674c30..4559063e87c6 100644 --- a/applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json +++ b/applications/luci-app-ttyd/root/usr/share/luci/menu.d/luci-app-ttyd.json @@ -1,5 +1,5 @@ { - "admin/services/ttyd": { + "admin/system/ttyd": { "title": "Terminal", "action": { "type": "firstchild" @@ -10,7 +10,7 @@ } }, - "admin/services/ttyd/ttyd": { + "admin/system/ttyd/ttyd": { "title": "Terminal", "order": 1, "action": { @@ -19,7 +19,7 @@ } }, - "admin/services/ttyd/config": { + "admin/system/ttyd/config": { "title": "Config", "order": 2, "action": { diff --git a/applications/luci-app-upnp/po/bg/upnp.po b/applications/luci-app-upnp/po/bg/upnp.po index d0a404035e9b..a2fdc84c0c4e 100644 --- a/applications/luci-app-upnp/po/bg/upnp.po +++ b/applications/luci-app-upnp/po/bg/upnp.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-05-19 19:36+0200\n" -"PO-Revision-Date: 2026-03-15 08:27+0000\n" -"Last-Translator: Daniel Konstantinov \n" +"PO-Revision-Date: 2026-03-05 17:52+0000\n" +"Last-Translator: Nikolay Tsanov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -28,8 +28,6 @@ msgid "" "ACL specify which client addresses and ports can be mapped, IPv6 always " "allowed." msgstr "" -"ACL указва кои клиентски адреси и портове могат да бъдат съпоставяни; IPv6 " -"винаги е разрешен." #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:235 msgid "Action" @@ -109,7 +107,7 @@ msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:153 msgid "Download speed" -msgstr "Скорост на теглене" +msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:144 msgid "Enable PCP/NAT-PMP protocols" @@ -251,7 +249,7 @@ msgstr "Неизвестно" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:157 msgid "Upload speed" -msgstr "Скорост на качване" +msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:161 msgctxt "Use %s (%s = STUN)" diff --git a/applications/luci-app-upnp/po/ca/upnp.po b/applications/luci-app-upnp/po/ca/upnp.po index 2ff340b7240d..e3dd21cbf0c5 100644 --- a/applications/luci-app-upnp/po/ca/upnp.po +++ b/applications/luci-app-upnp/po/ca/upnp.po @@ -3,9 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-10 03:40+0200\n" -"PO-Revision-Date: 2026-03-08 17:33+0000\n" -"Last-Translator: Christopher Picón " -"\n" +"PO-Revision-Date: 2021-09-17 06:52+0000\n" +"Last-Translator: Roger Pueyo Centelles \n" "Language-Team: Catalan \n" "Language: ca\n" @@ -13,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 4.9-dev\n" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:180 msgctxt "" @@ -46,7 +45,7 @@ msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:135 msgid "Advanced Settings" -msgstr "Configuració Avançada" +msgstr "Configuració avançada" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:148 msgid "Advertise as IGDv1 (IPv4 only) device instead of IGDv2" @@ -174,11 +173,11 @@ msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:205 msgid "Report system instead of service uptime" -msgstr "Informa del temps d'activitat del sistema en lloc del servei" +msgstr "Reporta el temps actiu del sistema en lloc del del dimoni" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:186 msgid "SOAP/HTTP port" -msgstr "port SOAP/HTTP" +msgstr "SOAP/HTTP port" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:165 msgid "STUN host" @@ -235,11 +234,11 @@ msgstr "" #: applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json:3 msgid "UPnP IGD & PCP" -msgstr "UPnP IGD i PCP" +msgstr "UPnP IGD & PCP" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:87 msgid "UPnP IGD & PCP/NAT-PMP Service" -msgstr "Servei UPnP IGD, PCP i NAT-PMP" +msgstr "UPnP IGD & PCP/NAT-PMP Service" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:147 msgid "UPnP IGDv1 compatibility mode" diff --git a/applications/luci-app-upnp/po/sv/upnp.po b/applications/luci-app-upnp/po/sv/upnp.po index f5a987a38b69..7cef6deddcdc 100644 --- a/applications/luci-app-upnp/po/sv/upnp.po +++ b/applications/luci-app-upnp/po/sv/upnp.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2026-03-22 17:10+0000\n" +"PO-Revision-Date: 2025-11-11 08:51+0000\n" "Last-Translator: Kristoffer Grundström \n" "Language-Team: Swedish \n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.15-dev\n" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:180 msgctxt "" @@ -92,7 +92,7 @@ msgstr "Kommentar" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:72 #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:122 msgid "Delete" -msgstr "Radera" +msgstr "Ta bort" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:237 msgid "Deny" @@ -130,7 +130,7 @@ msgstr "Aktivera säkert läge" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/status/include/80_upnp.js:45 #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:103 msgid "Expires" -msgstr "Utgår" +msgstr "" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/status/include/80_upnp.js:43 #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:101 diff --git a/applications/luci-app-upnp/po/zh_Hans/upnp.po b/applications/luci-app-upnp/po/zh_Hans/upnp.po index 6f1b5b5b594b..92afe87ea806 100644 --- a/applications/luci-app-upnp/po/zh_Hans/upnp.po +++ b/applications/luci-app-upnp/po/zh_Hans/upnp.po @@ -6,8 +6,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-10 03:40+0200\n" -"PO-Revision-Date: 2026-03-13 14:10+0000\n" -"Last-Translator: nKsyn \n" +"PO-Revision-Date: 2025-12-26 15:12+0000\n" +"Last-Translator: Anya Lin \n" "Language-Team: Chinese (Simplified Han script) \n" "Language: zh_Hans\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.15.1\n" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:180 msgctxt "" @@ -24,7 +24,7 @@ msgctxt "" msgid "" "A 900s interval will result in %s notifications with the minimum max-age of " "1800s" -msgstr "当通知间隔为 900 秒时,%s 通知的最小 max-age 为 1800 秒" +msgstr "900 秒的时间间隔将导致 %s 通知的最小 max-age 为 1800 秒" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:216 msgid "" @@ -235,8 +235,8 @@ msgstr "" "射" #: applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json:3 -msgid "UPnP IGD & PCP" -msgstr "UPnP IGD 和 PCP" +msgid "UPnP" +msgstr "UPnP" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:87 msgid "UPnP IGD & PCP/NAT-PMP Service" diff --git a/applications/luci-app-upnp/po/zh_Hant/upnp.po b/applications/luci-app-upnp/po/zh_Hant/upnp.po index 7d53e7dc65b5..acee7e1aa589 100644 --- a/applications/luci-app-upnp/po/zh_Hant/upnp.po +++ b/applications/luci-app-upnp/po/zh_Hant/upnp.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2026-03-27 06:10+0000\n" +"PO-Revision-Date: 2026-02-20 00:35+0000\n" "Last-Translator: EESF-2 \n" "Language-Team: Chinese (Traditional Han script) \n" @@ -13,7 +13,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:180 msgctxt "" @@ -156,7 +156,7 @@ msgstr "協定" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:210 msgid "Puts extra debugging information into the system log" -msgstr "將額外的除錯資訊寫入系統紀錄" +msgstr "將額外的偵錯資訊寫入系統日誌" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:192 msgid "Report custom router web interface (presentation) URL" @@ -231,8 +231,8 @@ msgid "" msgstr "偵測不受限制的 full-cone/one-to-one NAT 的公共 IPv4 位址" #: applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json:3 -msgid "UPnP IGD & PCP" -msgstr "UPnP IGD & PCP" +msgid "UPnP" +msgstr "UPnP" #: applications/luci-app-upnp/htdocs/luci-static/resources/view/upnp/upnp.js:87 msgid "UPnP IGD & PCP/NAT-PMP Service" diff --git a/applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json b/applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json index 80250be50cd2..73fc3dc511ca 100644 --- a/applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json +++ b/applications/luci-app-upnp/root/usr/share/luci/menu.d/luci-app-upnp.json @@ -1,6 +1,6 @@ { "admin/services/upnp": { - "title": "UPnP IGD & PCP", + "title": "UPnP", "action": { "type": "view", "path": "upnp/upnp" diff --git a/applications/luci-app-wol/po/bg/wol.po b/applications/luci-app-wol/po/bg/wol.po index a03f66334f3a..24919e975892 100644 --- a/applications/luci-app-wol/po/bg/wol.po +++ b/applications/luci-app-wol/po/bg/wol.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-19 00:29+0200\n" -"PO-Revision-Date: 2026-03-15 08:27+0000\n" -"Last-Translator: Daniel Konstantinov \n" +"PO-Revision-Date: 2026-03-05 17:52+0000\n" +"Last-Translator: Nikolay Tsanov \n" "Language-Team: Bulgarian \n" "Language: bg\n" diff --git a/applications/luci-app-wol/po/de/wol.po b/applications/luci-app-wol/po/de/wol.po index 2e1581856e6b..07b1ed1d68db 100644 --- a/applications/luci-app-wol/po/de/wol.po +++ b/applications/luci-app-wol/po/de/wol.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-19 00:29+0200\n" -"PO-Revision-Date: 2026-03-23 18:10+0000\n" -"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n" +"PO-Revision-Date: 2025-12-30 17:00+0000\n" +"Last-Translator: Steve \n" "Language-Team: German \n" "Language: de\n" @@ -12,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.15.1\n" #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:65 msgid "Choose the host to wake up or enter a custom MAC address to use" diff --git a/applications/luci-app-wol/po/hu/wol.po b/applications/luci-app-wol/po/hu/wol.po index a7d2ad43f7fb..4430e36cd8aa 100644 --- a/applications/luci-app-wol/po/hu/wol.po +++ b/applications/luci-app-wol/po/hu/wol.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-19 00:29+0200\n" -"PO-Revision-Date: 2026-03-08 17:32+0000\n" +"PO-Revision-Date: 2025-05-08 13:01+0000\n" "Last-Translator: hmzs \n" "Language-Team: Hungarian \n" @@ -12,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:65 msgid "Choose the host to wake up or enter a custom MAC address to use" @@ -71,8 +71,8 @@ msgstr "Felébresztés hálózaton keresztül" msgid "" "Wake on LAN is a mechanism to boot computers remotely in the local network." msgstr "" -"A \"felébresztés hálózaton keresztül\" (WoL - Wake on LAN) a helyi " -"hálózatban lévő számítógépek távoli elindítására szolgáló módszer." +"A \"felébresztés hálózaton keresztül\" (WoL) a helyi hálózatban lévő " +"számítógépek távoli elindítására szolgáló módszer." #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:140 msgid "Wake up host" diff --git a/applications/luci-app-wol/po/id/wol.po b/applications/luci-app-wol/po/id/wol.po index 8d857af509d3..88b3f71efd6f 100644 --- a/applications/luci-app-wol/po/id/wol.po +++ b/applications/luci-app-wol/po/id/wol.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-19 00:29+0200\n" -"PO-Revision-Date: 2026-03-13 18:16+0000\n" -"Last-Translator: Charles03010 \n" +"PO-Revision-Date: 2026-01-12 12:01+0000\n" +"Last-Translator: deri sahertian \n" "Language-Team: Indonesian \n" "Language: id\n" @@ -12,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.15.1\n" #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:65 msgid "Choose the host to wake up or enter a custom MAC address to use" diff --git a/applications/luci-app-wol/po/sv/wol.po b/applications/luci-app-wol/po/sv/wol.po index c64845df300c..7dd02c1a571c 100644 --- a/applications/luci-app-wol/po/sv/wol.po +++ b/applications/luci-app-wol/po/sv/wol.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2026-03-22 17:11+0000\n" +"PO-Revision-Date: 2026-01-27 12:49+0000\n" "Last-Translator: Kristoffer Grundström \n" "Language-Team: Swedish \n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16-dev\n" #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:65 msgid "Choose the host to wake up or enter a custom MAC address to use" diff --git a/applications/luci-app-wol/po/zh_Hant/wol.po b/applications/luci-app-wol/po/zh_Hant/wol.po index 6c2924caa7b0..dbfa89020390 100644 --- a/applications/luci-app-wol/po/zh_Hant/wol.po +++ b/applications/luci-app-wol/po/zh_Hant/wol.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-04-19 00:29+0200\n" -"PO-Revision-Date: 2026-03-27 06:10+0000\n" +"PO-Revision-Date: 2026-02-26 14:29+0000\n" "Last-Translator: EESF-2 \n" "Language-Team: Chinese (Traditional Han script) \n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.17-dev\n" +"X-Generator: Weblate 5.16.1-dev\n" #: applications/luci-app-wol/htdocs/luci-static/resources/view/wol.js:65 msgid "Choose the host to wake up or enter a custom MAC address to use" diff --git a/applications/luci-app-wol/root/usr/share/luci/menu.d/luci-app-wol.json b/applications/luci-app-wol/root/usr/share/luci/menu.d/luci-app-wol.json index 1fb8cd7ae8a5..db16831cec8e 100644 --- a/applications/luci-app-wol/root/usr/share/luci/menu.d/luci-app-wol.json +++ b/applications/luci-app-wol/root/usr/share/luci/menu.d/luci-app-wol.json @@ -1,5 +1,5 @@ { - "admin/services/wol": { + "admin/control/wol": { "title": "Wake on LAN", "order": 90, "action": {