From 064929ddec55c67ea4c09f586796e9b262c464f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 4 Jul 2026 08:36:24 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20Sync=202026-07-04=2008:36:24?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-app-openclaw/CHANGELOG.md | 46 + luci-app-openclaw/Makefile | 2 +- luci-app-openclaw/README.md | 12 +- luci-app-openclaw/VERSION | 2 +- .../docs/ISSUE_TRIAGE_2026-07-04.md | 32 + .../luasrc/controller/openclaw.lua | 123 +-- luci-app-openclaw/root/usr/bin/openclaw-env | 8 +- .../tests/test_node_packaging_contract.sh | 2 +- .../tests/test_openclaw_contracts.sh | 9 +- luci-app-openclaw/tests/test_openclaw_node.sh | 4 +- luci-app-smartdns/Makefile | 2 +- .../resources/view/smartdns/smartdns.js | 128 ++- luci-app-smartdns/po/zh_Hans/smartdns.po | 842 +++++++++--------- luci-app-ssr-plus/Makefile | 2 +- .../root/usr/share/shadowsocksr/update.lua | 12 +- naiveproxy/Makefile | 2 +- quectel_MHI/Makefile | 2 +- torrserver/Makefile | 6 +- 18 files changed, 690 insertions(+), 546 deletions(-) create mode 100644 luci-app-openclaw/docs/ISSUE_TRIAGE_2026-07-04.md mode change 100644 => 100755 quectel_MHI/Makefile diff --git a/luci-app-openclaw/CHANGELOG.md b/luci-app-openclaw/CHANGELOG.md index 002251dd..5a500540 100644 --- a/luci-app-openclaw/CHANGELOG.md +++ b/luci-app-openclaw/CHANGELOG.md @@ -4,6 +4,52 @@ 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/)。 +## [2.0.8] - 2026-07-04 + +### 修复 ARM64 Node.js 下载资产不一致 + +- 默认 Node.js 更新为 `22.23.0`,与 GitHub Release 和长期 `node-bins` 中的 ARM64 musl 资产保持一致。 +- 同步更新 `build-node-musl.yml` 手动构建参数,避免后续手动构建继续产出旧版本 Node.js。 +- `node-bins` release 已补齐 `node-v22.23.0-linux-arm64-musl.tar.xz`,用于 ARM64 OpenWrt/iStoreOS 在线安装。 + +### 测试 + +- 更新 Node.js 默认版本、Node 版本比较和 ARM64 musl 打包契约测试。 + +--- + +## [2.0.7] - 2026-07-04 + +### 适配 OpenClaw v2026.6.11 + +- `OC_TESTED_VERSION` 更新为 `2026.6.11`,继续默认安装 npm `latest` 稳定标签。 +- 保持默认 Node.js `22.22.2` 和最低要求 `22.19.0`,满足 OpenClaw `2026.6.11` 的 `engines.node`。 +- README 同步当前适配版本:OpenClaw `2026.6.11`、微信插件 `@tencent-weixin/openclaw-weixin@2.4.6`、微信 CLI `2.1.4`。 + +### 修复微信插件安装、登录和卸载 + +- 微信插件安装和升级时,如缺少 `python3`,后台自动尝试 `opkg update && opkg install python3-light`,失败后在安装日志给出手动命令。 +- 微信登录前只修复 npm cache、tmp、微信账号状态目录和配置文件权限,避免递归改写插件代码目录属主。 +- 微信登录增加 `openclaw` 用户写权限预检,目录不可写时直接在二维码日志返回明确错误。 +- 微信卸载会清理 legacy extensions、npm projects 中的微信插件包、微信账号状态目录,并用 Node.js 结构化删除 `plugins.allow`、`plugins.installs`、`plugins.entries`、`channels`、`channel` 中的 `openclaw-weixin/weixin` 配置。 +- 备份 API 改用统一安装路径 helper,兼容用户把 `install_path` 误填成 `/mnt/data/openclaw` 的场景。 + +### 测试 + +- 更新 OpenClaw 默认版本契约到 `2026.6.11`。 +- 增加微信插件自动安装 `python3-light`、登录权限预检和卸载清理 npm projects/config 的契约断言。 + +### 致谢 + +感谢以下用户通过 Issue 或 PR 提供问题反馈、复现信息和修复思路: + +- @hotwa (#85) +- @djbadboyvip (#94)、@alan9771 (#93, #82)、@luckymai3688 (#92, #91)、@lucian521 (#90) +- @svgr110 (#89)、@Cuscito (#88)、@hwliu11 (#84)、@sam528300-lab (#78) +- @yiyibuguai (#75)、@xuguoliang189 (#64)、@ampcwin (#70)、@okareyouok (#60) + +--- + ## [2.0.6] - 2026-06-08 ### 适配 OpenClaw v2026.6.1 diff --git a/luci-app-openclaw/Makefile b/luci-app-openclaw/Makefile index 64aa3fdf..7a36e2a4 100644 --- a/luci-app-openclaw/Makefile +++ b/luci-app-openclaw/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-openclaw PKG_VERSION:=$(strip $(shell cat $(CURDIR)/VERSION 2>/dev/null || echo "1.0.0")) -PKG_RELEASE:=17 +PKG_RELEASE:=18 PKG_MAINTAINER:=10000ge10000 <10000ge10000@users.noreply.github.com> PKG_LICENSE:=GPL-3.0 diff --git a/luci-app-openclaw/README.md b/luci-app-openclaw/README.md index 51125fd6..039039e3 100644 --- a/luci-app-openclaw/README.md +++ b/luci-app-openclaw/README.md @@ -27,9 +27,9 @@ | 组件 | 默认版本 | 说明 | |------|----------|------| -| OpenClaw | `2026.6.1` | npm `latest` 稳定标签;不默认追 `2026.6.5-beta.2` | -| Node.js | `22.22.2` | Alpine musl LTS 包;OpenClaw 2026.6.x 要求 `>=22.19.0`,安装后会按 `engines.node` 做强校验 | -| 微信插件 | `@tencent-weixin/openclaw-weixin@2.4.3` | CLI 使用 `@tencent-weixin/openclaw-weixin-cli@2.1.4` | +| OpenClaw | `2026.6.11` | npm `latest` 稳定标签 | +| Node.js | `22.23.0` | Alpine musl LTS 包;OpenClaw 2026.6.x 要求 `>=22.19.0`,安装后会按 `engines.node` 做强校验 | +| 微信插件 | `@tencent-weixin/openclaw-weixin@2.4.6` | CLI 使用 `@tencent-weixin/openclaw-weixin-cli@2.1.4` | ## 📦 安装 @@ -111,15 +111,15 @@ openclaw-env setup 微信渠道安装前会检查: - `openclaw` 系统用户是否存在,不存在时自动创建 -- `python3` 是否已安装 +- `python3` 是否已安装;缺失时会自动执行 `opkg update && opkg install python3-light` - npm cache、tmp、OpenClaw 数据目录是否可由 `openclaw` 用户写入 - 旧渠道名 `weixin` 会迁移为 `openclaw-weixin` -如缺少 Python3: +如自动安装失败,可手动安装: ```bash opkg update -opkg install python3 +opkg install python3-light ``` ## 已知说明 diff --git a/luci-app-openclaw/VERSION b/luci-app-openclaw/VERSION index 157e54f3..815e68dd 100644 --- a/luci-app-openclaw/VERSION +++ b/luci-app-openclaw/VERSION @@ -1 +1 @@ -2.0.6 +2.0.8 diff --git a/luci-app-openclaw/docs/ISSUE_TRIAGE_2026-07-04.md b/luci-app-openclaw/docs/ISSUE_TRIAGE_2026-07-04.md new file mode 100644 index 00000000..4ce3d11a --- /dev/null +++ b/luci-app-openclaw/docs/ISSUE_TRIAGE_2026-07-04.md @@ -0,0 +1,32 @@ +# Issue Triage 2026-07-04 + +本文件记录 2026-07-04 维护时对 open issue / PR 的处理边界,便于后续关闭 issue 时引用。 + +## 已在 2.0.7 覆盖 + +- OpenClaw 默认版本升级:`2026.6.11`,覆盖和当前稳定版、Node 最低版本相关的问题反馈。 +- 微信插件安装:缺少 Python 时自动尝试安装 `python3-light`,失败后给出明确手动命令。 +- 微信插件登录:收窄权限修复范围,增加 `openclaw` 用户写权限预检。 +- 微信插件卸载:清理 legacy extension、npm projects 中的微信插件包、微信账号状态目录和配置中的 `openclaw-weixin/weixin` 残留。 +- 自定义安装路径:备份 API 改用统一路径 helper,继续兼容 `/mnt/data` 和误填 `/mnt/data/openclaw`。 + +## 已在 2.0.8 覆盖 + +- ARM64 musl Node.js 默认版本和自托管资产对齐到 `22.23.0`。 +- 长期 `node-bins` release 已补齐 `node-v22.23.0-linux-arm64-musl.tar.xz`,避免在线安装继续请求不存在的 `22.22.2` 资产。 +- 手动 ARM64 musl Node.js 构建 workflow 同步到 `22.23.0`。 + +## 已由当前 main 既有实现覆盖 + +- 可配置安装根目录和路径规范化:PR #85 的核心路径 helper、`/mnt/data/openclaw` 误填兼容、危险路径拒绝已经在 main 存在。 +- HOME 不全局污染:`profile.d/openclaw.sh` 仅在 wrapper 内注入 `HOME`。 +- 控制台打开方式:Web 控制台使用新窗口 HTTP Gateway URL,避免 LuCI HTTPS / iframe / 旧 token 混用。 +- 微信渠道名迁移:init 脚本会把旧 `weixin` 迁移到 `openclaw-weixin`,并清理 duplicate entries。 + +## 暂不关闭 + +以下类型 issue 不应仅凭 2.0.7 关闭,需要单独复现或确认: + +- 模型/provider 具体行为差异或上游 OpenClaw 功能请求。 +- 缺少完整日志、无法确认由本次 Node / 微信 / 权限修复覆盖的问题。 +- 需要用户确认网络、DNS、代理、设备资源或第三方 API 状态的问题。 diff --git a/luci-app-openclaw/luasrc/controller/openclaw.lua b/luci-app-openclaw/luasrc/controller/openclaw.lua index 789c0522..7419aa6a 100644 --- a/luci-app-openclaw/luasrc/controller/openclaw.lua +++ b/luci-app-openclaw/luasrc/controller/openclaw.lua @@ -99,6 +99,17 @@ local function write_wechat_log_and_exit(log_file, exit_file, content, exit_code end end +local function wechat_python3_bootstrap_cmd(log_file) + return "if ! command -v python3 >/dev/null 2>&1; then " .. + "echo '未检测到 python3,正在尝试安装 python3-light...' >> " .. shellquote(log_file) .. "; " .. + "(opkg update && opkg install python3-light) >> " .. shellquote(log_file) .. " 2>&1 || true; " .. + "fi; " .. + "if ! command -v python3 >/dev/null 2>&1; then " .. + "echo '❌ python3-light 自动安装失败,请手动执行: opkg update && opkg install python3-light' >> " .. shellquote(log_file) .. "; " .. + "echo 127 > /tmp/openclaw-wechat-install.exit; exit 0; " .. + "fi; " +end + function index() -- 主入口: 服务 → OpenClaw (🧠 作为菜单图标) local page = entry({"admin", "services", "openclaw"}, alias("admin", "services", "openclaw", "basic"), _("OpenClaw"), 90) @@ -808,10 +819,8 @@ function action_backup() local uci = require "luci.model.uci".cursor() local action = http.formvalue("action") or "create" - -- 获取安装路径 - local install_path_uci = uci:get("openclaw", "main", "install_path") or "/opt" - -- 实际安装路径 - local install_path = install_path_uci .. "/openclaw" + -- 使用统一路径 helper,兼容用户误填 /mnt/data/openclaw 的场景。 + local install_path = get_install_path() local node_bin = install_path .. "/node/bin/node" local oc_entry = "" @@ -1326,17 +1335,6 @@ function action_wechat_install() http.write_json({ status = "ok", message = "微信插件安装已在后台启动..." }) return end - if sys.exec("command -v python3 2>/dev/null"):gsub("%s+", "") == "" then - write_wechat_log_and_exit( - "/tmp/openclaw-wechat-install.log", - "/tmp/openclaw-wechat-install.exit", - "开始安装微信插件...\n安装路径: " .. install_path .. "\n❌ 错误: 未检测到 python3。\n请先安装依赖: opkg update && opkg install python3\n", - 127 - ) - http.prepare_content("application/json") - http.write_json({ status = "ok", message = "微信插件安装已在后台启动..." }) - return - end if not ensure_openclaw_user(oc_data) then write_wechat_log_and_exit( "/tmp/openclaw-wechat-install.log", @@ -1360,6 +1358,7 @@ function action_wechat_install() "echo '开始安装微信插件...' > /tmp/openclaw-wechat-install.log; " .. "echo '安装路径: %s' >> /tmp/openclaw-wechat-install.log; " .. "echo 'npx 路径: %s' >> /tmp/openclaw-wechat-install.log; " .. + wechat_python3_bootstrap_cmd("/tmp/openclaw-wechat-install.log") .. "mkdir -p %s/.npm %s/.tmp %s/.openclaw/extensions; " .. "if [ ! -w %s/.openclaw/extensions ]; then chown -R openclaw:openclaw %s/.openclaw/extensions 2>/dev/null; fi; " .. "chown -R openclaw:openclaw %s/.npm %s/.tmp %s/.openclaw 2>/dev/null; " .. @@ -1496,7 +1495,11 @@ function action_wechat_login() "( " .. "echo '正在启动微信登录...' > /tmp/openclaw-wechat-qrcode.txt; " .. "echo '安装路径: %s' >> /tmp/openclaw-wechat-qrcode.txt; " .. - "mkdir -p %s/.npm %s/.tmp %s/.openclaw; chown -R openclaw:openclaw %s/.npm %s/.tmp %s/.openclaw 2>/dev/null; " .. + "mkdir -p %s/.npm %s/.tmp %s/.openclaw/openclaw-weixin; " .. + "touch %s/.openclaw/openclaw.json 2>/dev/null || true; " .. + "chown -R openclaw:openclaw %s/.npm %s/.tmp %s/.openclaw/openclaw-weixin 2>/dev/null; " .. + "chown openclaw:openclaw %s/.openclaw %s/.openclaw/openclaw.json 2>/dev/null; " .. + "su -s /bin/sh openclaw -c 'test -w %s/.npm && test -w %s/.tmp && test -w %s/.openclaw && test -w %s/.openclaw/openclaw-weixin && test -w %s/.openclaw/openclaw.json' || { echo '❌ openclaw 用户无法写入微信登录目录,请检查数据目录权限' >> /tmp/openclaw-wechat-qrcode.txt; echo 1 > /tmp/openclaw-wechat-login.exit; exit 0; }; " .. "cd %s && " .. "su -s /bin/sh openclaw -c 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json " .. "NPM_CONFIG_CACHE=%s/.npm npm_config_cache=%s/.npm TMPDIR=%s/.tmp PATH=%s/node/bin:%s/global/bin:$PATH " .. @@ -1504,9 +1507,10 @@ function action_wechat_login() "echo $? > /tmp/openclaw-wechat-login.exit; " .. ") >/dev/null 2>&1 & echo $! > /tmp/openclaw-wechat-login.pid", install_path, - oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, - oc_data, oc_data, oc_data, oc_data, oc_data, - oc_data, oc_data, oc_data, install_path, install_path, node_bin, oc_entry + oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, + oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, + oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, + install_path, install_path, node_bin, oc_entry ) sys.exec(login_cmd) http.prepare_content("application/json") @@ -1594,34 +1598,59 @@ function action_wechat_uninstall() local sys = require "luci.sys" local install_path = get_install_path() + local node_bin = install_path .. "/node/bin/node" + local oc_data = install_path .. "/data" - -- 删除微信插件目录 - local wechat_ext_dir = install_path .. "/data/.openclaw/extensions/openclaw-weixin" - if wechat_ext_dir == install_path .. "/data/.openclaw/extensions/openclaw-weixin" then - sys.exec("rm -rf " .. shellquote(wechat_ext_dir) .. " 2>/dev/null") + -- 删除微信插件目录和账号状态。所有路径都限制在当前 OpenClaw 数据目录下。 + local wechat_ext_dir = oc_data .. "/.openclaw/extensions/openclaw-weixin" + local wechat_state_dir = oc_data .. "/.openclaw/openclaw-weixin" + local npm_projects = oc_data .. "/.openclaw/npm/projects" + sys.exec("rm -rf " .. shellquote(wechat_ext_dir) .. " " .. shellquote(wechat_state_dir) .. " 2>/dev/null") + if nixio.fs.stat(npm_projects, "type") then + sys.exec("find " .. shellquote(npm_projects) .. " -path '*/node_modules/@tencent-weixin/openclaw-weixin' -type d -prune -exec rm -rf {} + 2>/dev/null") + sys.exec("find " .. shellquote(npm_projects) .. " -path '*/node_modules/@tencent-weixin/openclaw-weixin-cli' -type d -prune -exec rm -rf {} + 2>/dev/null") end -- 从配置中删除微信相关配置 - local config_file = install_path .. "/data/.openclaw/openclaw.json" + local config_file = oc_data .. "/.openclaw/openclaw.json" if nixio.fs.stat(config_file, "type") then - -- 读取配置 - local cf = io.open(config_file, "r") - local content = "" - if cf then - content = cf:read("*a") or "" - cf:close() - end - - -- 删除微信配置块 (简单字符串替换) - content = content:gsub(',?%s*"openclaw%-weixin"%s*:%s*%b{}', "") - content = content:gsub('"openclaw%-weixin"%s*:%s*%b{}%s*,?', "") - - -- 写回配置 - local wf = io.open(config_file, "w") - if wf then - wf:write(content) - wf:close() + local cleanup_js = [[ +const fs = require('fs'); +const p = process.env.OC_CONFIG; +let d = {}; +try { d = JSON.parse(fs.readFileSync(p, 'utf8')); } catch (e) { process.exit(0); } +function drop(o, k) { if (o && typeof o === 'object') delete o[k]; } +function dropChannel(o) { drop(o, 'openclaw-weixin'); drop(o, 'weixin'); } +if (d.plugins && Array.isArray(d.plugins.allow)) { + d.plugins.allow = d.plugins.allow.filter((x) => x !== 'openclaw-weixin' && x !== 'weixin'); +} +if (d.plugins) { + dropChannel(d.plugins.installs); + dropChannel(d.plugins.entries); +} +dropChannel(d.channels); +dropChannel(d.channel); +dropChannel(d); +fs.writeFileSync(p, JSON.stringify(d, null, 2)); +]] + if nixio.fs.stat(node_bin, "type") then + sys.exec("OC_CONFIG=" .. shellquote(config_file) .. " " .. shellquote(node_bin) .. " -e " .. shellquote(cleanup_js) .. " 2>/dev/null") + else + local cf = io.open(config_file, "r") + local content = "" + if cf then + content = cf:read("*a") or "" + cf:close() + end + content = content:gsub(',?%s*"openclaw%-weixin"%s*:%s*%b{}', "") + content = content:gsub('"openclaw%-weixin"%s*:%s*%b{}%s*,?', "") + local wf = io.open(config_file, "w") + if wf then + wf:write(content) + wf:close() + end end + sys.exec("chown openclaw:openclaw " .. shellquote(config_file) .. " 2>/dev/null") end -- 清理临时文件 @@ -1717,17 +1746,6 @@ function action_wechat_upgrade_plugin() http.write_json({ status = "ok", message = "微信插件升级已在后台启动..." }) return end - if sys.exec("command -v python3 2>/dev/null"):gsub("%s+", "") == "" then - write_wechat_log_and_exit( - "/tmp/openclaw-wechat-install.log", - "/tmp/openclaw-wechat-install.exit", - "正在升级微信插件...\n安装路径: " .. install_path .. "\n❌ 错误: 未检测到 python3。\n请先安装依赖: opkg update && opkg install python3\n", - 127 - ) - http.prepare_content("application/json") - http.write_json({ status = "ok", message = "微信插件升级已在后台启动..." }) - return - end if not ensure_openclaw_user(oc_data) then write_wechat_log_and_exit( "/tmp/openclaw-wechat-install.log", @@ -1751,6 +1769,7 @@ function action_wechat_upgrade_plugin() "echo '正在升级微信插件...' > /tmp/openclaw-wechat-install.log; " .. "echo '安装路径: %s' >> /tmp/openclaw-wechat-install.log; " .. "echo 'npx 路径: %s' >> /tmp/openclaw-wechat-install.log; " .. + wechat_python3_bootstrap_cmd("/tmp/openclaw-wechat-install.log") .. "mkdir -p %s/.npm %s/.tmp %s/.openclaw/extensions; " .. "if [ ! -w %s/.openclaw/extensions ]; then chown -R openclaw:openclaw %s/.openclaw/extensions 2>/dev/null; fi; " .. "chown -R openclaw:openclaw %s/.npm %s/.tmp %s/.openclaw 2>/dev/null; " .. diff --git a/luci-app-openclaw/root/usr/bin/openclaw-env b/luci-app-openclaw/root/usr/bin/openclaw-env index 2e360e10..27e3d3a5 100755 --- a/luci-app-openclaw/root/usr/bin/openclaw-env +++ b/luci-app-openclaw/root/usr/bin/openclaw-env @@ -7,19 +7,19 @@ # openclaw-env upgrade — 升级 OpenClaw 到最新版 # openclaw-env node — 仅下载/更新 Node.js # 环境变量: -# OC_VERSION — 指定 OpenClaw 版本 (如 2026.6.1),不设置则安装已测试稳定版 +# OC_VERSION — 指定 OpenClaw 版本 (如 2026.6.11),不设置则安装已测试稳定版 # ============================================================================ set -e # ── Node.js 版本策略 (双版本兼容) ── -# V2: 当前推荐版本,用于 OpenClaw v2026.6.1+ (要求 >= 22.19.0,使用 Alpine musl LTS 包确保可运行) +# V2: 当前推荐版本,用于 OpenClaw v2026.6.11+ (要求 >= 22.19.0,使用 Alpine musl LTS 包确保可运行) # V1: 旧版兼容,用于 OpenClaw v2026.3.8 及更早版本 -NODE_VERSION_V2="22.22.2" +NODE_VERSION_V2="22.23.0" NODE_VERSION_V1="22.15.1" # 默认使用 V2 版本 (可通过 NODE_VERSION 环境变量覆盖) NODE_VERSION="${NODE_VERSION:-${NODE_VERSION_V2}}" # 经过验证的 OpenClaw 稳定版本 (更新此值需同步测试) -OC_TESTED_VERSION="2026.6.1" +OC_TESTED_VERSION="2026.6.11" # OpenClaw 2026.6.x package.json engines.node 的最低要求。 # 如果未来上游提高要求,安装成功后还会从 package.json 再做一次强校验。 OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.19.0}" diff --git a/luci-app-openclaw/tests/test_node_packaging_contract.sh b/luci-app-openclaw/tests/test_node_packaging_contract.sh index bbd289be..0fe9d7de 100755 --- a/luci-app-openclaw/tests/test_node_packaging_contract.sh +++ b/luci-app-openclaw/tests/test_node_packaging_contract.sh @@ -20,7 +20,7 @@ fi grep -Fq 'verify_prefix /opt/openclaw/node' "$BUILD_SCRIPT" || fail "build script should verify default install path" grep -Fq 'verify_prefix /tmp/custom-openclaw-root/openclaw/node' "$BUILD_SCRIPT" || fail "build script should verify custom install path" -grep -Fq 'NODE_VER="22.22.2"' "$WORKFLOW" || fail "workflow should build current musl-compatible Node.js" +grep -Fq 'NODE_VER="22.23.0"' "$WORKFLOW" || fail "workflow should build current musl-compatible Node.js" grep -Fq 'BUILD_MODE=apk' "$WORKFLOW" || fail "workflow should use apk mode for ARM64 musl package" grep -Fq 'PKG_TYPE=lts' "$WORKFLOW" || fail "workflow should use Alpine LTS Node.js package" diff --git a/luci-app-openclaw/tests/test_openclaw_contracts.sh b/luci-app-openclaw/tests/test_openclaw_contracts.sh index 786e1451..2135c5f1 100755 --- a/luci-app-openclaw/tests/test_openclaw_contracts.sh +++ b/luci-app-openclaw/tests/test_openclaw_contracts.sh @@ -6,8 +6,8 @@ fail() { exit 1 } -grep -q "OC_TESTED_VERSION=\"2026.6.1\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned" -grep -q "NODE_VERSION_V2=\"22.22.2\"" root/usr/bin/openclaw-env || fail "default Node.js version not pinned" +grep -q "OC_TESTED_VERSION=\"2026.6.11\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned" +grep -q "NODE_VERSION_V2=\"22.23.0\"" root/usr/bin/openclaw-env || fail "default Node.js version not pinned" grep -q "OC_NODE_MIN_VERSION=\"\${OC_NODE_MIN_VERSION:-22.19.0}\"" root/usr/bin/openclaw-env || fail "minimum Node.js version not pinned" grep -q "oc_assert_node_min_version" root/usr/bin/openclaw-env || fail "Node.js minimum version check missing" grep -q 'oc_node_version_ge "$from_pkg" "$required"' root/usr/bin/openclaw-env || fail "package Node.js requirement must not lower static minimum" @@ -33,9 +33,12 @@ grep -q "is_safe_openclaw_root" luasrc/controller/openclaw.lua || fail "uninstal grep -q "local q_install_path = shellquote(install_path)" luasrc/controller/openclaw.lua || fail "uninstall rm must shellquote install_path" grep -q "rm -rf \" .. q_install_path" luasrc/controller/openclaw.lua || fail "uninstall rm must use quoted install_path" -grep -q "command -v python3" luasrc/controller/openclaw.lua || fail "wechat install must check python3" +grep -q "opkg install python3-light" luasrc/controller/openclaw.lua || fail "wechat install must auto install python3-light" grep -q "ensure_openclaw_user" luasrc/controller/openclaw.lua || fail "wechat install must ensure openclaw user" grep -q "NPM_CONFIG_CACHE" luasrc/controller/openclaw.lua || fail "wechat install must set npm cache" +grep -q "openclaw 用户无法写入微信登录目录" luasrc/controller/openclaw.lua || fail "wechat login writable preflight missing" +grep -q "node_modules/@tencent-weixin/openclaw-weixin" luasrc/controller/openclaw.lua || fail "wechat uninstall must remove npm project plugin" +grep -q "dropChannel(d.plugins.installs)" luasrc/controller/openclaw.lua || fail "wechat uninstall must clean plugin installs" grep -q "openclaw-weixin" root/etc/init.d/openclaw || fail "weixin channel migration missing" grep -q "delete d.plugins.entries\\['openclaw-weixin'\\]" root/etc/init.d/openclaw || fail "weixin duplicate entries cleanup missing" grep -q "npm/projects" root/etc/init.d/openclaw || fail "npm plugin project ownership fix missing" diff --git a/luci-app-openclaw/tests/test_openclaw_node.sh b/luci-app-openclaw/tests/test_openclaw_node.sh index d65bce54..9cfb2747 100755 --- a/luci-app-openclaw/tests/test_openclaw_node.sh +++ b/luci-app-openclaw/tests/test_openclaw_node.sh @@ -8,10 +8,10 @@ fail() { exit 1 } -[ "$(oc_normalize_node_version v22.22.2)" = "22.22.2" ] || fail "normalize v" +[ "$(oc_normalize_node_version v22.23.0)" = "22.23.0" ] || fail "normalize v" oc_node_version_ge 22.19.0 22.19.0 || fail "exact version" oc_node_version_ge 22.19.1 22.19.0 || fail "patch version" -oc_node_version_ge 22.22.2 22.19.0 || fail "supported LTS version" +oc_node_version_ge 22.23.0 22.19.0 || fail "supported LTS version" if oc_node_version_ge 22.18.1 22.19.0; then fail "older minor accepted" fi diff --git a/luci-app-smartdns/Makefile b/luci-app-smartdns/Makefile index aabd8b63..4e036e1e 100644 --- a/luci-app-smartdns/Makefile +++ b/luci-app-smartdns/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_LICENSE:=GPL-3.0-or-later PKG_MAINTAINER:=Nick Peng PKG_VERSION:=1.2025.47.2 -PKG_RELEASE:=9 +PKG_RELEASE:=10 LUCI_TITLE:=LuCI for smartdns LUCI_DESCRIPTION:=Provides Luci for smartdns diff --git a/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js b/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js index fde9e718..c752ba05 100644 --- a/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js +++ b/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js @@ -46,12 +46,6 @@ function getServiceStatus() { }); } -function smartdnsServiceStatus() { - return Promise.all([ - getServiceStatus() - ]); -} - function smartdnsRenderStatus(isRunning) { let renderHTML = ""; @@ -70,7 +64,7 @@ function smartdnsRenderStatus(isRunning) { const protocol = window.location.protocol; const hostname = window.location.hostname; const uiLink = protocol + "//" + hostname + ":" + uiPort; - renderHTML += "  " + _("Open the WebUI") + ""; + renderHTML += '  ' + _("Open the WebUI") + ''; } } else { renderHTML += "SmartDNS - " + _("NOT RUNNING") + ""; @@ -125,7 +119,7 @@ return view.extend({ s.anonymous = true; s.render = function (section_id) { const renderStatus = function () { - return L.resolveDefault(smartdnsServiceStatus()).then(function (res) { + return L.resolveDefault(getServiceStatus()).then(function (res) { const view = document.getElementById("service_status"); if (view == null) { return; @@ -223,6 +217,8 @@ return view.extend({ o.value("ping,tcp:443,tcp:80"); o.value("tcp:80,tcp:443,ping"); o.value("tcp:443,tcp:80,ping"); + o.value("tcp-syn:80,tcp-syn:443,ping"); + o.value("tcp-syn:443,tcp-syn:80,ping"); o.value("none", _("None")); o.validate = function (section_id, value) { if (value == "") { @@ -248,6 +244,15 @@ return view.extend({ continue; } + if (cm.indexOf("tcp-syn:") == 0) { + const port = cm.split(":")[1]; + if (port == "") { + return _("TCP SYN port is empty"); + } + + continue; + } + return _("Speed check mode is invalid."); } @@ -386,8 +391,8 @@ return view.extend({ return true; } - var ipset = value.split(",") - for (var i = 0; i < ipset.length; i++) { + let ipset = value.split(",") + for (let i = 0; i < ipset.length; i++) { if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) { return _("ipset name format error, format: [#[4|6]:]ipsetname"); } @@ -427,9 +432,9 @@ return view.extend({ return true; } - var nftset = value.split(",") - for (var i = 0; i < nftset.length; i++) { - if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) { + const nftset = value.split(",") + for (let nfts of nftset) { + if (!nfts.match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) { return _("NFTset name format error, format: [#[4|6]:[family#table#set]]"); } } @@ -496,7 +501,7 @@ return view.extend({ } if (df.type != 'config') { - continue + continue; } o.value(df.name); @@ -504,16 +509,16 @@ return view.extend({ o = s.taboption("advanced", form.DynamicList, "hosts_files", _("Hosts File"), _("Include hosts file.")); o.rmempty = true; - for (var i = 0; i < download_files.length; i++) { - if (download_files[i].type == undefined) { + for (let df of download_files) { + if (df.type == undefined) { continue; } - if (download_files[i].type != 'other') { - continue + if (df.type != 'other') { + continue; } - o.value(download_files[i].name); + o.value(df.name); } /////////////////////////////////////// @@ -671,7 +676,7 @@ return view.extend({ o.depends('enable_auto_update', '1'); o = s.taboption('files', form.ListValue, 'auto_update_day_time', _("Update time (every day)")); - for (var i = 0; i < 24; i++) + for (let i = 0; i < 24; i++) o.value(i, i + ':00'); o.default = '5'; o.depends('enable_auto_update', '1'); @@ -831,7 +836,7 @@ return view.extend({ }) }, [_("View Log")]); } - var log_levels = ["debug", "info", "notice", "warn", "error", "fatal"]; + const log_levels = ["debug", "info", "notice", "warn", "error", "fatal"]; log_levels.forEach(function(level) { o.depends({ log_output_mode: "file", log_level: level }); }); @@ -1112,9 +1117,9 @@ return view.extend({ return true; } - var val = uci.sections('smartdns', 'server'); - for (var i = 0; i < val.length; i++) { - if (value == val[i].server_group) { + const val = uci.sections('smartdns', 'server'); + for (let i of val) { + if (value == i.server_group) { return true; } } @@ -1132,6 +1137,8 @@ return view.extend({ o.value("ping,tcp:443,tcp:80"); o.value("tcp:80,tcp:443,ping"); o.value("tcp:443,tcp:80,ping"); + o.value("tcp-syn:80,tcp-syn:443,ping"); + o.value("tcp-syn:443,tcp-syn:80,ping"); o.value("none", _("None")); o.validate = function (section_id, value) { if (value == "") { @@ -1142,14 +1149,14 @@ return view.extend({ return true; } - var check_mode = value.split(",") - for (var i = 0; i < check_mode.length; i++) { - if (check_mode[i] == "ping") { + const check_mode = value.split(",") + for (let cm of check_mode) { + if (cm == "ping") { continue; } - if (check_mode[i].indexOf("tcp:") == 0) { - var port = check_mode[i].split(":")[1]; + if (cm.indexOf("tcp:") == 0) { + const port = cm.split(":")[1]; if (port == "") { return _("TCP port is empty"); } @@ -1157,6 +1164,15 @@ return view.extend({ continue; } + if (cm.indexOf("tcp-syn:") == 0) { + const port = cm.split(":")[1]; + if (port == "") { + return _("TCP SYN port is empty"); + } + + continue; + } + return _("Speed check mode is invalid."); } @@ -1189,9 +1205,9 @@ return view.extend({ return true; } - var ipset = value.split(",") - for (var i = 0; i < ipset.length; i++) { - if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) { + const ipset = value.split(",") + for (let ips of ipset) { + if (!ips.match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) { return _("ipset name format error, format: [#[4|6]:]ipsetname"); } } @@ -1209,9 +1225,9 @@ return view.extend({ return true; } - var nftset = value.split(",") - for (var i = 0; i < nftset.length; i++) { - if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) { + const nftset = value.split(",") + for (let nfts of nftset) { + if (!nfts.match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) { return _("NFTset name format error, format: [#[4|6]:[family#table#set]]"); } } @@ -1223,16 +1239,16 @@ return view.extend({ download_files = uci.sections('smartdns', 'download-file'); o = s.taboption("advanced", form.DynamicList, "conf_files", _("Include Config Files
/etc/smartdns/conf.d"), _("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page.")); - for (var i = 0; i < download_files.length; i++) { - if (download_files[i].type == undefined) { + for (let df of download_files) { + if (df.type == undefined) { continue; } - if (download_files[i].type != 'config') { - continue + if (df.type != 'config') { + continue; } - o.value(download_files[i].name); + o.value(df.name); } o = s.taboption("block", form.FileUpload, "block_domain_set_file", _("Domain List File"), _("Upload domain list file.")); @@ -1291,6 +1307,8 @@ return view.extend({ o.value("ping,tcp:443,tcp:80"); o.value("tcp:80,tcp:443,ping"); o.value("tcp:443,tcp:80,ping"); + o.value("tcp-syn:80,tcp-syn:443,ping"); + o.value("tcp-syn:443,tcp-syn:80,ping"); o.value("none", _("None")); o.validate = function (section_id, value) { if (value == "") { @@ -1301,14 +1319,14 @@ return view.extend({ return true; } - var check_mode = value.split(",") - for (var i = 0; i < check_mode.length; i++) { - if (check_mode[i] == "ping") { + const check_mode = value.split(",") + for (let cm of check_mode) { + if (cm == "ping") { continue; } - if (check_mode[i].indexOf("tcp:") == 0) { - var port = check_mode[i].split(":")[1]; + if (cm.indexOf("tcp:") == 0) { + const port = cm.split(":")[1]; if (port == "") { return _("TCP port is empty"); } @@ -1316,6 +1334,15 @@ return view.extend({ continue; } + if (cm.indexOf("tcp-syn:") == 0) { + const port = cm.split(":")[1]; + if (port == "") { + return _("TCP SYN port is empty"); + } + + continue; + } + return _("Speed check mode is invalid."); } @@ -1515,6 +1542,8 @@ return view.extend({ so.value("ping,tcp:443,tcp:80"); so.value("tcp:80,tcp:443,ping"); so.value("tcp:443,tcp:80,ping"); + so.value("tcp-syn:80,tcp-syn:443,ping"); + so.value("tcp-syn:443,tcp-syn:80,ping"); so.value("none", _("None")); so.validate = function (section_id, value) { if (value == "") { @@ -1540,6 +1569,15 @@ return view.extend({ continue; } + if (cm.indexOf("tcp-syn:") == 0) { + const port = cm.split(":")[1]; + if (port == "") { + return _("TCP SYN port is empty"); + } + + continue; + } + return _("Speed check mode is invalid."); } diff --git a/luci-app-smartdns/po/zh_Hans/smartdns.po b/luci-app-smartdns/po/zh_Hans/smartdns.po index 27ad8b86..2bfc3374 100644 --- a/luci-app-smartdns/po/zh_Hans/smartdns.po +++ b/luci-app-smartdns/po/zh_Hans/smartdns.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: luci-app-smartdns\n" -"POT-Creation-Date: 2025-10-03 09:04+0000\n" +"POT-Creation-Date: 2025-11-13 01:05+0000\n" "PO-Revision-Date: \n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -77,7 +77,7 @@ msgstr "请检查系统日志,并检查配置是否合法。" #: smartdns.js:91 msgid "Dnsmasq Forwarded To Smartdns Failure" -msgstr "重定向dnsmasq到smartdns失败" +msgstr "重定向 Dnsmasq 到 SmartDNS 失败" #: smartdns.js:120 msgid "SmartDNS" @@ -91,27 +91,27 @@ msgstr "SmartDNS 服务器" msgid "" "SmartDNS is a local high-performance DNS server, supports finding fastest " "IP, supports ad filtering, and supports avoiding DNS poisoning." -msgstr "SmartDNS是一个本地高性能DNS服务器,支持返回最快IP,支持广告过滤。" +msgstr "SmartDNS 是一个本地高性能 DNS 服务器,支持返回最快 IP,支持广告过滤。" #: smartdns.js:153 msgid "Settings" msgstr "设置" -#: smartdns.js:153 smartdns.js:156 smartdns.js:877 +#: smartdns.js:153 smartdns.js:156 smartdns.js:888 msgid "General Settings" msgstr "常规设置" -#: smartdns.js:157 smartdns.js:878 smartdns.js:1063 +#: smartdns.js:157 smartdns.js:889 smartdns.js:1074 msgid "Advanced Settings" msgstr "高级设置" #: smartdns.js:158 msgid "Second Server Settings" -msgstr "第二DNS服务器" +msgstr "第二 DNS 服务器" #: smartdns.js:159 msgid "DNS64 Server Settings" -msgstr "DNS64服务器配置" +msgstr "DNS64 服务器配置" #: smartdns.js:160 msgid "Download Files Setting" @@ -122,7 +122,7 @@ msgid "" "Download domain list files for domain-rule and include config files, please " "refresh the page after download to take effect." msgstr "" -"下载域名规则所需要的域名列表文件和smartdns配置文件,下载完成后刷新页面。" +"下载域名规则所需要的域名列表文件和 SmartDNS 配置文件,下载完成后刷新页面。" #: smartdns.js:161 msgid "Proxy Server Settings" @@ -132,14 +132,14 @@ msgstr "代理服务器设置" msgid "Custom Settings" msgstr "自定义设置" -#: smartdns.js:167 smartdns.js:524 smartdns.js:881 smartdns.js:1066 -#: smartdns.js:1453 smartdns.js:1633 +#: smartdns.js:167 smartdns.js:535 smartdns.js:892 smartdns.js:1077 +#: smartdns.js:1486 smartdns.js:1677 msgid "Enable" msgstr "启用" #: smartdns.js:167 msgid "Enable or disable smartdns server" -msgstr "启用或禁用SmartDNS服务" +msgstr "启用或禁用 SmartDNS 服务" #: smartdns.js:172 msgid "Server Name" @@ -147,9 +147,9 @@ msgstr "服务器名称" #: smartdns.js:172 msgid "Smartdns server name" -msgstr "SmartDNS的服务器名称,默认为smartdns,留空为主机名" +msgstr "SmartDNS 的服务器名称,默认为 smartdns,留空为主机名" -#: smartdns.js:178 smartdns.js:530 +#: smartdns.js:178 smartdns.js:541 msgid "Local Port" msgstr "本地端口" @@ -158,661 +158,665 @@ msgid "" "Smartdns local server port, smartdns will be automatically set as main dns " "when the port is 53." msgstr "" -"SmartDNS本地服务端口,当端口号设置为53时,smartdns将会自动配置为主dns。" +"SmartDNS 本地服务端口,当端口号设置为 53 时,SmartDNS 将会自动配置为主 DNS。" #: smartdns.js:186 msgid "Automatically Set Dnsmasq" -msgstr "自动设置Dnsmasq" +msgstr "自动设置 Dnsmasq" #: smartdns.js:186 msgid "Automatically set as upstream of dnsmasq when port changes." -msgstr "端口更改时自动设为 dnsmasq 的上游。" +msgstr "端口更改时自动设为 Dnsmasq 的上游。" #: smartdns.js:192 msgid "Enable WebUI" -msgstr "启用WebUI" +msgstr "启用 WebUI" #: smartdns.js:192 msgid "Enable or disable smartdns webui plugin." -msgstr "启用或禁用SmartDNS WebUI插件。" +msgstr "启用或禁用 SmartDNS WebUI 插件。" #: smartdns.js:196 msgid "WebUI Port" -msgstr "WebUI端口" +msgstr "WebUI 端口" #: smartdns.js:196 msgid "WebUI server port." -msgstr "WebUI服务端口。" +msgstr "WebUI 服务端口。" #: smartdns.js:202 msgid "WebUI Data Dir" -msgstr "WebUI数据库目录" +msgstr "WebUI 数据库目录" #: smartdns.js:202 msgid "Directory for storing the webui database." -msgstr "用于存储WebUI数据库的目录。" +msgstr "用于存储 WebUI 数据库的目录。" #: smartdns.js:208 msgid "WebUI Log Retention" -msgstr "WebUI日志保存天数" +msgstr "WebUI 日志保存天数" #: smartdns.js:208 msgid "Number of days to retain webui logs." -msgstr "保留WebUI日志的天数。" +msgstr "保留 WebUI 日志的天数。" -#: smartdns.js:219 smartdns.js:1128 smartdns.js:1287 smartdns.js:1510 +#: smartdns.js:219 smartdns.js:1139 smartdns.js:1309 smartdns.js:1543 msgid "Speed Check Mode" msgstr "测速模式" -#: smartdns.js:219 smartdns.js:1128 smartdns.js:1287 smartdns.js:1510 +#: smartdns.js:219 smartdns.js:1139 smartdns.js:1309 smartdns.js:1543 msgid "Smartdns speed check mode." -msgstr "SmartDNS测速模式。" +msgstr "SmartDNS 测速模式。" -#: smartdns.js:222 smartdns.js:263 smartdns.js:795 smartdns.js:1131 -#: smartdns.js:1290 smartdns.js:1332 smartdns.js:1506 smartdns.js:1514 +#: smartdns.js:222 smartdns.js:274 smartdns.js:806 smartdns.js:1142 +#: smartdns.js:1312 smartdns.js:1365 smartdns.js:1539 smartdns.js:1547 msgid "default" msgstr "默认" -#: smartdns.js:227 smartdns.js:1136 smartdns.js:1295 smartdns.js:1494 -#: smartdns.js:1519 +#: smartdns.js:229 smartdns.js:1149 smartdns.js:1319 smartdns.js:1527 +#: smartdns.js:1554 msgid "None" msgstr "无" -#: smartdns.js:246 smartdns.js:1155 smartdns.js:1314 smartdns.js:1538 +#: smartdns.js:250 smartdns.js:1170 smartdns.js:1340 smartdns.js:1575 msgid "TCP port is empty" -msgstr "TCP端口号为空" +msgstr "TCP 端口号为空" -#: smartdns.js:252 smartdns.js:1161 smartdns.js:1320 smartdns.js:1544 +#: smartdns.js:258 smartdns.js:1178 smartdns.js:1348 smartdns.js:1583 +msgid "TCP SYN port is empty" +msgstr "TCP SYN端口号为空" + +#: smartdns.js:263 smartdns.js:1183 smartdns.js:1353 smartdns.js:1588 msgid "Speed check mode is invalid." msgstr "测速模式无效。" -#: smartdns.js:259 +#: smartdns.js:270 msgid "Response Mode" msgstr "响应模式" -#: smartdns.js:260 +#: smartdns.js:271 msgid "" "Smartdns response mode, First Ping: return the first ping IP, Fastest IP: " "return the fastest IP, Fastest Response: return the fastest DNS response." msgstr "" -"SmartDNS响应模式,最快PING: 返回最早有ping结果的IP,速度适中;最快IP: 返回" -"最快IP,查询请求可能延长; 最快响应:返回最快响应的结果,查询请求时间短。" +"SmartDNS 响应模式,最快 Ping:返回最早有 ping 结果的 IP,速度适中;最快 IP:返回" +"最快 IP,查询请求可能延长;最快响应:返回最快响应的结果,查询请求时间短。" -#: smartdns.js:264 +#: smartdns.js:275 msgid "First Ping" -msgstr "最快PING" +msgstr "最快 Ping" -#: smartdns.js:265 +#: smartdns.js:276 msgid "Fastest IP" -msgstr "最快IP" +msgstr "最快 IP" -#: smartdns.js:266 +#: smartdns.js:277 msgid "Fastest Response" msgstr "最快响应" -#: smartdns.js:269 smartdns.js:537 +#: smartdns.js:280 smartdns.js:548 msgid "TCP Server" -msgstr "TCP服务器" +msgstr "TCP 服务器" -#: smartdns.js:269 smartdns.js:537 +#: smartdns.js:280 smartdns.js:548 msgid "Enable TCP DNS Server" -msgstr "启用TCP服务器。" +msgstr "启用 TCP 服务器。" -#: smartdns.js:274 +#: smartdns.js:285 msgid "DOT Server" -msgstr "DOT服务器" +msgstr "DOT 服务器" -#: smartdns.js:274 +#: smartdns.js:285 msgid "Enable DOT DNS Server" -msgstr "启用DOT服务器" +msgstr "启用 DOT 服务器" -#: smartdns.js:278 +#: smartdns.js:289 msgid "DOT Server Port" -msgstr "DOT服务器端口" +msgstr "DOT 服务器端口" -#: smartdns.js:278 +#: smartdns.js:289 msgid "Smartdns DOT server port." -msgstr "Smartdns DOT服务器端口号。" - -#: smartdns.js:286 -msgid "DOH Server" -msgstr "DOH服务器" - -#: smartdns.js:286 -msgid "Enable DOH DNS Server" -msgstr "启用DOH服务器" - -#: smartdns.js:290 -msgid "DOH Server Port" -msgstr "DOH服务器端口" - -#: smartdns.js:290 -msgid "Smartdns DOH server port." -msgstr "Smartdns DOH服务器端口号" +msgstr "SmartDNS DOT 服务器端口号。" #: smartdns.js:297 +msgid "DOH Server" +msgstr "DOH 服务器" + +#: smartdns.js:297 +msgid "Enable DOH DNS Server" +msgstr "启用 DOH 服务器" + +#: smartdns.js:301 +msgid "DOH Server Port" +msgstr "DOH 服务器端口" + +#: smartdns.js:301 +msgid "Smartdns DOH server port." +msgstr "SmartDNS DOH 服务器端口号" + +#: smartdns.js:308 msgid "Server Cert" msgstr "服务器证书" -#: smartdns.js:297 +#: smartdns.js:308 msgid "Server certificate file path." msgstr "服务器证书文件路径。" -#: smartdns.js:304 +#: smartdns.js:315 msgid "Server Cert Key" msgstr "服务器证书私钥" -#: smartdns.js:304 +#: smartdns.js:315 msgid "Server certificate key file path." msgstr "服务器证书私钥文件路径。" -#: smartdns.js:311 +#: smartdns.js:322 msgid "Server Cert Key Pass" msgstr "服务器证书私钥密码" -#: smartdns.js:311 +#: smartdns.js:322 msgid "Server certificate key file password." msgstr "服务器证书私钥文件密码。" -#: smartdns.js:318 +#: smartdns.js:329 msgid "IPv6 Server" -msgstr "IPv6服务器" +msgstr "IPv6 服务器" -#: smartdns.js:318 +#: smartdns.js:329 msgid "Enable IPv6 DNS Server" -msgstr "启用IPv6服务器。" +msgstr "启用 IPv6 服务器。" -#: smartdns.js:323 +#: smartdns.js:334 msgid "Bind Device" msgstr "绑定到设备" -#: smartdns.js:323 +#: smartdns.js:334 msgid "Listen only on the specified interfaces." -msgstr "监听在指定的设备上,避免非本地网络的DNS查询请求。" +msgstr "监听在指定的设备上,避免非本地网络的 DNS 查询请求。" -#: smartdns.js:328 +#: smartdns.js:339 msgid "Bind Device Name" msgstr "绑定的设备名称" -#: smartdns.js:328 +#: smartdns.js:339 msgid "Name of device name listen on." msgstr "绑定的设备名称。" -#: smartdns.js:334 smartdns.js:1168 smartdns.js:1327 smartdns.js:1501 +#: smartdns.js:345 smartdns.js:1190 smartdns.js:1360 smartdns.js:1534 msgid "Dual-stack IP Selection" -msgstr "双栈IP优选" +msgstr "双栈 IP 优选" -#: smartdns.js:335 smartdns.js:1169 smartdns.js:1328 smartdns.js:1502 +#: smartdns.js:346 smartdns.js:1191 smartdns.js:1361 smartdns.js:1535 msgid "Enable IP selection between IPv4 and IPv6" msgstr "启用 IPv4 和 IPv6 间的 IP 优选策略。" -#: smartdns.js:340 +#: smartdns.js:351 msgid "Domain prefetch" msgstr "域名预加载" -#: smartdns.js:341 +#: smartdns.js:352 msgid "Enable domain prefetch, accelerate domain response speed." msgstr "启用域名预加载,加速域名响应速度。" -#: smartdns.js:346 +#: smartdns.js:357 msgid "Serve expired" msgstr "缓存过期服务" -#: smartdns.js:347 +#: smartdns.js:358 msgid "" "Attempts to serve old responses from cache with a TTL of 0 in the response " "without waiting for the actual resolution to finish." -msgstr "查询性能优化,有请求时尝试回应TTL为0的过期记录,以避免查询等待。" +msgstr "查询性能优化,有请求时尝试回应 TTL 为 0 的过期记录,以避免查询等待。" -#: smartdns.js:352 +#: smartdns.js:363 msgid "Cache Size" msgstr "缓存大小" -#: smartdns.js:352 +#: smartdns.js:363 msgid "DNS domain result cache size" -msgstr "缓存DNS的结果,缓存大小,配置零则不缓存。" +msgstr "缓存 DNS 的结果,缓存大小,配置零则不缓存。" -#: smartdns.js:356 +#: smartdns.js:367 msgid "Cache Persist" msgstr "持久化缓存" -#: smartdns.js:356 +#: smartdns.js:367 msgid "Write cache to disk on exit and load on startup." -msgstr "退出时保存cache到磁盘,启动时加载。" +msgstr "退出时保存 Cache 到磁盘,启动时加载。" -#: smartdns.js:361 +#: smartdns.js:372 msgid "Resolve Local Hostnames" msgstr "解析本地主机名" -#: smartdns.js:361 +#: smartdns.js:372 msgid "Resolve local hostnames by reading Dnsmasq lease file." -msgstr "读取Dnsmasq的租约文件解析本地主机名。" +msgstr "读取 Dnsmasq 的租约文件解析本地主机名。" -#: smartdns.js:366 +#: smartdns.js:377 msgid "mDNS Lookup" -msgstr "mDNS查询" +msgstr "mDNS 查询" -#: smartdns.js:366 +#: smartdns.js:377 msgid "Resolve local network hostname via mDNS protocol." -msgstr "使用mDNS协议解析本地网络主机名。" +msgstr "使用 mDNS 协议解析本地网络主机名。" -#: smartdns.js:371 smartdns.js:589 smartdns.js:1174 smartdns.js:1336 -#: smartdns.js:1550 +#: smartdns.js:382 smartdns.js:600 smartdns.js:1196 smartdns.js:1369 +#: smartdns.js:1594 msgid "Force AAAA SOA" -msgstr "停用IPv6地址解析" +msgstr "停用 IPv6 地址解析" -#: smartdns.js:371 smartdns.js:589 smartdns.js:1174 smartdns.js:1336 -#: smartdns.js:1550 +#: smartdns.js:382 smartdns.js:600 smartdns.js:1196 smartdns.js:1369 +#: smartdns.js:1594 msgid "Force AAAA SOA." -msgstr "停用IPv6地址解析。" +msgstr "停用 IPv6 地址解析。" -#: smartdns.js:376 smartdns.js:594 smartdns.js:1179 +#: smartdns.js:387 smartdns.js:605 smartdns.js:1201 msgid "Force HTTPS SOA" -msgstr "停用HTTPS记录解析" +msgstr "停用 HTTPS 记录解析" -#: smartdns.js:376 smartdns.js:594 smartdns.js:1179 +#: smartdns.js:387 smartdns.js:605 smartdns.js:1201 msgid "Force HTTPS SOA." -msgstr "停用HTTPS记录解析。" +msgstr "停用 HTTPS 记录解析。" -#: smartdns.js:381 smartdns.js:602 smartdns.js:1184 smartdns.js:1340 -#: smartdns.js:1556 +#: smartdns.js:392 smartdns.js:613 smartdns.js:1206 smartdns.js:1373 +#: smartdns.js:1600 msgid "IPset Name" -msgstr "IPset名称" +msgstr "IPset 名称" -#: smartdns.js:381 smartdns.js:602 smartdns.js:1184 smartdns.js:1340 -#: smartdns.js:1556 +#: smartdns.js:392 smartdns.js:613 smartdns.js:1206 smartdns.js:1373 +#: smartdns.js:1600 msgid "IPset name." -msgstr "IPset名称。" +msgstr "IPset 名称。" -#: smartdns.js:393 smartdns.js:414 smartdns.js:614 smartdns.js:1196 -#: smartdns.js:1352 +#: smartdns.js:404 smartdns.js:425 smartdns.js:625 smartdns.js:1218 +#: smartdns.js:1385 msgid "ipset name format error, format: [#[4|6]:]ipsetname" -msgstr "IPset名称格式错误,格式:[#[4|6]:]ipsetname" +msgstr "IPset 名称格式错误,格式:[#[4|6]:]ipsetname" -#: smartdns.js:401 +#: smartdns.js:412 msgid "No Speed IPset Name" -msgstr "无速度时IPSet名称" +msgstr "无速度时 IPset 名称" -#: smartdns.js:402 +#: smartdns.js:413 msgid "Ipset name, Add domain result to ipset when speed check fails." -msgstr "IPset名称,当测速失败时,将查询到的结果添加到对应的IPSet集合中。" +msgstr "IPset 名称,当测速失败时,将查询到的结果添加到对应的 IPset 集合中。" -#: smartdns.js:422 smartdns.js:621 smartdns.js:1204 smartdns.js:1359 -#: smartdns.js:1562 +#: smartdns.js:433 smartdns.js:632 smartdns.js:1226 smartdns.js:1392 +#: smartdns.js:1606 msgid "NFTset Name" -msgstr "NFTSet名称" +msgstr "NFTset 名称" -#: smartdns.js:422 smartdns.js:621 smartdns.js:1204 smartdns.js:1359 -#: smartdns.js:1562 +#: smartdns.js:433 smartdns.js:632 smartdns.js:1226 smartdns.js:1392 +#: smartdns.js:1606 msgid "NFTset name, format: [#[4|6]:[family#table#set]]" -msgstr "NFTSet名称,格式:[#[4|6]:[family#table#set]]" +msgstr "NFTset 名称,格式:[#[4|6]:[family#table#set]]" -#: smartdns.js:434 smartdns.js:455 smartdns.js:633 smartdns.js:1216 -#: smartdns.js:1371 smartdns.js:1575 +#: smartdns.js:445 smartdns.js:466 smartdns.js:644 smartdns.js:1238 +#: smartdns.js:1404 smartdns.js:1619 msgid "NFTset name format error, format: [#[4|6]:[family#table#set]]" -msgstr "NFTSet名称格式错误,格式:[#[4|6]:[family#table#set]]" +msgstr "NFTset 名称格式错误,格式:[#[4|6]:[family#table#set]]" -#: smartdns.js:442 +#: smartdns.js:453 msgid "No Speed NFTset Name" -msgstr "无速度时NFTSet名称" +msgstr "无速度时 NFTset 名称" -#: smartdns.js:443 +#: smartdns.js:454 msgid "" "Nftset name, Add domain result to nftset when speed check fails, format: " "[#[4|6]:[family#table#set]]" -msgstr "NFTset名称,当测速失败时,将查询到的结果添加到对应的NFTSet集合中。" +msgstr "NFTset 名称,当测速失败时,将查询到的结果添加到对应的 NFTset 集合中。" -#: smartdns.js:463 +#: smartdns.js:474 msgid "Domain TTL" -msgstr "域名TTL" +msgstr "域名 TTL" -#: smartdns.js:463 +#: smartdns.js:474 msgid "TTL for all domain result." msgstr "设置所有域名的 TTL 值。" -#: smartdns.js:467 +#: smartdns.js:478 msgid "Domain TTL Min" -msgstr "域名TTL最小值" +msgstr "域名 TTL 最小值" -#: smartdns.js:468 +#: smartdns.js:479 msgid "Minimum TTL for all domain result." msgstr "所有域名的最小 TTL 值。" -#: smartdns.js:475 +#: smartdns.js:486 msgid "Domain TTL Max" -msgstr "域名TTL最大值" +msgstr "域名 TTL 最大值" -#: smartdns.js:476 +#: smartdns.js:487 msgid "Maximum TTL for all domain result." msgstr "所有域名的最大 TTL 值。" -#: smartdns.js:480 +#: smartdns.js:491 msgid "Reply Domain TTL Max" -msgstr "回应的域名TTL最大值" +msgstr "回应的域名 TTL 最大值" -#: smartdns.js:481 +#: smartdns.js:492 msgid "Reply maximum TTL for all domain result." -msgstr "设置返回给客户端的域名TTL最大值。" +msgstr "设置返回给客户端的域名 TTL 最大值。" -#: smartdns.js:485 smartdns.js:641 smartdns.js:1049 +#: smartdns.js:496 smartdns.js:652 smartdns.js:1060 msgid "Additional Server Args" msgstr "额外的服务器参数" -#: smartdns.js:486 smartdns.js:642 +#: smartdns.js:497 smartdns.js:653 msgid "" "Additional server args, refer to the help description of the bind option." -msgstr "额外的服务器参数,参考bind选项的帮助说明。" +msgstr "额外的服务器参数,参考 bind 选项的帮助说明。" -#: smartdns.js:492 smartdns.js:1225 +#: smartdns.js:503 smartdns.js:1247 msgid "Include Config Files
/etc/smartdns/conf.d" msgstr "包含配置文件
/etc/smartdns/conf.d" -#: smartdns.js:493 smartdns.js:1226 +#: smartdns.js:504 smartdns.js:1248 msgid "" "Include other config files from /etc/smartdns/conf.d or custom path, can be " "downloaded from the download page." msgstr "" -"包含配置文件,路径为/etc/smartdns/conf.d,或自定义配置文件路径,可以从下载页" +"包含配置文件,路径为 /etc/smartdns/conf.d,或自定义配置文件路径,可以从下载页" "面配置自动下载。" -#: smartdns.js:506 +#: smartdns.js:517 msgid "Hosts File" -msgstr "Hosts文件" +msgstr "Hosts 文件" -#: smartdns.js:506 +#: smartdns.js:517 msgid "Include hosts file." -msgstr "包含hosts文件。" +msgstr "包含 hosts 文件。" -#: smartdns.js:525 +#: smartdns.js:536 msgid "Enable or disable second DNS server." -msgstr "是否启用第二DNS服务器。" +msgstr "是否启用第二 DNS 服务器。" -#: smartdns.js:530 +#: smartdns.js:541 msgid "Smartdns local server port" -msgstr "SmartDNS本地服务端口" +msgstr "SmartDNS 本地服务端口" -#: smartdns.js:542 smartdns.js:917 smartdns.js:1103 smartdns.js:1262 -#: smartdns.js:1461 +#: smartdns.js:553 smartdns.js:928 smartdns.js:1114 smartdns.js:1284 +#: smartdns.js:1494 msgid "Server Group" msgstr "服务器组" -#: smartdns.js:543 +#: smartdns.js:554 msgid "Query DNS through specific dns server group, such as office, home." -msgstr "使用指定服务器组查询,比如office, home。" +msgstr "使用指定服务器组查询,比如 office、home。" -#: smartdns.js:549 +#: smartdns.js:560 msgid "Skip Speed Check" msgstr "跳过测速" -#: smartdns.js:550 +#: smartdns.js:561 msgid "Do not check speed." msgstr "禁用测速。" -#: smartdns.js:555 +#: smartdns.js:566 msgid "Skip Address Rules" -msgstr "跳过address规则" - -#: smartdns.js:556 -msgid "Skip address rules." -msgstr "跳过address规则。" - -#: smartdns.js:561 -msgid "Skip Nameserver Rule" -msgstr "跳过Nameserver规则" - -#: smartdns.js:562 -msgid "Skip nameserver rules." -msgstr "跳过Nameserver规则。" +msgstr "跳过 address 规则" #: smartdns.js:567 -msgid "Skip Ipset Rule" -msgstr "跳过ipset规则" +msgid "Skip address rules." +msgstr "跳过 address 规则。" -#: smartdns.js:568 -msgid "Skip ipset rules." -msgstr "跳过ipset规则。" +#: smartdns.js:572 +msgid "Skip Nameserver Rule" +msgstr "跳过 Nameserver 规则" #: smartdns.js:573 -msgid "Skip SOA Address Rule" -msgstr "跳过address SOA(#)规则" - -#: smartdns.js:574 -msgid "Skip SOA address rules." -msgstr "跳过address SOA(#)规则。" +msgid "Skip nameserver rules." +msgstr "跳过 Nameserver 规则。" #: smartdns.js:578 +msgid "Skip Ipset Rule" +msgstr "跳过 ipset 规则" + +#: smartdns.js:579 +msgid "Skip ipset rules." +msgstr "跳过 ipset 规则。" + +#: smartdns.js:584 +msgid "Skip SOA Address Rule" +msgstr "跳过 address SOA(#) 规则" + +#: smartdns.js:585 +msgid "Skip SOA address rules." +msgstr "跳过 address SOA(#) 规则。" + +#: smartdns.js:589 msgid "Skip Dualstack Selection" msgstr "跳过双栈优选" -#: smartdns.js:579 +#: smartdns.js:590 msgid "Skip Dualstack Selection." msgstr "跳过双栈优选。" -#: smartdns.js:584 +#: smartdns.js:595 msgid "Skip Cache" -msgstr "跳过cache" +msgstr "跳过 Cache" -#: smartdns.js:584 +#: smartdns.js:595 msgid "Skip Cache." -msgstr "跳过cache。" +msgstr "跳过 Cache。" -#: smartdns.js:598 +#: smartdns.js:609 msgid "Skip IP Alias" -msgstr "跳过IP别名" +msgstr "跳过 IP 别名" -#: smartdns.js:649 +#: smartdns.js:660 msgid "DNS64" msgstr "DNS64" -#: smartdns.js:657 +#: smartdns.js:668 msgid "Enable Auto Update" msgstr "启用自动更新" -#: smartdns.js:657 +#: smartdns.js:668 msgid "Enable daily (weekly) auto update." msgstr "启用每日(每周)自动更新" -#: smartdns.js:662 +#: smartdns.js:673 msgid "Update Time (Every Week)" msgstr "更新时间(每周)" -#: smartdns.js:663 +#: smartdns.js:674 msgid "Every Day" msgstr "每天" -#: smartdns.js:664 +#: smartdns.js:675 msgid "Every Monday" msgstr "每周一" -#: smartdns.js:665 +#: smartdns.js:676 msgid "Every Tuesday" msgstr "每周二" -#: smartdns.js:666 +#: smartdns.js:677 msgid "Every Wednesday" msgstr "每周三" -#: smartdns.js:667 +#: smartdns.js:678 msgid "Every Thursday" msgstr "每周四" -#: smartdns.js:668 +#: smartdns.js:679 msgid "Every Friday" msgstr "每周五" -#: smartdns.js:669 +#: smartdns.js:680 msgid "Every Saturday" msgstr "每周六" -#: smartdns.js:670 +#: smartdns.js:681 msgid "Every Sunday" msgstr "每周日" -#: smartdns.js:674 +#: smartdns.js:685 msgid "Update time (every day)" msgstr "更新时间(每天)" -#: smartdns.js:680 +#: smartdns.js:691 msgid "Upload Config File" msgstr "上传配置文件" -#: smartdns.js:681 +#: smartdns.js:692 msgid "Upload smartdns config file to /etc/smartdns/conf.d" -msgstr "上传配置文件到/etc/smartdns/conf.d" +msgstr "上传配置文件到 /etc/smartdns/conf.d" -#: smartdns.js:687 +#: smartdns.js:698 msgid "Upload Domain List File" msgstr "上传域名列表文件" -#: smartdns.js:688 +#: smartdns.js:699 msgid "Upload domain list file to /etc/smartdns/domain-set" -msgstr "上传域名列表文件到/etc/smartdns/domain-set" +msgstr "上传域名列表文件到 /etc/smartdns/domain-set" -#: smartdns.js:694 +#: smartdns.js:705 msgid "Upload File" msgstr "上传文件" -#: smartdns.js:700 +#: smartdns.js:711 msgid "Update Files" msgstr "更新文件" -#: smartdns.js:709 +#: smartdns.js:720 msgid "Update" msgstr "更新" -#: smartdns.js:712 +#: smartdns.js:723 msgid "Download Files" msgstr "下载文件" -#: smartdns.js:713 +#: smartdns.js:724 msgid "List of files to download." msgstr "下载文件列表。" -#: smartdns.js:721 +#: smartdns.js:732 msgid "File Name" msgstr "文件名" -#: smartdns.js:725 +#: smartdns.js:736 msgid "URL" msgstr "URL" -#: smartdns.js:734 +#: smartdns.js:745 msgid "URL format error, format: http:// or https://" -msgstr "URL格式错误,格式:http://或https://" +msgstr "URL 格式错误,格式:http:// 或 https://" -#: smartdns.js:740 smartdns.js:905 +#: smartdns.js:751 smartdns.js:916 msgid "type" msgstr "类型" -#: smartdns.js:740 +#: smartdns.js:751 msgid "File Type" msgstr "文件类型" -#: smartdns.js:741 +#: smartdns.js:752 msgid "domain list (/etc/smartdns/domain-set)" msgstr "域名列表(/etc/smartdns/domain-set)" -#: smartdns.js:742 +#: smartdns.js:753 msgid "smartdns config (/etc/smartdns/conf.d)" -msgstr "smartdns 配置文件(/etc/smartdns/conf.d)" +msgstr "SmartDNS 配置文件(/etc/smartdns/conf.d)" -#: smartdns.js:743 +#: smartdns.js:754 msgid "ip-set file (/etc/smartdns/ip-set)" -msgstr "IP集合列表文件(/etc/smartdns/ip-set)" +msgstr "IP 集合列表文件(/etc/smartdns/ip-set)" -#: smartdns.js:744 +#: smartdns.js:755 msgid "other file (/etc/smartdns/download)" msgstr "其它文件(/etc/smartdns/download)" -#: smartdns.js:748 +#: smartdns.js:759 msgid "Description" msgstr "描述" -#: smartdns.js:755 +#: smartdns.js:766 msgid "Proxy Server" msgstr "代理服务器" -#: smartdns.js:755 +#: smartdns.js:766 msgid "Proxy Server URL, format: [socks5|http]://user:pass@ip:port." msgstr "代理服务器地址,格式:[socks5|http]://user:pass@ip:port。" -#: smartdns.js:763 +#: smartdns.js:774 msgid "" "Proxy server URL format error, format: [socks5|http]://user:pass@ip:port." msgstr "代理服务器地址格式错误,格式:[socks5|http]://user:pass@ip:port。" -#: smartdns.js:773 +#: smartdns.js:784 msgid "smartdns custom settings" -msgstr "smartdns 自定义设置,具体配置参数参考指导" +msgstr "SmartDNS 自定义设置,具体配置参数参考指导" -#: smartdns.js:787 +#: smartdns.js:798 msgid "Generate Coredump" -msgstr "生成coredump" +msgstr "生成 Coredump" -#: smartdns.js:788 +#: smartdns.js:799 msgid "" "Generate Coredump file when smartdns crash, coredump file is located at /tmp/" "smartdns.xxx.core." msgstr "" -"当smartdns异常时生成coredump文件,coredump文件在/tmp/smartdns.xxx.core." +"当 SmartDNS 异常时生成 Coredump 文件,Coredump 文件在 /tmp/smartdns.xxx.core。" -#: smartdns.js:792 +#: smartdns.js:803 msgid "Log Level" msgstr "日志级别" -#: smartdns.js:804 +#: smartdns.js:815 msgid "Log Output Mode" msgstr "日志输出模式" -#: smartdns.js:807 smartdns.js:848 +#: smartdns.js:818 smartdns.js:859 msgid "file" msgstr "文件" -#: smartdns.js:808 smartdns.js:849 +#: smartdns.js:819 smartdns.js:860 msgid "syslog" msgstr "系统日志" -#: smartdns.js:810 +#: smartdns.js:821 msgid "Log Size" msgstr "日志大小" -#: smartdns.js:815 +#: smartdns.js:826 msgid "Log Number" msgstr "日志数量" -#: smartdns.js:820 +#: smartdns.js:831 msgid "Log File" msgstr "日志文件路径" -#: smartdns.js:825 smartdns.js:833 +#: smartdns.js:836 smartdns.js:844 msgid "View Log" msgstr "查看日志" -#: smartdns.js:840 +#: smartdns.js:851 msgid "Enable Audit Log" msgstr "启用审计日志" -#: smartdns.js:845 +#: smartdns.js:856 msgid "Audit Log Output Mode" msgstr "审计日志输出模式" -#: smartdns.js:852 +#: smartdns.js:863 msgid "Audit Log Size" msgstr "审计日志大小" -#: smartdns.js:857 +#: smartdns.js:868 msgid "Audit Log Number" msgstr "审计日志数量" -#: smartdns.js:862 +#: smartdns.js:873 msgid "Audit Log File" msgstr "审计日志文件路径" -#: smartdns.js:870 +#: smartdns.js:881 msgid "Upstream Servers" msgstr "上游服务器" -#: smartdns.js:871 +#: smartdns.js:882 msgid "" "Upstream Servers, support UDP, TCP, DoT, DoH, DoQ, DoH3 protocol. Please " "configure multiple DNS servers, including multiple foreign DNS servers." @@ -820,113 +824,113 @@ msgstr "" "上游 DNS 服务器,支持 UDP,TCP,DoT,DoH,DoQ,DoH3 协议。请配置多个上游 DNS " "服务器,包括多个国内外服务器。" -#: smartdns.js:887 +#: smartdns.js:898 msgid "DNS Server Name" -msgstr "DNS服务器名称" +msgstr "DNS 服务器名称" -#: smartdns.js:890 +#: smartdns.js:901 msgid "ip" msgstr "ip" -#: smartdns.js:890 +#: smartdns.js:901 msgid "DNS Server ip" -msgstr "DNS服务器IP" +msgstr "DNS 服务器 IP" -#: smartdns.js:895 +#: smartdns.js:906 msgid "port" msgstr "端口" -#: smartdns.js:895 +#: smartdns.js:906 msgid "DNS Server port" -msgstr "DNS服务器端口" +msgstr "DNS 服务器端口" -#: smartdns.js:905 +#: smartdns.js:916 msgid "DNS Server type" msgstr "协议类型" -#: smartdns.js:907 +#: smartdns.js:918 msgid "udp" msgstr "udp" -#: smartdns.js:908 +#: smartdns.js:919 msgid "tcp" msgstr "tcp" -#: smartdns.js:909 +#: smartdns.js:920 msgid "tls" msgstr "tls" -#: smartdns.js:910 +#: smartdns.js:921 msgid "https" msgstr "https" -#: smartdns.js:911 +#: smartdns.js:922 msgid "quic" msgstr "quic" -#: smartdns.js:912 +#: smartdns.js:923 msgid "h3" msgstr "h3" -#: smartdns.js:917 +#: smartdns.js:928 msgid "DNS Server group" msgstr "服务器组" -#: smartdns.js:936 +#: smartdns.js:947 msgid "Exclude Default Group" msgstr "从默认组中排除" -#: smartdns.js:936 +#: smartdns.js:947 msgid "Exclude DNS Server from default group." -msgstr "从default默认服务器组中排除。" +msgstr "从 default 默认服务器组中排除。" -#: smartdns.js:943 +#: smartdns.js:954 msgid "IP Blacklist Filtering" -msgstr "IP黑名单过滤" +msgstr "IP 黑名单过滤" -#: smartdns.js:944 +#: smartdns.js:955 msgid "Filtering IP with blacklist" -msgstr "使用IP黑名单过滤" +msgstr "使用 IP 黑名单过滤" -#: smartdns.js:950 +#: smartdns.js:961 msgid "TLS Hostname Verify" -msgstr "校验TLS主机名" - -#: smartdns.js:951 -msgid "Set TLS hostname to verify." -msgstr "设置校验TLS主机名。" +msgstr "校验 TLS 主机名" #: smartdns.js:962 +msgid "Set TLS hostname to verify." +msgstr "设置校验 TLS 主机名。" + +#: smartdns.js:973 msgid "No check certificate" msgstr "停用证书校验" -#: smartdns.js:963 +#: smartdns.js:974 msgid "Do not check certificate." msgstr "不校验证书的合法性。" -#: smartdns.js:973 +#: smartdns.js:984 msgid "TLS SNI name" -msgstr "TLS SNI名称" - -#: smartdns.js:974 -msgid "Sets the server name indication for query. '-' for disable SNI name." -msgstr "设置服务器SNI名称,‘-’表示禁用SNI名称。" +msgstr "TLS SNI 名称" #: smartdns.js:985 -msgid "HTTP Host" -msgstr "HTTP主机" +msgid "Sets the server name indication for query. '-' for disable SNI name." +msgstr "设置服务器 SNI 名称,‘-’表示禁用 SNI 名称。" -#: smartdns.js:986 +#: smartdns.js:996 +msgid "HTTP Host" +msgstr "HTTP 主机" + +#: smartdns.js:997 msgid "" "Set the HTTP host used for the query. Use this parameter when the host of " "the URL address is an IP address." -msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时,使用此参数。" +msgstr "设置查询时使用的 HTTP 主机,当 URL 地址的 host 是 IP 地址时,使用此参数。" -#: smartdns.js:995 +#: smartdns.js:1006 msgid "TLS SPKI Pinning" msgstr "TLS SPKI 指纹" -#: smartdns.js:996 +#: smartdns.js:1007 msgid "" "Used to verify the validity of the TLS server, The value is Base64 encoded " "SPKI fingerprint, leaving blank to indicate that the validity of TLS is not " @@ -935,322 +939,322 @@ msgstr "" "用于校验 TLS 服务器的有效性,数值为 Base64 编码的 SPKI 指纹,留空表示不验证 " "TLS 的合法性。" -#: smartdns.js:1008 +#: smartdns.js:1019 msgid "Marking Packets" msgstr "数据包标记" -#: smartdns.js:1009 +#: smartdns.js:1020 msgid "Set mark on packets." msgstr "设置数据包标记。" -#: smartdns.js:1016 +#: smartdns.js:1027 msgid "Use Proxy" msgstr "使用代理" -#: smartdns.js:1017 +#: smartdns.js:1028 msgid "Use proxy to connect to upstream DNS server." -msgstr "使用代理连接上游DNS服务器。" +msgstr "使用代理连接上游 DNS 服务器。" -#: smartdns.js:1031 +#: smartdns.js:1042 msgid "Please set proxy server first." msgstr "请先设置代理服务器。" -#: smartdns.js:1035 +#: smartdns.js:1046 msgid "Only socks5 proxy support udp server." -msgstr "仅SOCKS5代理支持UDP服务器。" +msgstr "仅 SOCKS5 代理支持 UDP 服务器。" -#: smartdns.js:1042 +#: smartdns.js:1053 msgid "Fallback" msgstr "备用服务器" -#: smartdns.js:1043 +#: smartdns.js:1054 msgid "" "Mark this server as a fallback server, use it only when default servers fail." msgstr "使用该服务器作为备用服务器,在默认服务器失效时启用。" -#: smartdns.js:1050 +#: smartdns.js:1061 msgid "Additional Args for upstream dns servers" msgstr "额外的上游 DNS 服务器参数" -#: smartdns.js:1058 +#: smartdns.js:1069 msgid "Client Rules" msgstr "客户端规则" -#: smartdns.js:1058 +#: smartdns.js:1069 msgid "Client Rules Settings, can achieve parental control functionality." msgstr "客户端规则设置,可以实现家长控制功能。" -#: smartdns.js:1062 +#: smartdns.js:1073 msgid "Basic Settings" msgstr "基本设置" -#: smartdns.js:1064 smartdns.js:1255 +#: smartdns.js:1075 smartdns.js:1277 msgid "DNS Block Setting" msgstr "域名屏蔽设置" -#: smartdns.js:1070 +#: smartdns.js:1081 msgid "Client Address" msgstr "客户端地址" -#: smartdns.js:1071 +#: smartdns.js:1082 msgid "" "If a client address is specified, only that client will apply this rule. You " "can enter an IP address, such as 1.2.3.4, or a MAC address, such as aa:bb:cc:" "dd:ee:ff." msgstr "" -"如果指定了客户端,那么对应的客户端会应用相应的规则,可以输入IP地址,如:" -"1.2.3.4,或MAC地址,如:aa:bb:cc:dd:ee:ff。" +"如果指定了客户端,那么对应的客户端会应用相应的规则,可以输入 IP 地址,如:" +"1.2.3.4,或 MAC 地址,如:aa:bb:cc:dd:ee:ff。" -#: smartdns.js:1092 +#: smartdns.js:1103 msgid "Client address format error, please input ip adress or mac address." -msgstr "客户端地址格式错误,请输入 IP 地址或 mac 地址。" +msgstr "客户端地址格式错误,请输入 IP 地址或 MAC 地址。" -#: smartdns.js:1095 +#: smartdns.js:1106 msgid "Client Address File" msgstr "客户端地址文件" -#: smartdns.js:1096 +#: smartdns.js:1107 msgid "Upload client address file, same as Client Address function." msgstr "上传客户端地址文件,与客户端地址功能相同。" -#: smartdns.js:1103 smartdns.js:1262 smartdns.js:1461 +#: smartdns.js:1114 smartdns.js:1284 smartdns.js:1494 msgid "DNS Server group belongs to, such as office, home." -msgstr "设置服务器组,例如office,home" +msgstr "设置服务器组,例如 office、home" -#: smartdns.js:1123 smartdns.js:1282 smartdns.js:1481 +#: smartdns.js:1134 smartdns.js:1304 smartdns.js:1514 #, javascript-format msgid "Server Group %s not exists" -msgstr "服务器组%s不存在" +msgstr "服务器组 %s 不存在" -#: smartdns.js:1239 smartdns.js:1385 smartdns.js:1415 smartdns.js:1485 +#: smartdns.js:1261 smartdns.js:1418 smartdns.js:1448 smartdns.js:1518 msgid "Domain List File" msgstr "域名列表文件" -#: smartdns.js:1239 smartdns.js:1415 +#: smartdns.js:1261 smartdns.js:1448 msgid "Upload domain list file." msgstr "上传域名列表文件" -#: smartdns.js:1250 +#: smartdns.js:1272 msgid "Domain Rules" msgstr "域名规则" -#: smartdns.js:1250 +#: smartdns.js:1272 msgid "Domain Rules Settings" msgstr "域名规则设置" -#: smartdns.js:1254 +#: smartdns.js:1276 msgid "DNS Forwarding Setting" msgstr "域名分流设置" -#: smartdns.js:1256 smartdns.js:1443 +#: smartdns.js:1278 smartdns.js:1476 msgid "Domain Rule List" msgstr "域名规则列表" -#: smartdns.js:1256 +#: smartdns.js:1278 msgid "Set Specific domain rule list." msgstr "设置指定域名的规则列表。" -#: smartdns.js:1257 +#: smartdns.js:1279 msgid "Domain Address" msgstr "域名地址" -#: smartdns.js:1257 +#: smartdns.js:1279 msgid "Set Specific domain ip address." -msgstr "设置指定域名的IP地址。" +msgstr "设置指定域名的 IP 地址。" -#: smartdns.js:1333 smartdns.js:1507 +#: smartdns.js:1366 smartdns.js:1540 msgid "Yes" msgstr "是" -#: smartdns.js:1334 smartdns.js:1508 +#: smartdns.js:1367 smartdns.js:1541 msgid "No" msgstr "否" -#: smartdns.js:1379 smartdns.js:1583 smartdns.js:1680 +#: smartdns.js:1412 smartdns.js:1627 smartdns.js:1724 msgid "Additional Rule Flag" msgstr "额外规则标识" -#: smartdns.js:1380 smartdns.js:1584 +#: smartdns.js:1413 smartdns.js:1628 msgid "" "Additional Flags for rules, read help on domain-rule for more information." -msgstr "额外的规则标识,具体参考domain-rule的帮助说明。" +msgstr "额外的规则标识,具体参考 domain-rule 的帮助说明。" -#: smartdns.js:1386 smartdns.js:1486 +#: smartdns.js:1419 smartdns.js:1519 msgid "" "Upload domain list file, or configure auto download from Download File " "Setting page." msgstr "上传域名列表文件,或在下载文件设置页面设置自动下载。" -#: smartdns.js:1394 smartdns.js:1423 +#: smartdns.js:1427 smartdns.js:1456 msgid "Domain List" msgstr "域名列表" -#: smartdns.js:1394 +#: smartdns.js:1427 msgid "Configure forwarding domain name list." msgstr "配置分流域名列表" -#: smartdns.js:1423 +#: smartdns.js:1456 msgid "Configure block domain list." msgstr "配置屏蔽域名列表" -#: smartdns.js:1444 +#: smartdns.js:1477 msgid "Configure domain rule list." msgstr "配置域名规则列表" -#: smartdns.js:1459 +#: smartdns.js:1492 msgid "Domain Rule Name" msgstr "域名规则名称" -#: smartdns.js:1492 +#: smartdns.js:1525 msgid "Block domain" msgstr "屏蔽域名" -#: smartdns.js:1492 +#: smartdns.js:1525 msgid "Block domain." msgstr "屏蔽域名。" -#: smartdns.js:1594 +#: smartdns.js:1638 msgid "" "Specify an IP address to return for any host in the given domains, Queries " "in the domains are never forwarded and always replied to with the specified " "IP address which may be IPv4 or IPv6." msgstr "" -"配置特定域名返回特定的IP地址,域名查询将不到上游服务器请求,直接返回配置的IP" +"配置特定域名返回特定的 IP 地址,域名查询将不到上游服务器请求,直接返回配置的 IP" "地址,可用于广告屏蔽。" -#: smartdns.js:1613 +#: smartdns.js:1657 msgid "IP Rules" -msgstr "IP规则" +msgstr "IP 规则" -#: smartdns.js:1613 +#: smartdns.js:1657 msgid "IP Rules Settings" -msgstr "IP规则设置" +msgstr "IP 规则设置" -#: smartdns.js:1617 smartdns.js:1623 +#: smartdns.js:1661 smartdns.js:1667 msgid "IP Rule List" -msgstr "IP规则列表" +msgstr "IP 规则列表" -#: smartdns.js:1617 +#: smartdns.js:1661 msgid "Set Specific ip rule list." -msgstr "设置对应IP的规则。" +msgstr "设置对应 IP 的规则。" -#: smartdns.js:1618 +#: smartdns.js:1662 msgid "IP Blacklist" -msgstr "IP黑名单" +msgstr "IP 黑名单" -#: smartdns.js:1618 +#: smartdns.js:1662 msgid "Set Specific ip blacklist." msgstr "设置指定的 IP 黑名单列表。" -#: smartdns.js:1624 +#: smartdns.js:1668 msgid "Configure ip rule list." -msgstr "配置IP规则列表" +msgstr "配置 IP 规则列表" -#: smartdns.js:1639 +#: smartdns.js:1683 msgid "IP Rule Name" -msgstr "IP规则名称" +msgstr "IP 规则名称" -#: smartdns.js:1643 +#: smartdns.js:1687 msgid "IP Set File" -msgstr "IP集合列表文件" +msgstr "IP 集合列表文件" -#: smartdns.js:1643 +#: smartdns.js:1687 msgid "Upload IP set file." -msgstr "上传IP集合列表文件。" +msgstr "上传 IP 集合列表文件。" -#: smartdns.js:1649 +#: smartdns.js:1693 msgid "IP Addresses" -msgstr "IP地址" +msgstr "IP 地址" -#: smartdns.js:1649 +#: smartdns.js:1693 msgid "IP addresses, CIDR format." -msgstr "IP地址,CIDR格式。" +msgstr "IP 地址,CIDR 格式。" -#: smartdns.js:1654 +#: smartdns.js:1698 msgid "Whitelist IP" msgstr "白名单" -#: smartdns.js:1654 +#: smartdns.js:1698 msgid "Whitelist IP Rule, Accept IP addresses within the range." -msgstr "白名单规则,接受指定范围的IP地址。" +msgstr "白名单规则,接受指定范围的 IP 地址。" -#: smartdns.js:1659 +#: smartdns.js:1703 msgid "Blacklist IP" msgstr "黑名单" -#: smartdns.js:1659 +#: smartdns.js:1703 msgid "Blacklist IP Rule, Decline IP addresses within the range." -msgstr "黑名单规则,拒绝指定范围的IP地址。" +msgstr "黑名单规则,拒绝指定范围的 IP 地址。" -#: smartdns.js:1664 +#: smartdns.js:1708 msgid "Ignore IP" -msgstr "忽略IP" +msgstr "忽略 IP" -#: smartdns.js:1664 +#: smartdns.js:1708 msgid "Do not use these IP addresses." -msgstr "忽略这些IP地址" +msgstr "忽略这些 IP 地址" -#: smartdns.js:1669 +#: smartdns.js:1713 msgid "Bogus nxdomain" -msgstr "假冒IP" +msgstr "假冒 IP" -#: smartdns.js:1669 +#: smartdns.js:1713 msgid "Return SOA when the requested result contains a specified IP address." -msgstr "当结果包含对应范围的IP时,返回SOA。" +msgstr "当结果包含对应范围的 IP 时,返回 SOA。" -#: smartdns.js:1674 +#: smartdns.js:1718 msgid "IP alias" -msgstr "IP别名" +msgstr "IP 别名" -#: smartdns.js:1674 +#: smartdns.js:1718 msgid "" "IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such " "as Cloudflare's CDN." -msgstr "IP地址映射,可用于支持AnyCast IP的CDN加速,比如Cloudflare的CDN。" +msgstr "IP 地址映射,可用于支持 Anycast IP 的 CDN 加速,比如 Cloudflare 的 CDN。" -#: smartdns.js:1681 +#: smartdns.js:1725 msgid "Additional Flags for rules, read help on ip-rule for more information." -msgstr "额外的规则标识,具体参考ip-rule的帮助说明。" +msgstr "额外的规则标识,具体参考 ip-rule 的帮助说明。" -#: smartdns.js:1690 +#: smartdns.js:1734 msgid "" "Configure IP blacklists that will be filtered from the results of specific " "DNS server." -msgstr "配置需要从指定域名服务器结果过滤的IP黑名单。" +msgstr "配置需要从指定域名服务器结果过滤的 IP 黑名单。" -#: smartdns.js:1707 +#: smartdns.js:1751 msgid "Technical Support" msgstr "技术支持" -#: smartdns.js:1708 +#: smartdns.js:1752 msgid "If you like this software, please buy me a cup of coffee." msgstr "如果本软件对你有帮助,请给作者加个蛋。" -#: smartdns.js:1712 +#: smartdns.js:1756 msgid "SmartDNS official website" -msgstr "SmartDNS官方网站" +msgstr "SmartDNS 官方网站" -#: smartdns.js:1713 +#: smartdns.js:1757 msgid "open website" msgstr "打开网站" -#: smartdns.js:1720 smartdns.js:1721 +#: smartdns.js:1764 smartdns.js:1765 msgid "Report bugs" -msgstr "报告BUG" +msgstr "报告 Bug" -#: smartdns.js:1728 +#: smartdns.js:1772 msgid "Donate to smartdns" -msgstr "捐助smartdns项目" +msgstr "捐助 SmartDNS 项目" -#: smartdns.js:1729 +#: smartdns.js:1773 msgid "Donate" msgstr "捐助" -#: smartdns.js:1735 +#: smartdns.js:1779 msgid "Restart Service" msgstr "重启服务" -#: smartdns.js:1744 +#: smartdns.js:1788 msgid "Restart" msgstr "重启" diff --git a/luci-app-ssr-plus/Makefile b/luci-app-ssr-plus/Makefile index 14c8cd4b..b49c7030 100644 --- a/luci-app-ssr-plus/Makefile +++ b/luci-app-ssr-plus/Makefile @@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus LUCI_PKGARCH:=all PKG_NAME:=luci-app-ssr-plus PKG_VERSION:=196 -PKG_RELEASE:=38 +PKG_RELEASE:=39 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua index ede40fa5..dd204d16 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua @@ -43,7 +43,7 @@ local excluded_domain = { local mydnsip = '127.0.0.1' local mydnsport = '5335' local ipsetname = 'gfwlist' -local new_appledns = uci:get_first("shadowsocksr", "global", "apple_dns") +local new_appledns = uci:get_first("shadowsocksr", "global", "apple_dns", "") local bc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- base64decoding local function base64_dec(data) @@ -111,10 +111,10 @@ local function generate_apple(type) end end end - for _, domain in ipairs(domains) do - if new_appledns and new_appledns ~= "" then - out:write(string.format("server=/%s/%s\n", domain, new_appledns)) - end + if new_appledns and new_appledns ~= "" then + for _, domain in ipairs(domains) do + out:write(string.format("server=/%s/%s\n", domain, new_appledns)) + end end out:close() os.remove("/tmp/ssr-update.tmp") @@ -180,6 +180,8 @@ local function update(url, file, type, file2) apple:close() if new_appledns and new_appledns ~= "" then generate_apple(type) + else + os.remove("/tmp/ssr-update.tmp") end end if type == "ad_data" then diff --git a/naiveproxy/Makefile b/naiveproxy/Makefile index af239edb..ead2658f 100644 --- a/naiveproxy/Makefile +++ b/naiveproxy/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=naiveproxy -PKG_VERSION:=149.0.7827.114 +PKG_VERSION:=150.0.7871.63 PKG_RELEASE:=1 ARCH_PREBUILT:=$(ARCH_PACKAGES) diff --git a/quectel_MHI/Makefile b/quectel_MHI/Makefile old mode 100644 new mode 100755 index de638550..3f81ee55 --- a/quectel_MHI/Makefile +++ b/quectel_MHI/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=pcie_mhi PKG_VERSION:=1.3.8 -PKG_RELEASE:=29 +PKG_RELEASE:=30 include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/package.mk diff --git a/torrserver/Makefile b/torrserver/Makefile index a1e6c124..acbfd4fc 100644 --- a/torrserver/Makefile +++ b/torrserver/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=torrserver -PKG_VERSION:=MatriX.141.10 -PKG_RELEASE:=11 +PKG_VERSION:=MatriX.142 +PKG_RELEASE:=12 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/YouROK/TorrServer.git -PKG_SOURCE_VERSION:=394c915bfc64c8448a7da166e909da074420172e +PKG_SOURCE_VERSION:=f0585eb7dfc92e0e5fdcb17a7e7eead212201e7d PKG_MIRROR_HASH:=skip PKG_MAINTAINER:=Konstantine Shevlakov