mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-09 21:47:59 +08:00
63 lines
2.6 KiB
Lua
63 lines
2.6 KiB
Lua
-- 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
|