因BWiki近期更新,普通用户无法直接访问除重定向、编辑表格外的特殊页面(如最近更改等),进行3次有效编辑后即可恢复。
全站通知:
模块:Tr
刷
历
编
跳到导航
跳到搜索
此模块的文档可以在模块:Tr/doc创建
local database = mw.loadData( 'Module:Tr/db' )
local main_database = database.main
local prefix_database = database.prefix
local postfix_database = database.postfix
local input_frame --保存全局输入frame
-- 所有local函数,统一定义方便递归
local stripArticle, tcBasic, procNumberPostfix, procParenPostfix, proc, tcPlural
-- 尝试检查各种可能的复数变体,匹配就tc返回,否则nil
function tcPlural(str)
if not str then return end
local matches
matches = str:match('^(.+)s$') -- -s
if matches then
if main_database[matches] then
return main_database[matches]
else
matches = matches:match('^(.+)e$') -- -es
if matches then
if main_database[matches] then
return main_database[matches]
else
matches = matches:match('^(.+)i$') -- ies
if matches then
matches = matches..'y'
if main_database[matches] then return main_database[matches] end
else
--和上一个匹配互斥,放在else可以省点事
matches = str:match('^(.+)ves$') -- ves
if matches then
matches = matches..'f' -- -f
if main_database[matches] then return main_database[matches] end
matches = matches..'e' -- -fe
if main_database[matches] then return main_database[matches] end
end
end
end
end
end
end
end
-- 脱冠词 成功脱掉返回脱掉后的文本,失败nil
function stripArticle(str)
return str:match('^the%s+(.+)$') or str:match('^an?%s+(.+)$')
end
-- 基本:冠词/复数。
function tcBasic(en)
if main_database[en] then return main_database[en] end
local main = stripArticle(en)
if main then
--有冠词
if main_database[main] then return main_database[main] end
local zh = tcPlural(main)
if zh then return zh end
else
--无冠词
if main_database[en] then return main_database[en] end
end
return tcPlural(en)
end
-- 尝试去掉数字后缀,然后再次尝试做处理。
function procNumberPostfix(en)
local main, number = en:match('^(.-)%s+([%d%.]+)$') --后缀允许数字和.混合。可能会带来少数没意义的匹配,问题不大。
if main then
zh = tcBasic(main) or proc(main) --前面还是要尝试基本款翻译,以应对 block 2 这样的情况
if zh then
return zh..' '..number..' ' --中文和数字之间要有空格
end
end
end
-- 尝试去掉括号后缀,然后再次尝试做处理。
function procParenPostfix(en)
local main, postfix, postfix_zh
main, postfix = en:match('^(.-)%s*(%b())$')
if main then
postfix_zh = postfix_database[postfix] -- 带着括号直接看是否有专用后缀
if not postfix_zh then
postfix = postfix:sub(2,-2)
postfix_zh = postfix_database[postfix] or tcBasic(postfix) -- 没?去掉括号再看一次,同时处理普通后缀
if postfix_zh then
postfix_zh = '('..postfix_zh..')' -- 用中文括号。
end
end
end
--加上前面主体部分
if postfix_zh then
local zh = tcBasic(main) or proc(main)
if zh then return zh..postfix_zh end
end
end
-- 复杂处理:先尝试做,/and/or分割,然后考虑数字后缀、然后尝试括号后缀、然后专用后缀/前缀、然后普通后缀/前缀。
function proc(en)
local a, b, zh_a, zh_b
-- and/or 要考虑牛津逗号的问题,否则会导致 a, b, and c 最后被分离出“and c”片段。另外 “, and”附近的空格问题要处理。
-- X and Y
a, sep, b = en:match('^(.-)%s*([,%s])%s*and%s+(.+)$')
if a then
zh_a = tcBasic(a) or proc(a)
if zh_a then
zh_b = tcBasic(b) or proc(b)
if zh_b then
return zh_a..((sep == ',') and '、和' or '和')..zh_b
end
end
end
-- X or Y
a, sep, b = en:match('^(.-)%s*([,%s])%s*or%s+(.+)$')
if a then
zh_a = tcBasic(a) or proc(a)
if zh_a then
zh_b = tcBasic(b) or proc(b)
if zh_b then
return zh_a..((sep == ',') and '、或' or '或')..zh_b
end
end
end
-- X , Y and X / Y
a, sep, b = en:match('^(.-)%s*([,/])%s*(.+)$')
if a then
zh_a = tcBasic(a) or proc(a)
if zh_a then
zh_b = tcBasic(b) or proc(b)
if zh_b then
return zh_a..((sep == ',') and '、' or '/')..zh_b
end
end
end
local zh, postfix_main, prefix_main, postfix, prefix, postfix_zh, prefix_zh
zh = procNumberPostfix(en)
if zh then return zh end
zh = procParenPostfix(en)
if zh then return zh end
--尝试解析后缀
postfix_main, postfix = en:match('^(.-)%s+([%w%d]+)$')
--专用后缀
if postfix_main then
postfix_zh = postfix_database[postfix]
if postfix_zh then
zh = tcBasic(postfix_main) or proc(postfix_main)
if zh then return zh..postfix_zh end
end
end
--尝试解析前缀:
en = stripArticle(en) or en -- 预脱冠词,否则前缀分析没意义
prefix, prefix_main = en:match('^(%S+)%s+(.+)$')
-- 专用前缀
if prefix_main then
prefix_zh = prefix_database[prefix]
if prefix_zh then
zh = tcBasic(prefix_main) or proc(prefix_main)
if zh then return prefix_zh..zh end
end
end
-- 普通后缀:
if postfix_main then
postfix_zh = tcBasic(postfix)
if postfix_zh then
zh = tcBasic(postfix_main) or proc(postfix_main)
if zh then return zh..postfix_zh end
end
end
-- 普通前缀
if prefix_main then
prefix_zh = tcBasic(prefix)
if prefix_zh then
zh = tcBasic(prefix_main) or proc(prefix_main)
if zh then return prefix_zh..zh end
end
end
end
-- 主返回点
return { go = function(frame)
input_frame = frame
local input = frame.args[1]:match("^%s*(.-)%s*$") --module内要自己trim
local en = input:lower()
local zh, m
--有冠词试试不脱冠词直接测试复数,补充template内的缺失(诸如 The Axe 这种天生带 the 的专有名词)
if en:match('^the%s+(.+)$') then
zh = tcPlural(en)
if zh then return zh end
end
-- -ves结尾的额外测试一下复数,s/es/ies在模板内已经搞过了。
local matches = en:match('^(.+)ves$')
if matches then
m = stripArticle(matches) or matches -- 冠词还是要脱
--无冠词版本这里4个其实有重复,但不影响效率。
local t = m..'f'
if main_database[t] then return main_database[t] end
local t = m..'fe'
if main_database[t] then return main_database[t] end
local t = matches..'f'
if main_database[t] then return main_database[t] end
local t = matches..'fe'
if main_database[t] then return main_database[t] end
end
-- 其他复杂变体
zh = proc(en)
if zh then
-- 处理空格问题
zh = zh:gsub("%s+"," ")
zh = zh:gsub("%s*(%s*","(")
zh = zh:gsub("%s*)%s*",")")
zh = zh:gsub("!%s+","!")
zh = zh:gsub("?%s+","?")
zh = zh:match("^%s*(.-)%s*$")
return zh
end
-- 最后的fallback
return input
end }