Terraria Wiki
Advertisement

作为 Template:tr 的补充,为 Template:tr 提供深度扩展分析辅助,以及最终的fallback。


local database = mw.loadData( 'Module:Tc/db' )
local main_database = database.main
local prefix_database = database.prefix
local postfix_database = database.postfix

local input_frame --保存全局输入frame

-- 所有local函数,统一定义方便递归
local lookup, stripPlural, stripArticle, tcBasic, procPrefix, procPostfix, procNumberPostfix

--查表
function lookup(...)
	for _,en in ipairs({...}) do
	 if main_database[en] then return main_database[en] end
	end
end

-- 脱复数,返回各种潜在的可能复数
function stripPlural(str)
	if not str then 
		return 
	end
	local result = {}
	local matches
	--匹配要按长度逆序,降低重复查表数量。
	matches = str:match('^(.+)ies$')
	if matches then
		table.insert(result, matches..'y')
	else
		--和上一个匹配互斥,放在else可以省点事
		matches = str:match('^(.+)ves$')
		if matches then
			table.insert(result, matches..'f')
			table.insert(result, matches..'fe')
		end
	end
	matches = str:match('^(.+)es$')
	if matches then
		table.insert(result, matches)
	end
	matches = str:match('^(.+)s$')
	if matches then
		table.insert(result, matches)
	end
	return unpack(result)
end

-- 脱冠词 成功脱掉返回脱掉后的文本,失败nil
function stripArticle(str)
	return str:match('^the%s+(.+)$') or str:match('^an?%s+(.+)$')
end

-- 基本:冠词/复数。
function tcBasic(en)
	local main = stripArticle(en)
	if main then
		--有冠词
		return lookup(en) or lookup(main) or lookup(stripPlural(main)) or lookup(stripPlural(en)) 
	else
		--无冠词
		return lookup(en) or lookup(stripPlural(en)) 
	end
end

--尝试处理前缀
function procPrefix(en)
	en = stripArticle(en) or en --预脱冠词,否则前缀分析没意义
	-- 考虑前缀
	local prefix, main = en:match('^(%S+)%s+(.+)$')
	if main then
		local prefix_zh = prefix_database[prefix] or tcBasic(prefix)
		if prefix_zh then
			--注意顺序,前后缀优先交错进行。
			local zh = tcBasic(main) or procNumberPostfix(main) or procPostfix(main) or procPrefix(main)
			if zh then 
				return prefix_zh..zh
			end
		end
	end
end

--尝试处理后缀
function procPostfix(en)
	--先解析后缀
	local main, postfix, postfix_zh
	--标准后缀
	main, postfix = en:match('^(.-)%s+([%w%d]+)$')
	if main then
		postfix_zh = postfix_database[postfix] or tcBasic(postfix)
	else
		--标准后缀匹配不成功,再试试括号后缀
		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
	end
	--加上前面主体部分
	if postfix_zh then
		--注意顺序,前后缀优先交错进行。
		local zh = tcBasic(main) or procNumberPostfix(main) or procPrefix(main) or procPostfix(main)
		if zh then
			return zh..postfix_zh
		end
	end
end

-- 尝试去掉数字后缀,然后再次尝试做处理。
function procNumberPostfix(en)
	local main, number = en:match('^(.-)%s+(%d+)$')
	if main then
		zh = tcBasic(main) or procPostfix(main) or procPrefix(main) --前面还是要尝试基本款翻译,以应对 block 2 这样的情况
		if zh then
			return zh..' '..number..' ' --中文和数字之间空格,
		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内的缺失
	if stripArticle(en) then
		lookup(stripPlural(en))
	end
	-- -ves结尾的额外测试一下复数
	local matches = en:match('^(.+)ves$')
	if matches then
		m = stripArticle(matches) or matches -- 冠词还是要脱
		zh = lookup(m..'f', m..'fe', matches..'f', matches..'fe') --无冠词版本这里有重复,但不影响效率。
		if zh then return zh end
	end
	-- 其他复杂变体
	zh = procNumberPostfix(en) or procPostfix(en) or procPrefix(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 }
Advertisement