模組:Och-pron

維基詞典,自由的多語言詞典

這是上古漢語的發音模塊。請參見{{zh-pron}}。資料儲存於Module:zh/data/och-pron-BSModule:zh/data/och-pron-ZS及他們的子頁面中。


-- @see [[en:Module:och-pron]]
local export = {}

local colour_1 = "#ccece6"
local colour_2 = "#E0F3F3"
local colour_3 = "#F7FCFB"

local function zh_fmt(text)
	return text ~= "" and '<span class="Hani" lang="zh">' .. text .. '</span>' or ""
end

local function insert_pron(reading_temp, text, system, i, return_note, index)
	reading_temp = mw.ustring.gsub(reading_temp, "([̥̊]) ", "%1")
	part = mw.text.split(reading_temp, " ")
	IPA = mw.ustring.gsub(part[1], "^\*", "")
	table.remove(part, 1)
	return ((i == 1 and (mw.ustring.len(text) == 1 or (index or 1) == 1)) and "/*" or "") .. IPA .. 
		(mw.ustring.len(text) == i and "/" or "") ..
		((#part > 0 and return_note) and (" " .. table.concat(part, " ")) or "")
end

local function pron_table(titlechar, reading, system, reading_index, count, i)
	return system == "BS"
		-- 與 local fields = {...} 一對一對應。
		and {
			nil,
			-- [[Special:PermanentLink/6736383#該如何使其不轉換]] 在一些漢字條目,如:[[圣]]、[[袜]],有時出現的上古、中古發音,裡頭的簡體字會被轉換,使其不轉換。
			'<b>' .. zh_fmt('-{' .. titlechar .. '}-') .. '</b>',
			reading_index .. "/" .. count,
			reading[1],
			'‹ <i>' .. mw.ustring.gsub(reading[2], '([XH])', '<sup>%1</sup>') .. '</i> ›',
			'<span class="IPAchar">' .. mw.ustring.gsub(insert_pron(reading[3], titlechar, "BS", 1, true), "ˤ", "ˁ") .. '</span>',
			reading[4]
		}
		
		-- system == "ZS"
		-- 與 local fields = {...} 一對一對應。
		or {
			nil,
			-- [[Special:PermanentLink/6736383#該如何使其不轉換]] 在一些漢字條目,如:[[圣]]、[[袜]],有時出現的上古、中古發音,裡頭的簡體字會被轉換,使其不轉換。
			'<b>' .. zh_fmt('-{' .. titlechar .. '}-') .. '</b>',
			reading_index .. "/" .. count,
			reading[1],
			zh_fmt("[[" .. reading[2] .. "|-{" .. reading[2] .. "}-]]"),
			zh_fmt("[[" .. reading[3] .. "|-{" .. reading[3] .. "}-]]"),
			reading[4],
			zh_fmt("[[" .. reading[5] .. "|-{" .. reading[5] .. "}-]]"),
			'<span class="IPAchar">/*' .. reading[6] .. '/</span>',
			mw.ustring.gsub(mw.ustring.gsub(reading[7], "([一-鿌㐀-䶵𠀀-𬺯,]+)", zh_fmt("%1")), "([一-鿌㐀-䶵𠀀-𬺯])", "[[%1]]")
		}
end

function export.ipa(index_text, preview)
	local titlechar = mw.title.getCurrentTitle().text
	local reading_index = mw.text.split(index_text, ";")
	local output_text = {}
	local systems = { "BS", "ZS" }
	local indiv_pronunciation = { ["BS"] = {}, ["ZS"] = {} }
	local rand = ""

	-- 與 pron_table() 一對一對應。
	local fields = {
		
		["BS"] = {
			"[[w:白一平|白一平]]–[[w:沙加爾|沙加爾]]系統1.1 " ..
				"([http://ocbaxtersagart.lsait.lsa.umich.edu/ 2014])",
			"<small>字</small>",
			"<small>讀音 #</small>",
			"<small>現代北京音<br/>(拼音)</small>",
			"<small>構擬中古音</small>",
			"<small>構擬上古音</small>",
			"<small>英語翻譯</small>"
		},
	
		["ZS"] = {
			"[[w:鄭張尚芳|鄭張]]系統 (2003)",
			"<small>字</small>",
			"<small>讀音 #</small>",
			"<small>序號</small>",
			"<small>聲符</small>",
			"<small>韻部</small>",
			"<small>小分部</small>",
			"<small>對應中古韻</small>",
			"<small>構擬上古音</small>",
			"<small>注釋</small>"
		}
	}
	
	for system_seq, system in ipairs(systems) do
		for i, cp in ipairs { mw.ustring.codepoint(titlechar, 1, -1) } do
			local ch = mw.ustring.char(cp)
			local success, data_module = pcall(mw.loadData, "Module:zh/data/och-pron-" .. system .. "/" .. ch)
			if success then
				count = 0
				for index, value in ipairs(data_module) do
					count = count + 1
				end
				reading_number = reading_index[i] and (mw.text.split(reading_index[i], ',')[system_seq] or reading_index[i]) or "y"
				if reading_number == "y" then
					for reading_index, reading in ipairs(data_module) do
						table.insert(indiv_pronunciation[system], pron_table(ch, reading, system, reading_index, count, i))
					end
				elseif reading_number == "n" then
					break
				else
					for indiv_number in mw.text.gsplit(reading_number, '\+') do
						table.insert(indiv_pronunciation[system], pron_table(ch, data_module[tonumber(indiv_number)], system, indiv_number, count, i))
					end
				end
			end
		end
		if indiv_pronunciation[system][1] then
			local hash, results = {}, {}
			local value_eff
			for _, value in ipairs(indiv_pronunciation[system]) do
				local valeur = value
				table.remove(valeur, 1)
				value_eff = table.concat(valeur)
				if not hash[value_eff] then
					hash[value_eff] = true
					table.insert(value, 1, nil)
					results[#results + 1] = value
				end
			end
			rand = rand ~= "" and rand or mw.ustring.gsub("oc-" .. value_eff, "[^A-Za-z0-9]", mw.ustring.codepoint)
			local fmt = {
				header = '\n{| class="wikitable mw-collapsible mw-collapsed" id="mw-customcollapsible-oc' .. rand ..
					'" style="width:100%; margin:0; text-align:center; border-collapse: collapse; border-style: hidden;"',
				lv1 = '\n|-\n! style="background-color:' .. colour_1 .. '" colspan=' .. #results+1 .. '|',
				lv2 = '\n|-\n! style="background-color:' .. colour_2 .. '; width:8em"|',
				lv3 = '\n| style="background-color:' .. colour_3 .. '"|',
				closing = '\n|}',
				
				BS_note = '\n|-\n|colspan=' .. #results+1 ..
					[=[ style="text-align:left; font-size:90%"|<div class="toccolours mw-collapsible mw-collapsed">
					'''來自白一平–沙加爾系統的上古漢語標註筆記:'''
					<div class="mw-collapsible-content">
					* 圓括號 "()" 表示存在不確定;<br>
					* 方括號 "[]" 表示身分不確定,例如 *[t] 的尾音有可能是 *-t 或 *-p;<br>
					* 尖角括號 "&lt;>" 表示接中辭;<br>
					* 連字號 "-" 表示語素範圍;<br>
					* 句號 "." 表示音節範圍。</div>
					</div>]=]
			}
		
			table.insert(output_text, fmt.header)
			for field_index, field in ipairs(fields[system]) do
				if mw.ustring.match(field, "small") then
					local field_set = {}
					for _, result in ipairs(results) do
						table.insert(field_set, result[field_index])
					end
					if table.concat(field_set) ~= "" then
						table.insert(output_text, fmt.lv2 .. field .. fmt.lv3 .. table.concat(field_set, fmt.lv3))
					end
				else
					table.insert(output_text, fmt.lv1 .. field)
				end
			end
			table.insert(output_text, (system == "BS" and fmt.BS_note or "") .. fmt.closing)
		end
		fold = '\n* <div title="expand" class="mw-customtoggle-oc' .. rand .. '"> ' ..
			'[[w:上古漢語|上古]]<span style="float:right; border:1px solid #ccc; border-radius:1px;' ..
			' padding:0 0; font-size:90%">▼</span>' .. preview .. '</div>'
	end
	return output_text[1] and fold .. mw.ustring.gsub(table.concat(output_text), "%[%[%]%]", "") or ""
end

function export.retrieve_pron(text, reconstruction, no_intro, index)
	if type(text) == "table" then text = text.args[1] end
	text = require("Module:links").remove_links(text)
	local retrieve_result = {}
	local intro = no_intro and "" or "<span lang=\"Latn\" style=\"border-bottom: 1px dotted #000; cursor:help\" title=\"上古漢語\">OC</span> "
	if not reconstruction then
		if index and index ~= "y" then
			index_set = mw.text.split(index, ",")
		end
		for char_index, cp in ipairs { mw.ustring.codepoint(text, 1, -1) } do
			local char_pronunciation = {}
			local ch = mw.ustring.char(cp)
			local success, data_module = pcall(mw.loadData, "Module:zh/data/och-pron-ZS/" .. ch)
			if success then
				local reading_no = index_set and index_set[char_index] or "y"
				if reading_no ~= "y" then
					for number in mw.text.gsplit(reading_no, "+") do
						table.insert(char_pronunciation, data_module[tonumber(number)][6])
					end
				else
					for _, reading in ipairs(data_module) do
						table.insert(char_pronunciation, reading[6])
					end
				end
			else
				return nil
			end
			table.insert(retrieve_result, table.concat(char_pronunciation, mw.ustring.len(text) == 1 and ", *" or "/"))
		end
	end
	return intro .. "<span lang=\"Latn\">" .. (reconstruction or "*" .. table.concat(retrieve_result, " ")) .. "</span>"
end

function export.generate_show(text, index)
	local index_set = mw.text.split(index, ";")
	local extract_results = { ["BS"] = {}, ["ZS"] = {} }
	local result = {}
	local position = { ["BS"] = 3, ["ZS"] = 6 }
	
	local fmt = {
		beginning = {
			["BS"] = "\n*: <small>([[w:白一平|白]]–[[w:沙加爾|沙]])</small>:" ..
				'<span style="font-size:95%">',
			["ZS"] = "\n*: <small>([[w:鄭張尚芳|鄭張]])</small>:" ..
				'<span style="font-size:95%">',
		},
		ending = {
			["BS"] = "</span>", ["ZS"] = "</span>"
		}
	}
	
	for system_seq, system in ipairs({ "BS", "ZS" }) do
		for i, cp in ipairs { mw.ustring.codepoint(text, 1, -1) } do
			local char_pronunciation = {}
			local ch = mw.ustring.char(cp)
			local success, data_module = pcall(mw.loadData, "Module:zh/data/och-pron-" .. system .. "/" .. ch)
			if success then
				local existing_pron = {}
				reading_number = index_set[i] and (mw.text.split(index_set[i], ',')[system_seq] or index_set[i]) or "y"
				if reading_number == "y" then
					index = 0
					for _, reading in ipairs(data_module) do
						index = index + 1
						local reading_temp = reading[position[system]]
						if not existing_pron[reading_temp] then
							table.insert(char_pronunciation, insert_pron(reading_temp, text, system, i, false, index))
							existing_pron[reading_temp] = true
						end
					end
				elseif reading_number == "n" then
					break
				else
					index = 0
					for indiv_number in mw.text.gsplit(reading_number, '\+') do
						index = index + 1
						local reading_temp = data_module[tonumber(indiv_number)][position[system]]
						if not existing_pron[reading_temp] then
							table.insert(char_pronunciation, insert_pron(reading_temp, text, system, i, false, index))
							existing_pron[reading_temp] = true
						end
					end
				end
				table.insert(extract_results[system], table.concat(char_pronunciation, mw.ustring.len(text) == 1 and ", " or "|"))
			else
				extract_results[system] = {}
				break
			end
		end
		if extract_results[system][1] then
			table.insert(result, fmt.beginning[system] .. 
				'<span class="IPAchar">' .. 
				table.concat(extract_results[system], "&nbsp; ") .. 
				 '</span>' .. 
				 fmt.ending[system])
		end
	end
	text = result[1] and mw.ustring.gsub(table.concat(result), "|%*", "|") or nil
	text = text and mw.ustring.gsub(text, "/|", "|") or nil
	text = text and mw.ustring.gsub(text, "|", '<span style="padding-left:2px; padding-right:2px">|</span>')
	return text
end

function export.link(frame, arg)
	local args = arg or frame:getParent().args
	text, meaning, lit = args[1], args[2] or args['gloss'] or nil, args['lit'] or nil
	return require("Module:zh/link").link(frame, nil, { "*" .. text, tr = export.retrieve_pron(text, args["tr"] or false, args["no_intro"] or false, args["id"] or false), gloss = meaning, lit = lit }, mw.title.getCurrentTitle().subpageText)
end

return export