💐 Sync 2026-10-06 12:33:44

This commit is contained in:
github-actions[bot] committed 2026-10-06 12:33:44 +08:00
1 parent 8be03ce939
commit 7fe69dbb3a
246 files changed
+50330 -3414

No files matched your search

@@ -0,0 +1,62 @@
-- msg.lua — 组合型用户可见消息的拼接与还原(纯 Lua,不 require luci.i18n)
--
-- 为什么需要它:
-- 后端模块**不能** require("luci.i18n") —— substore-cron.sh 在独立的 lua 进程里
-- 跑 core.sync,那里没有 LuCI 环境。所以后端一律返回语言中立的英文 msgid,
-- 翻译只发生在显示边界(控制器 / 视图)。
--
-- 但有一类消息是「msgid 前缀 + 动态值」拼出来的,例如:
-- "Invalid proxy config: " .. reason
-- 整体查翻译表必然落空 —— 值每次都不同 —— 前缀那半句就永远翻译不了。
-- 这里用分隔符把各段拼起来,显示边界按分隔符拆开、**逐段**查表,
-- 于是前缀也能翻译,动态值原样输出。
--
-- 分隔符取 "\1"(SOH):它不会出现在任何合法取值里(URL / 主机名 / User-Agent /
-- 端口 / 协议名在 http.lua 里都校验过),而且 util.json_encode 会把控制字符
-- 转义成 \u0001,所以组合消息存进 meta.error 再读回来仍然完好。
--
-- 拆分只按**第一个**分隔符切,剩下的递归处理,所以嵌套(值本身又是组合消息)
-- 天然成立。全程精确,没有任何启发式匹配。
local M = {}
M.SEP = "\1"
-- 把若干段依次拼成一条组合消息。段可以是 msgid(会被翻译),
-- 也可以是要原样显示的动态值(查表落空即原样输出)。
function M.compose(...)
local out = {}
for i = 1, select("#", ...) do
if i > 1 then out[#out + 1] = M.SEP end
out[#out + 1] = tostring((select(i, ...)))
end
return table.concat(out)
end
-- compose 的两段简写,读起来更贴近原来的 `前缀 .. 值`。
function M.join(prefix, value)
return M.compose(prefix, value)
end
-- 把一串 msgid 用 sep 连成组合消息。sep 自己也是一段(也参与查表),
-- 因为中文里的连接符未必与英文相同。
function M.compose_list(parts, sep)
local out = {}
for i, p in ipairs(parts) do
if i > 1 then out[#out + 1] = M.SEP .. tostring(sep) .. M.SEP end
out[#out + 1] = tostring(p)
end
return table.concat(out)
end
-- 翻译一条(可能是组合消息的)用户可见文案。translate 由调用方传入 ——
-- 本模块不 require luci.i18n(见文件头)。
-- 对**已经翻译过**的串是幂等的:它不含分隔符,整串查表落空即原样返回。
function M.translate(s, translate)
if s == nil then return nil end
s = tostring(s)
local i = s:find(M.SEP, 1, true)
if not i then return translate(s) end
return translate(s:sub(1, i - 1)) .. M.translate(s:sub(i + 1), translate)
end
return M