Files

63 lines
2.6 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 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